diff --git a/docs/superpowers/2026-05-27-fusion-billing-session-handoff.md b/docs/superpowers/2026-05-27-fusion-billing-session-handoff.md new file mode 100644 index 00000000..d4ae7c85 --- /dev/null +++ b/docs/superpowers/2026-05-27-fusion-billing-session-handoff.md @@ -0,0 +1,75 @@ +# fusion_centralize_billing — Session Handoff (2026-05-27) + +Resume point for the centralized-billing initiative. Read this first, then continue +from **"Decision pending"** below. + +## Where we are + +- **Sub-project #1 (core billing engine): DONE and on `main`** (tip `d770c0c3`, pushed to + GitHub + Gitea). + - 11/11 plan tasks, TDD, Opus code-reviewed; all Critical/High bugs fixed + (cross-billing cron → match by `plan_id`; `/usage` authz vs IDOR; input validation → + 4xx not 500; correct billing-period window; idempotency scoped to `(sub, metric, key)`; + webhook sign-exact-bytes + event-id + SSRF guard). + - **39 tests green on Odoo 19 Enterprise.** + - Note: the 14 billing commits were rebased off the old login-audit/helpdesk stack and + landed cleanly on `main`. `fusion_login_audit` was deliberately **not** landed — it + stays on `feat/fusion-login-audit`. A concurrent `feat/helpdesk-customer-followup` + session still carries a pre-landing copy of the billing commits; when it merges, replay + its helpdesk-only commits onto `main`. + +- **Reference docs (on `main`):** + - Spec: `docs/superpowers/specs/2026-05-27-nexa-billing-centralized-design.md` + - Core plan: `docs/superpowers/plans/2026-05-27-fusion-centralize-billing-core.md` + +## Next: sub-project #2 — NexaCloud adapter + dual-run reconciliation + +Per spec §12, each sub-project is its own spec → plan → build cycle. #2 decomposes into +four chunks (dependency order): + +| Chunk | What | Risk | +|-------|------|------| +| **2a — Mapping + importer** | Read `nexacloud` DB → create `res.partner` + `account.link`, `product.template` + subscription plans, one subscription `sale.order` per deployment | **Low** — read-only on NexaCloud, writes only into Odoo | +| **2b — Usage metering wiring** | NexaCloud `usage_metering.py` pushes CPU-seconds → Odoo `/usage`; verify aggregation → draft invoice w/ quota + overage + HST | Edits NexaCloud code | +| **2c — Control loop** | NexaCloud consumes Odoo's outbound webhooks (`invoice.payment_failed` → suspend via existing `network_isolation`/`throttle_checker`; `subscription.terminated` → deprovision) | Edits NexaCloud code | +| **2d — Dual-run reconciliation** | `fusion.billing.reconciliation` diffs Odoo-computed vs NexaCloud-actual per customer/period for ≥ 1 cycle before any flip | Safety gate before flipping real billing | + +The core engine already built the *receiving* side (`/usage`, webhook engine, charge math). +#2 is about **connecting NexaCloud to it and proving the numbers match before flipping.** + +## Decision pending (resume here) + +We were in the `superpowers:brainstorming` flow for #2 and stopped at: **which slice to +start with?** + +- **(recommended) 2a — Mapping + importer** — lowest risk, foundation for everything else. +- 2d — Reconciliation first (front-load the trust mechanism). +- Full #2 design as one spec, then one plan. +- Just write the #2 plan, no code this session. + +## Open questions to resolve before building #2 + +- **Spec §15 Q2 — NexaCloud billing granularity:** confirm **one subscription per + deployment** (spec leans this way) vs one subscription per customer with deployment line + items. +- **Access / environments needed:** + - Read access to the `nexacloud` DB schema (LXC 102 / its Postgres on LXC 201) to design + the importer mapping. + - A NexaCloud staging or safe path for 2b/2c (they edit live NexaCloud code). + - Test target for the Odoo side stays the odoo-trial Enterprise sandbox. +- **Resolved already:** Stripe is one account (`acct_1ShlA9IkwUB1dVox`) for everything — no + account migration (spec §11 / §15 Q1). Branch strategy — land on `main`, branch new work + off `main`. + +## How to run / test + +- **Billing tests:** `bash scripts/fcb_test_on_trial.sh` from repo root → pass = `FCB_EXIT=0` + (~1–2 min). Syncs the module to the odoo-trial Enterprise sandbox (Proxmox VM 316, db + `trial`) and runs `--test-enable`. Local dev Odoo is Community and **cannot** install this + module. + +## Branch hygiene (lesson from this session) + +Cut each new feature branch from `main`, and land it before starting the next. For any +cross-branch git surgery, use a **throwaway `git worktree`** — never switch the shared +working dir's branch, because a concurrent session may be working on it.