wulf-pulse/.planning/quick/260718-9qg-create-a-quickbooks-online-integration-h/260718-9qg-SUMMARY.md
lorentz a65b29055c docs(quick-260718-9qg): complete QBO integration handoff quick task
Records the plan, execution summary, and STATE.md quick-task log entry
for the QBO_INTEGRATION_HANDOFF.md doc committed in ea8a36b.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6RuWdiUiXrPK6FLBHjtpY
2026-07-18 07:08:29 -04:00

5.8 KiB

phase plan subsystem tags requires provides affects tech-stack key-files key-decisions requirements-completed duration completed
quick-260718-9qg 01 docs
quickbooks
qbo
oauth2
integration
handoff
finance
QBO_INTEGRATION_HANDOFF.md — self-contained OAuth2/token/API/gotchas reference for QuickBooks Online, written for a team with no access to Pulse's codebase
any future work building or maintaining a QBO integration in a different app
added patterns
created modified
QBO_INTEGRATION_HANDOFF.md
Inlined every detail (env vars, exact Intuit URLs, table schemas, request/response shapes) rather than pointing at Pulse source files, per the plan's self-containment requirement
Called out two real defects found during investigation as explicit gotchas rather than silently working around them: unverified OAuth `state` (CSRF gap) and the legacy `NEXTAUTH_URL` env var used for the redirect URI instead of Pulse's actual BETTER_AUTH_URL
Used placeholder values for all env var examples — no real secrets existed in .env for QBO_* keys to begin with, so nothing needed redaction
DOC-QBO-HANDOFF
25min 2026-07-18

Phase quick-260718-9qg Plan 01: QBO Integration Handoff Doc Summary

Self-contained QBO_INTEGRATION_HANDOFF.md covering QBO's OAuth2 authorization-code flow, token storage/refresh schema, sandbox vs production API base URLs, minor-version pinning, and 11 concrete gotchas (deletion-diffing, CSRF state, report NoReportData markers, check-number normalization, idempotency, etc.) drawn from Pulse's actual QBO source and its recent AR-reconciliation fix.

Performance

  • Duration: ~25 min
  • Started: 2026-07-18T11:00:00Z (approx.)
  • Completed: 2026-07-18T11:25:00Z (approx.)
  • Tasks: 1
  • Files modified: 1 (new file)

Accomplishments

  • Investigated Pulse's real QBO integration end to end: lib/services/qbo-client.ts, lib/services/qbo-sync-service.ts, all four app/api/qbo/* routes, migrations/051_create_qbo_tables.sql, migrations/088_qbo_invoices_soft_delete.sql, middleware.ts public-route list, integration-health.ts config check, git history (b98c674, ef9b31e, 672f17b), and the 260519-0oz quick-task SUMMARY for the createPayment/createDeposit work.
  • Wrote QBO_INTEGRATION_HANDOFF.md (596 lines) at the repo root with all required sections: Overview, Prerequisites, Environment variables (table), OAuth2 connection flow (11-step numbered walkthrough with exact Intuit URLs), Token storage & refresh (generalized schema + pseudocode), API usage (base URLs, path shape, minorversion, query/write/report examples), Gotchas & lessons learned (11 concrete items), and a framework-agnostic TypeScript pseudocode code-flow example.
  • Surfaced two real defects discovered during investigation as explicit gotchas for the new team to avoid repeating: (1) Pulse's OAuth state value is generated but never persisted/verified on callback — a real CSRF gap; (2) the redirect-URI base URL is read from NEXTAUTH_URL, a variable not present anywhere in Pulse's .env/.env.local (a legacy holdover from a prior auth library), distinct from the app's actual BETTER_AUTH_URL.

Task Commits

Each task was committed atomically:

  1. Task 1: Investigate Pulse's QBO integration and write the self-contained handoff doc - ea8a36b (docs)

Plan metadata: (this commit, made after SUMMARY.md)

Files Created/Modified

  • QBO_INTEGRATION_HANDOFF.md - Self-contained QBO integration handoff document (overview, prerequisites, env vars, OAuth2 flow, token storage/refresh, API usage, gotchas, code-flow example)

Decisions Made

  • Inlined every Pulse-derived detail directly into the doc (no bare see lib/services/qbo-client.ts pointers); Pulse file paths appear only as parenthetical provenance notes.
  • Documented the NEXTAUTH_URL / BETTER_AUTH_URL mismatch and the unverified OAuth state as explicit "don't repeat this" gotchas rather than omitting them, since the plan's objective is transferring hard-won (including negative) knowledge to a new team.
  • Recommended crypto.randomUUID() (or a signed token) plus server-side verification in place of Pulse's current Math.random()-based state, and recommended adding an explicit Intuit token-revocation call for a real "disconnect," since a new implementation should start from a stronger baseline than Pulse's current code.

Deviations from Plan

None - plan executed exactly as written. This was a docs-only investigation-and-write task; no application source, migrations, env files, or existing docs were touched (confirmed via git status --short, which shows only QBO_INTEGRATION_HANDOFF.md as an addition).

Issues Encountered

None.

User Setup Required

None - no external service configuration required. This task only produced a reference document; it does not change any running behavior.

Next Phase Readiness

  • QBO_INTEGRATION_HANDOFF.md is ready to be handed directly to the new application's engineering team.
  • No blockers. If the new team later reports gaps (e.g. QBO Payments/charge-card scope, multi-realm support), a follow-up quick task can extend this document — it was intentionally scoped to what Pulse's own integration actually covers (accounting scope only, single realm).

Self-Check: PASSED

  • QBO_INTEGRATION_HANDOFF.md exists at repo root — FOUND
  • Automated verify command (test -f ... && line count >= 100 && grep oauth/refresh/sandbox|production) — PASSED (OK)
  • Commit ea8a36b exists in git log — FOUND
  • git status --short shows only QBO_INTEGRATION_HANDOFF.md as a tracked addition (plus the pre-existing untracked .planning/quick/260718-9qg-.../ plan directory, unrelated to source/docs/migrations) — CONFIRMED

Phase: quick-260718-9qg Completed: 2026-07-18