From 43b2edcbb55d9ddee2ffe6d6672e1e6b139c3a60 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Wed, 27 May 2026 08:56:28 -0400 Subject: [PATCH] =?UTF-8?q?@=20docs(billing):=20session=20handoff=20?= =?UTF-8?q?=E2=80=94=20core=20on=20main,=20sub-project=20#2=20(NexaCloud)?= =?UTF-8?q?=20next?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Captures resume state for the centralized-billing initiative: core engine done and on main, the 4-chunk decomposition of sub-project #2 (NexaCloud adapter + dual-run reconciliation), the pending "where to start" decision, open questions, and the test/branch workflow. Co-Authored-By: Claude Opus 4.7 (1M context) @ --- ...26-05-27-fusion-billing-session-handoff.md | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 docs/superpowers/2026-05-27-fusion-billing-session-handoff.md 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.