openvibers/openvibe.billing Commits
openvibe-sdk v0.117.0 (was v0.94.0) (#236)
Changes
@@@ -66,7 +66,7 @@ promo write changes both in one transaction.- OpenVibe.Network (JWKS for service tokens; SSO with PKCE for the staff console; `identity.subject.resolve` for the Live import)- OpenVibe.Events (the SDK outbox relay, when `EVENTS_URL` and the OAuth client secret are set)- the payment providers whose secrets are configured (none in production today)--- `openvibe-contracts` v0.338.0, `openvibe-sdk` v0.94.0 (service tokens, per-person limits, `openvibe-sdk/db`, `openvibe-sdk/service`, `openvibe-sdk/vibes`), `openvibe-shared` v4.168.0, pinned by release tarball++- `openvibe-contracts` v0.338.0, `openvibe-sdk` v0.117.0 (service tokens, per-person limits, `openvibe-sdk/db`, `openvibe-sdk/service`, `openvibe-sdk/vibes`), `openvibe-shared` v4.168.0, pinned by release tarball- **PostgreSQL 18 and Valkey 9** (OpenVibe.Host `roles/data/`, ADR-035): every read and write is async through`openvibe-sdk/db`; Valkey holds the per-person limit counters (optional: without `VALKEY_URL` they count in the process)@@@ -514,6 +514,6 @@ Part of the [OpenVibe network](https://openvibe.network). Built in the open by [<!-- versions:start -->- openvibe-contracts: v0.338.0--- openvibe-sdk: v0.94.0++- openvibe-sdk: v0.117.0- openvibe-shared: v4.168.0<!-- versions:end -->@@@ -9,7 +9,7 @@"deployed": true,"deployment": "The money ledger since the cutover of 2026-10-17 04:50-04:56 UTC (BILLING_AUTHORITY=billing in billing.env and live.env): deployed with `sudo ovhost deploy billing`, /opt/openvibe.billing, 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), the billing policy (/policy), a person's own Vibes (/api/me/vibes, CORS for OpenVibe's sites), /api/health, /api/ready, /release.json and /webhooks/*. PowerChat deliveries reach /webhooks/powerchat through openvibe.live's /api/powerchat/webhook (proxied by Live's vhost, OpenVibe.Live#172).","contracts": "openvibe-contracts v0.338.0",-- "sdk": "openvibe-sdk v0.94.0",++ "sdk": "openvibe-sdk v0.117.0","shared": "openvibe-shared v4.168.0","notes": "Runtime, journal, adapters, import, reconciliation and the staff console (cashout approve/deny, review queue, reconciliation, freeze, audit log) are built, tested and deployed, with /metrics (loopback only), hourly scheduled reconciliation, EXTERNAL PowerChat receipts (billing.receipt.external, announced for OpenVibe.Tips), overflow guards and serializable settlement (PostgreSQL, ADR-035). The cutover (README runbook, docs/live-cutover.md) ran on 2026-10-17: final import 0 new rows, 0 holds, 0 anomalies; reconciliation OK before and after; Live's money tables are read-only behind a database tripwire. OpenVibe.Tips and OpenVibe.VIP launched right after (VIP checkout open). Still due: a small real PowerChat purchase settling end to end after the cutover. Live's payouts, refunds and plans have no tables of their own; where they map is docs/live-mapping.md.","features": [@@@ -13,7 +13,7 @@"express": "^4.21.2","iovalkey": "^0.4.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.117.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.168.0","pg": "^8.23.0"},@@@ -1119,9 +1119,9 @@}},"node_modules/openvibe-sdk": {-- "version": "0.94.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",-- "integrity": "sha512-p3buZSOSFV81OdZgs5GoSIfMCQNJjW23eAIXIt0RVFIOvh3TByNNEMmuCanxRybFIbzh+9IDMbBwHJrBLl3JeA==",++ "version": "0.117.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.117.0",++ "integrity": "sha512-ddxDwovrh77aqB1AHRSdswshCYzbTvePBj2smziWbTCzHhxDP5AKXCGqBmOt8ucBLZrDpr+1yhhBUtb6CD/YFw==","license": "MIT","bin": {"openvibe-download": "bin/openvibe-download.js"@@@ -27,7 +27,7 @@"express": "^4.21.2","iovalkey": "^0.4.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",-- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",++ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.117.0","openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.168.0","pg": "^8.23.0"},@@@ -23,8 +23,13 @@ const { createServiceOutbox, outboxSchema } = require('openvibe-sdk/events');const sent = { ...event, event_id: 'evt_legacy_sent' };await db.query('INSERT INTO outbox (event_id, event, created_at, sent_at) VALUES ($1, $2, $3, $4)',[sent.event_id, JSON.stringify(sent), sent.timestamp, event.timestamp]);-- const ddl = fs.readFileSync(path.join(migrations, '0006_sdk_outbox.sql'), 'utf8');-- assert.ok(ddl.includes(outboxSchema('service_outbox')));++ // The SDK's outbox schema is covered by 0006 and the migrations after it: a statement the SDK added later++ // (0.99.0's rejected_at index) lands in a new migration (0016), never in one that has run.++ const fromSix = fs.readdirSync(migrations).filter((f) => /^\d{4}_.*\.sql$/.test(f) && f >= '0006_').sort();++ const ddl = fromSix.map((f) => fs.readFileSync(path.join(migrations, f), 'utf8')).join('\n');++ for (const statement of outboxSchema('service_outbox').split(';').map((x) => x.trim()).filter(Boolean)) {++ assert.ok(ddl.includes(statement), `a migration from 0006 on carries: ${statement.slice(0, 80)}`);++ }fs.copyFileSync(path.join(migrations, '0006_sdk_outbox.sql'), path.join(dir, '0006_sdk_outbox.sql'));await db.migrate({ dir, log: { log() {} } });const rows = await db.many('SELECT event_id, envelope, created_at, attempts FROM service_outbox');
@@ -66,7 +66,7 @@ promo write changes both in one transaction.
@@ -66,7 +66,7 @@ promo write changes both in one transaction.
- OpenVibe.Network (JWKS for service tokens; SSO with PKCE for the staff console; `identity.subject.resolve` for the Live import)
- OpenVibe.Network (JWKS for service tokens; SSO with PKCE for the staff console; `identity.subject.resolve` for the Live import)
- OpenVibe.Events (the SDK outbox relay, when `EVENTS_URL` and the OAuth client secret are set)
- OpenVibe.Events (the SDK outbox relay, when `EVENTS_URL` and the OAuth client secret are set)
- the payment providers whose secrets are configured (none in production today)
- the payment providers whose secrets are configured (none in production today)
-- `openvibe-contracts` v0.338.0, `openvibe-sdk` v0.94.0 (service tokens, per-person limits, `openvibe-sdk/db`, `openvibe-sdk/service`, `openvibe-sdk/vibes`), `openvibe-shared` v4.168.0, pinned by release tarball
+- `openvibe-contracts` v0.338.0, `openvibe-sdk` v0.117.0 (service tokens, per-person limits, `openvibe-sdk/db`, `openvibe-sdk/service`, `openvibe-sdk/vibes`), `openvibe-shared` v4.168.0, pinned by release tarball
- **PostgreSQL 18 and Valkey 9** (OpenVibe.Host `roles/data/`, ADR-035): every read and write is async through
- **PostgreSQL 18 and Valkey 9** (OpenVibe.Host `roles/data/`, ADR-035): every read and write is async through
`openvibe-sdk/db`; Valkey holds the per-person limit counters (optional: without `VALKEY_URL` they count in the process)
`openvibe-sdk/db`; Valkey holds the per-person limit counters (optional: without `VALKEY_URL` they count in the process)
@@ -514,6 +514,6 @@ Part of the [OpenVibe network](https://openvibe.network). Built in the open by [
@@ -514,6 +514,6 @@ Part of the [OpenVibe network](https://openvibe.network). Built in the open by [
<!-- versions:start -->
<!-- versions:start -->
- openvibe-contracts: v0.338.0
- openvibe-contracts: v0.338.0
-- openvibe-sdk: v0.94.0
+- openvibe-sdk: v0.117.0
- openvibe-shared: v4.168.0
- openvibe-shared: v4.168.0
<!-- versions:end -->
<!-- versions:end -->
@@ -9,7 +9,7 @@
@@ -9,7 +9,7 @@
"deployed": true,
"deployed": true,
"deployment": "The money ledger since the cutover of 2026-10-17 04:50-04:56 UTC (BILLING_AUTHORITY=billing in billing.env and live.env): deployed with `sudo ovhost deploy billing`, /opt/openvibe.billing, 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), the billing policy (/policy), a person's own Vibes (/api/me/vibes, CORS for OpenVibe's sites), /api/health, /api/ready, /release.json and /webhooks/*. PowerChat deliveries reach /webhooks/powerchat through openvibe.live's /api/powerchat/webhook (proxied by Live's vhost, OpenVibe.Live#172).",
"deployment": "The money ledger since the cutover of 2026-10-17 04:50-04:56 UTC (BILLING_AUTHORITY=billing in billing.env and live.env): deployed with `sudo ovhost deploy billing`, /opt/openvibe.billing, 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), the billing policy (/policy), a person's own Vibes (/api/me/vibes, CORS for OpenVibe's sites), /api/health, /api/ready, /release.json and /webhooks/*. PowerChat deliveries reach /webhooks/powerchat through openvibe.live's /api/powerchat/webhook (proxied by Live's vhost, OpenVibe.Live#172).",
"contracts": "openvibe-contracts v0.338.0",
"contracts": "openvibe-contracts v0.338.0",
- "sdk": "openvibe-sdk v0.94.0",
+ "sdk": "openvibe-sdk v0.117.0",
"shared": "openvibe-shared v4.168.0",
"shared": "openvibe-shared v4.168.0",
"notes": "Runtime, journal, adapters, import, reconciliation and the staff console (cashout approve/deny, review queue, reconciliation, freeze, audit log) are built, tested and deployed, with /metrics (loopback only), hourly scheduled reconciliation, EXTERNAL PowerChat receipts (billing.receipt.external, announced for OpenVibe.Tips), overflow guards and serializable settlement (PostgreSQL, ADR-035). The cutover (README runbook, docs/live-cutover.md) ran on 2026-10-17: final import 0 new rows, 0 holds, 0 anomalies; reconciliation OK before and after; Live's money tables are read-only behind a database tripwire. OpenVibe.Tips and OpenVibe.VIP launched right after (VIP checkout open). Still due: a small real PowerChat purchase settling end to end after the cutover. Live's payouts, refunds and plans have no tables of their own; where they map is docs/live-mapping.md.",
"notes": "Runtime, journal, adapters, import, reconciliation and the staff console (cashout approve/deny, review queue, reconciliation, freeze, audit log) are built, tested and deployed, with /metrics (loopback only), hourly scheduled reconciliation, EXTERNAL PowerChat receipts (billing.receipt.external, announced for OpenVibe.Tips), overflow guards and serializable settlement (PostgreSQL, ADR-035). The cutover (README runbook, docs/live-cutover.md) ran on 2026-10-17: final import 0 new rows, 0 holds, 0 anomalies; reconciliation OK before and after; Live's money tables are read-only behind a database tripwire. OpenVibe.Tips and OpenVibe.VIP launched right after (VIP checkout open). Still due: a small real PowerChat purchase settling end to end after the cutover. Live's payouts, refunds and plans have no tables of their own; where they map is docs/live-mapping.md.",
"features": [
"features": [
@@ -13,7 +13,7 @@
@@ -13,7 +13,7 @@
"express": "^4.21.2",
"express": "^4.21.2",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",
+ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.117.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.168.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.168.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
@@ -1119,9 +1119,9 @@
@@ -1119,9 +1119,9 @@
}
}
},
},
"node_modules/openvibe-sdk": {
"node_modules/openvibe-sdk": {
- "version": "0.94.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",
- "integrity": "sha512-p3buZSOSFV81OdZgs5GoSIfMCQNJjW23eAIXIt0RVFIOvh3TByNNEMmuCanxRybFIbzh+9IDMbBwHJrBLl3JeA==",
+ "version": "0.117.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.117.0",
+ "integrity": "sha512-ddxDwovrh77aqB1AHRSdswshCYzbTvePBj2smziWbTCzHhxDP5AKXCGqBmOt8ucBLZrDpr+1yhhBUtb6CD/YFw==",
"license": "MIT",
"license": "MIT",
"bin": {
"bin": {
"openvibe-download": "bin/openvibe-download.js"
"openvibe-download": "bin/openvibe-download.js"
@@ -27,7 +27,7 @@
@@ -27,7 +27,7 @@
"express": "^4.21.2",
"express": "^4.21.2",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.338.0",
- "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.94.0",
+ "openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.117.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.168.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.168.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
},
},
@@ -23,8 +23,13 @@ const { createServiceOutbox, outboxSchema } = require('openvibe-sdk/events');
@@ -23,8 +23,13 @@ const { createServiceOutbox, outboxSchema } = require('openvibe-sdk/events');
const sent = { ...event, event_id: 'evt_legacy_sent' };
const sent = { ...event, event_id: 'evt_legacy_sent' };
await db.query('INSERT INTO outbox (event_id, event, created_at, sent_at) VALUES ($1, $2, $3, $4)',
await db.query('INSERT INTO outbox (event_id, event, created_at, sent_at) VALUES ($1, $2, $3, $4)',
[sent.event_id, JSON.stringify(sent), sent.timestamp, event.timestamp]);
[sent.event_id, JSON.stringify(sent), sent.timestamp, event.timestamp]);
- const ddl = fs.readFileSync(path.join(migrations, '0006_sdk_outbox.sql'), 'utf8');
- assert.ok(ddl.includes(outboxSchema('service_outbox')));
+ // The SDK's outbox schema is covered by 0006 and the migrations after it: a statement the SDK added later
+ // (0.99.0's rejected_at index) lands in a new migration (0016), never in one that has run.
+ const fromSix = fs.readdirSync(migrations).filter((f) => /^\d{4}_.*\.sql$/.test(f) && f >= '0006_').sort();
+ const ddl = fromSix.map((f) => fs.readFileSync(path.join(migrations, f), 'utf8')).join('\n');
+ for (const statement of outboxSchema('service_outbox').split(';').map((x) => x.trim()).filter(Boolean)) {
+ assert.ok(ddl.includes(statement), `a migration from 0006 on carries: ${statement.slice(0, 80)}`);
+ }
fs.copyFileSync(path.join(migrations, '0006_sdk_outbox.sql'), path.join(dir, '0006_sdk_outbox.sql'));
fs.copyFileSync(path.join(migrations, '0006_sdk_outbox.sql'), path.join(dir, '0006_sdk_outbox.sql'));
await db.migrate({ dir, log: { log() {} } });
await db.migrate({ dir, log: { log() {} } });
const rows = await db.many('SELECT event_id, envelope, created_at, attempts FROM service_outbox');
const rows = await db.many('SELECT event_id, envelope, created_at, attempts FROM service_outbox');