openvibers/openvibe.billing Commits
Docs: STATUS.json and README match production (2026-09-23)
Changes
@@@ -2,8 +2,10 @@> The isolated money ledger: providers, receipts, subscriptions, entitlements, refunds and payouts.--**Status:** alpha — runtime built and tested (Wave 8); OpenVibe.Live stays authoritative until the--cutover below is run.++**Status:** alpha — runtime built and tested (Wave 8). Deployed on the host in **shadow** mode++since 2026-09-23 (`/opt/openvibe.billing`, API on `127.0.0.1:4600`): no provider secret is configured,++it holds a reconciled import of a Live snapshot, and OpenVibe.Live stays the money authority++(`BILLING_AUTHORITY` is not set in Live) until the cutover below is run. The cutover has not been run.**Domain:** `billing.openvibe.network` — the staff console (Network SSO, staff only), `/webhooks/*` and`/api/health`; the service API `/api/v1` is reachable only on loopback (`127.0.0.1:4600`)**Decision:** [ADR-012](https://github.com/OpenVibers/OpenVibe.Contracts/blob/main/docs/adr/ADR-012-economic-classification.md) —@@@ -104,10 +106,11 @@ are not stored. Errors are RFC 9457 problem+json. People are SubjectRefs `{ "typ| `POST /api/v1/admin/sweep`, `GET /api/v1/admin/import-holds` | `billing.ledger.admin` | renewal sweep now; unmapped import users || `POST /webhooks/<provider>` | provider signature | `powerchat`, `stripe`, `paypal`, `ccbill` (GET too), `nowpayments` |--Capabilities are proposed in [docs/capabilities-proposal/](docs/capabilities-proposal/) with a service--manifest in [docs/service-manifest-proposal.json](docs/service-manifest-proposal.json). Until they--ship in an openvibe-contracts release, grants are matched locally (exact id or a `.*` family such as--`billing.*`) with contracts' own `capabilities.grants()`.++The capabilities and the service manifest are released in openvibe-contracts (v0.8.0;++`billing.staff.action` since v0.17.0); the drafts they came from stay in++[docs/capabilities-proposal/](docs/capabilities-proposal/) and++[docs/service-manifest-proposal.json](docs/service-manifest-proposal.json). Grants are matched with++contracts' own `capabilities.grants()` (exact id or a `.*` family such as `billing.*`).## Staff console@@@ -196,9 +199,11 @@ Reversing a subscription payment revokes the periods it granted.## Cutover runbook (Live → Billing)The exact production sequence, rollback, grants and the Live behaviour the switch cannot preserve are in--[docs/live-cutover.md](docs/live-cutover.md); the Live side is the patch--[docs/live-patch.diff](docs/live-patch.diff) (a `BILLING_AUTHORITY=live|billing` switch, `live` by default,--plus the `money_writes_frozen` freeze). In short:++[docs/live-cutover.md](docs/live-cutover.md); the Live side (a `BILLING_AUTHORITY=live|billing` switch,++`live` by default, plus the `money_writes_frozen` freeze) was the patch++[docs/live-patch.diff](docs/live-patch.diff) and is deployed in OpenVibe.Live since `c384787` with the++switch unset. None of the steps below has been executed yet; step 3 needs the owner (PowerChat++dashboard). In short:1. **Shadow import** as often as needed (`node scripts/import-live.js --live-db <snapshot> [--dry-run]`);map held users in the Network and explain every adjustment until reconciliation is clean.@@@ -215,14 +220,15 @@ Billing did itself.## Launch rule--The domain keeps its placeholder page on--[OpenVibers/OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) until everything in plan §12.12--holds: owning runtime with health/readiness ✔; canonical identity and scoped service principals ✔;--server-rendered public routes useful without JavaScript (not yet — the only pages are the staff-only--console);--real persistence and end-to-end workflows ✔; capability/event registration against--OpenVibe.Contracts (proposed, not released); migration strategy ✔ with a security review, sitemap/robots--still to do; acceptance tests ✔. A placeholder is never counted as an implemented service.++`billing.openvibe.network` left OpenVibe.Sites on 2026-09-23: it serves the staff console only. Billing++is not a public product and is not the money authority until the cutover above and everything in plan++§12.12 holds: owning runtime with health/readiness ✔ (`/metrics` not yet); canonical identity and++scoped service principals ✔ (principal `billing`); server-rendered public routes useful without++JavaScript (not yet — the only pages are the staff-only console); real persistence and end-to-end++workflows ✔ in tests, shadow only in production; capability/event registration against++OpenVibe.Contracts ✔ (v0.8.0); migration strategy ✔ (shadow import reconciles; restore drill passed++2026-09-23) with a security review, sitemap/robots still to do; acceptance tests ✔. A shadow deployment++is never counted as the money authority.---@@@ -6,6 +6,7 @@"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)","adr": "ADR-012","authoritative": false,-- "notes": "Runtime, journal, adapters, import, reconciliation and the staff console (Network SSO + PKCE, admins listed in BILLING_STAFF_SUBJECTS; cashout approve/deny, review queue, reconciliation, freeze, audit log) are built and tested. The console needs the Network to add https://billing.openvibe.network/auth/callback to client `billing` before anyone can sign in. The Live client is a patch (docs/live-patch.diff, switch BILLING_AUTHORITY off by default) with its cutover sequence in docs/live-cutover.md; the cutover has not been executed, so Live stays authoritative.",-- "updated": "2026-09-22"++ "deployment": "Deployed in shadow on openvibe-ovh: /opt/openvibe.billing (release b59725e), unit openvibe-billing, API on 127.0.0.1:4600 (loopback only; /api/v1 is denied on the public host). Public at https://billing.openvibe.network: the staff console (Network SSO + PKCE, BILLING_STAFF_SUBJECTS = the owner only), /api/health and /webhooks/*. No provider secret is configured, so every provider is off and /webhooks/* answers 404 billing.provider_disabled. Pins openvibe-contracts v0.19.0.",++ "notes": "Runtime, journal, adapters, import, reconciliation and the staff console (cashout approve/deny, review queue, reconciliation, freeze, audit log) are built and tested. Capabilities (8 billing.*) and events are registered in OpenVibe.Contracts (v0.8.0; billing.staff.action in v0.17.0). Production holds a shadow import of a Live snapshot (322 transactions: 304 imported plus 18 opening adjustments; 3 reconciliation runs, the last 2026-09-23 01:21 UTC, all checks ok), 0 subscriptions and 0 entitlements; the console has never been used (staff_audit 0). The restore drill passed on the host 2026-09-23 05:22 UTC. The Live side (Billing client behind BILLING_AUTHORITY, money freeze) is deployed in Live since c384787, but BILLING_AUTHORITY is not set in live.env, so Live stays the money authority. The cutover (README runbook, docs/live-cutover.md) has not been executed: it waits on the owner putting the PowerChat secret in billing.env and re-pointing the PowerChat webhook to https://billing.openvibe.network/webhooks/powerchat. Not done: /metrics (404), scheduled reconciliation, EXTERNAL PowerChat tips produce no event for Tips, payouts/refunds/plans are represented by cashouts, refund transactions and VIP plans rather than their own tables.",++ "updated": "2026-09-23"}@@@ -107,7 +107,7 @@ Shell helpers used below (on the host):# billing '<command>' runs one command with Billing's environment, as Billing's service user (ubuntu)# so the database files keep their owner — the same way the shadow imports were run.billing() { sudo bash -c "set -a; . /etc/openvibe/billing.env; set +a; export NODE_ENV=production BILLING_DB_PATH=/var/lib/openvibe-billing/billing.db; cd /opt/openvibe.billing && sudo -E -u ubuntu $1"; }--LIVE_DB=/opt/openvibe.live/shared/data/live.db++LIVE_DB=/opt/openvibe.live/data/live.db```Live owner calls are made from the browser console on openvibe.live, signed in as the owner:
@@ -2,8 +2,10 @@
@@ -2,8 +2,10 @@
> The isolated money ledger: providers, receipts, subscriptions, entitlements, refunds and payouts.
> The isolated money ledger: providers, receipts, subscriptions, entitlements, refunds and payouts.
-**Status:** alpha — runtime built and tested (Wave 8); OpenVibe.Live stays authoritative until the
-cutover below is run.
+**Status:** alpha — runtime built and tested (Wave 8). Deployed on the host in **shadow** mode
+since 2026-09-23 (`/opt/openvibe.billing`, API on `127.0.0.1:4600`): no provider secret is configured,
+it holds a reconciled import of a Live snapshot, and OpenVibe.Live stays the money authority
+(`BILLING_AUTHORITY` is not set in Live) until the cutover below is run. The cutover has not been run.
**Domain:** `billing.openvibe.network` — the staff console (Network SSO, staff only), `/webhooks/*` and
**Domain:** `billing.openvibe.network` — the staff console (Network SSO, staff only), `/webhooks/*` and
`/api/health`; the service API `/api/v1` is reachable only on loopback (`127.0.0.1:4600`)
`/api/health`; the service API `/api/v1` is reachable only on loopback (`127.0.0.1:4600`)
**Decision:** [ADR-012](https://github.com/OpenVibers/OpenVibe.Contracts/blob/main/docs/adr/ADR-012-economic-classification.md) —
**Decision:** [ADR-012](https://github.com/OpenVibers/OpenVibe.Contracts/blob/main/docs/adr/ADR-012-economic-classification.md) —
@@ -104,10 +106,11 @@ are not stored. Errors are RFC 9457 problem+json. People are SubjectRefs `{ "typ
@@ -104,10 +106,11 @@ are not stored. Errors are RFC 9457 problem+json. People are SubjectRefs `{ "typ
| `POST /api/v1/admin/sweep`, `GET /api/v1/admin/import-holds` | `billing.ledger.admin` | renewal sweep now; unmapped import users |
| `POST /api/v1/admin/sweep`, `GET /api/v1/admin/import-holds` | `billing.ledger.admin` | renewal sweep now; unmapped import users |
| `POST /webhooks/<provider>` | provider signature | `powerchat`, `stripe`, `paypal`, `ccbill` (GET too), `nowpayments` |
| `POST /webhooks/<provider>` | provider signature | `powerchat`, `stripe`, `paypal`, `ccbill` (GET too), `nowpayments` |
-Capabilities are proposed in [docs/capabilities-proposal/](docs/capabilities-proposal/) with a service
-manifest in [docs/service-manifest-proposal.json](docs/service-manifest-proposal.json). Until they
-ship in an openvibe-contracts release, grants are matched locally (exact id or a `.*` family such as
-`billing.*`) with contracts' own `capabilities.grants()`.
+The capabilities and the service manifest are released in openvibe-contracts (v0.8.0;
+`billing.staff.action` since v0.17.0); the drafts they came from stay in
+[docs/capabilities-proposal/](docs/capabilities-proposal/) and
+[docs/service-manifest-proposal.json](docs/service-manifest-proposal.json). Grants are matched with
+contracts' own `capabilities.grants()` (exact id or a `.*` family such as `billing.*`).
## Staff console
## Staff console
@@ -196,9 +199,11 @@ Reversing a subscription payment revokes the periods it granted.
@@ -196,9 +199,11 @@ Reversing a subscription payment revokes the periods it granted.
## Cutover runbook (Live → Billing)
## Cutover runbook (Live → Billing)
The exact production sequence, rollback, grants and the Live behaviour the switch cannot preserve are in
The exact production sequence, rollback, grants and the Live behaviour the switch cannot preserve are in
-[docs/live-cutover.md](docs/live-cutover.md); the Live side is the patch
-[docs/live-patch.diff](docs/live-patch.diff) (a `BILLING_AUTHORITY=live|billing` switch, `live` by default,
-plus the `money_writes_frozen` freeze). In short:
+[docs/live-cutover.md](docs/live-cutover.md); the Live side (a `BILLING_AUTHORITY=live|billing` switch,
+`live` by default, plus the `money_writes_frozen` freeze) was the patch
+[docs/live-patch.diff](docs/live-patch.diff) and is deployed in OpenVibe.Live since `c384787` with the
+switch unset. None of the steps below has been executed yet; step 3 needs the owner (PowerChat
+dashboard). In short:
1. **Shadow import** as often as needed (`node scripts/import-live.js --live-db <snapshot> [--dry-run]`);
1. **Shadow import** as often as needed (`node scripts/import-live.js --live-db <snapshot> [--dry-run]`);
map held users in the Network and explain every adjustment until reconciliation is clean.
map held users in the Network and explain every adjustment until reconciliation is clean.
@@ -215,14 +220,15 @@ Billing did itself.
@@ -215,14 +220,15 @@ Billing did itself.
## Launch rule
## Launch rule
-The domain keeps its placeholder page on
-[OpenVibers/OpenVibe.Sites](https://github.com/OpenVibers/OpenVibe.Sites) until everything in plan §12.12
-holds: owning runtime with health/readiness ✔; canonical identity and scoped service principals ✔;
-server-rendered public routes useful without JavaScript (not yet — the only pages are the staff-only
-console);
-real persistence and end-to-end workflows ✔; capability/event registration against
-OpenVibe.Contracts (proposed, not released); migration strategy ✔ with a security review, sitemap/robots
-still to do; acceptance tests ✔. A placeholder is never counted as an implemented service.
+`billing.openvibe.network` left OpenVibe.Sites on 2026-09-23: it serves the staff console only. Billing
+is not a public product and is not the money authority until the cutover above and everything in plan
+§12.12 holds: owning runtime with health/readiness ✔ (`/metrics` not yet); canonical identity and
+scoped service principals ✔ (principal `billing`); server-rendered public routes useful without
+JavaScript (not yet — the only pages are the staff-only console); real persistence and end-to-end
+workflows ✔ in tests, shadow only in production; capability/event registration against
+OpenVibe.Contracts ✔ (v0.8.0); migration strategy ✔ (shadow import reconciles; restore drill passed
+2026-09-23) with a security review, sitemap/robots still to do; acceptance tests ✔. A shadow deployment
+is never counted as the money authority.
---
---
@@ -6,6 +6,7 @@
@@ -6,6 +6,7 @@
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"adr": "ADR-012",
"adr": "ADR-012",
"authoritative": false,
"authoritative": false,
- "notes": "Runtime, journal, adapters, import, reconciliation and the staff console (Network SSO + PKCE, admins listed in BILLING_STAFF_SUBJECTS; cashout approve/deny, review queue, reconciliation, freeze, audit log) are built and tested. The console needs the Network to add https://billing.openvibe.network/auth/callback to client `billing` before anyone can sign in. The Live client is a patch (docs/live-patch.diff, switch BILLING_AUTHORITY off by default) with its cutover sequence in docs/live-cutover.md; the cutover has not been executed, so Live stays authoritative.",
- "updated": "2026-09-22"
+ "deployment": "Deployed in shadow on openvibe-ovh: /opt/openvibe.billing (release b59725e), unit openvibe-billing, API on 127.0.0.1:4600 (loopback only; /api/v1 is denied on the public host). Public at https://billing.openvibe.network: the staff console (Network SSO + PKCE, BILLING_STAFF_SUBJECTS = the owner only), /api/health and /webhooks/*. No provider secret is configured, so every provider is off and /webhooks/* answers 404 billing.provider_disabled. Pins openvibe-contracts v0.19.0.",
+ "notes": "Runtime, journal, adapters, import, reconciliation and the staff console (cashout approve/deny, review queue, reconciliation, freeze, audit log) are built and tested. Capabilities (8 billing.*) and events are registered in OpenVibe.Contracts (v0.8.0; billing.staff.action in v0.17.0). Production holds a shadow import of a Live snapshot (322 transactions: 304 imported plus 18 opening adjustments; 3 reconciliation runs, the last 2026-09-23 01:21 UTC, all checks ok), 0 subscriptions and 0 entitlements; the console has never been used (staff_audit 0). The restore drill passed on the host 2026-09-23 05:22 UTC. The Live side (Billing client behind BILLING_AUTHORITY, money freeze) is deployed in Live since c384787, but BILLING_AUTHORITY is not set in live.env, so Live stays the money authority. The cutover (README runbook, docs/live-cutover.md) has not been executed: it waits on the owner putting the PowerChat secret in billing.env and re-pointing the PowerChat webhook to https://billing.openvibe.network/webhooks/powerchat. Not done: /metrics (404), scheduled reconciliation, EXTERNAL PowerChat tips produce no event for Tips, payouts/refunds/plans are represented by cashouts, refund transactions and VIP plans rather than their own tables.",
+ "updated": "2026-09-23"
}
}
@@ -107,7 +107,7 @@ Shell helpers used below (on the host):
@@ -107,7 +107,7 @@ Shell helpers used below (on the host):
# billing '<command>' runs one command with Billing's environment, as Billing's service user (ubuntu)
# billing '<command>' runs one command with Billing's environment, as Billing's service user (ubuntu)
# so the database files keep their owner — the same way the shadow imports were run.
# so the database files keep their owner — the same way the shadow imports were run.
billing() { sudo bash -c "set -a; . /etc/openvibe/billing.env; set +a; export NODE_ENV=production BILLING_DB_PATH=/var/lib/openvibe-billing/billing.db; cd /opt/openvibe.billing && sudo -E -u ubuntu $1"; }
billing() { sudo bash -c "set -a; . /etc/openvibe/billing.env; set +a; export NODE_ENV=production BILLING_DB_PATH=/var/lib/openvibe-billing/billing.db; cd /opt/openvibe.billing && sudo -E -u ubuntu $1"; }
-LIVE_DB=/opt/openvibe.live/shared/data/live.db
+LIVE_DB=/opt/openvibe.live/data/live.db
```
```
Live owner calls are made from the browser console on openvibe.live, signed in as the owner:
Live owner calls are made from the browser console on openvibe.live, signed in as the owner: