openvibers/openvibe.contracts Commits

v0.30.1: cashout events carry the payout method's type only, never its address

OP OpenVibers committed 23 Sept 2026 · ddaed68733 · 15 files, +94 −27


Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex cf03d521..b0eb1abb 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,12 @@ All notable changes to `openvibe-contracts`. Releases are git tags (`vX.Y.Z`) th
from `https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/<tag>`. Before v0.30.0,
the notes were in the tag and commit messages (`git tag -n1`).
++## 0.30.1 — 2026-09-23
++
++- `billing.cashout.requested|paid|denied`: `cashout.payout_method` carries the method's `type` only
++ (`additionalProperties: false`). The address (e.g. a PayPal email) stays in Billing and never
++ travels on the retained event stream. No producer had emitted a cashout event yet.
++
## 0.30.0 (2026-09-23)
Additive: `compat.js` reports no breaking change against v0.29.0. No existing contract changed.
ddiff --git a/contracts/events/payloads/billing.cashout.denied.v1.json b/contracts/events/payloads/billing.cashout.denied.v1.json
iindex aa7f6db6..1d7823d3 100644
---- a/contracts/events/payloads/billing.cashout.denied.v1.json
++++ b/contracts/events/payloads/billing.cashout.denied.v1.json
@@@ -17,7 +17,7 @@
"amount_bits": { "type": "integer", "minimum": 1 },
"value_cents": { "type": "integer" },
"status": { "const": "denied" },
-- "payout_method": { "type": "object", "description": "{ type, address } as the creator entered it (e.g. a PayPal email)." },
++ "payout_method": { "type": "object", "required": ["type"], "additionalProperties": false, "description": "The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.", "properties": { "type": { "type": ["string", "null"] } } },
"escrow_until": { "type": "string" },
"request_txn": { "type": "string", "pattern": "^txn_[0-9A-HJKMNP-TV-Z]{26}$" },
"settle_txn": { "type": ["string", "null"], "pattern": "^txn_[0-9A-HJKMNP-TV-Z]{26}$" },
ddiff --git a/contracts/events/payloads/billing.cashout.paid.v1.json b/contracts/events/payloads/billing.cashout.paid.v1.json
iindex fa5b4fbf..149617bf 100644
---- a/contracts/events/payloads/billing.cashout.paid.v1.json
++++ b/contracts/events/payloads/billing.cashout.paid.v1.json
@@@ -17,7 +17,7 @@
"amount_bits": { "type": "integer", "minimum": 1 },
"value_cents": { "type": "integer" },
"status": { "const": "paid" },
-- "payout_method": { "type": "object", "description": "{ type, address } as the creator entered it (e.g. a PayPal email)." },
++ "payout_method": { "type": "object", "required": ["type"], "additionalProperties": false, "description": "The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.", "properties": { "type": { "type": ["string", "null"] } } },
"escrow_until": { "type": "string" },
"request_txn": { "type": "string", "pattern": "^txn_[0-9A-HJKMNP-TV-Z]{26}$" },
"settle_txn": { "type": ["string", "null"], "pattern": "^txn_[0-9A-HJKMNP-TV-Z]{26}$" },
ddiff --git a/contracts/events/payloads/billing.cashout.requested.v1.json b/contracts/events/payloads/billing.cashout.requested.v1.json
iindex 31724002..ee588f3f 100644
---- a/contracts/events/payloads/billing.cashout.requested.v1.json
++++ b/contracts/events/payloads/billing.cashout.requested.v1.json
@@@ -17,7 +17,7 @@
"amount_bits": { "type": "integer", "minimum": 1 },
"value_cents": { "type": "integer" },
"status": { "const": "requested" },
-- "payout_method": { "type": "object", "description": "{ type, address } as the creator entered it (e.g. a PayPal email)." },
++ "payout_method": { "type": "object", "required": ["type"], "additionalProperties": false, "description": "The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.", "properties": { "type": { "type": ["string", "null"] } } },
"escrow_until": { "type": "string" },
"request_txn": { "type": "string", "pattern": "^txn_[0-9A-HJKMNP-TV-Z]{26}$" },
"settle_txn": { "type": ["string", "null"], "pattern": "^txn_[0-9A-HJKMNP-TV-Z]{26}$" },
ddiff --git a/fixtures/billing.cashout.denied/invalid/no-transaction.json b/fixtures/billing.cashout.denied/invalid/no-transaction.json
iindex 9122a004..00674a9c 100644
---- a/fixtures/billing.cashout.denied/invalid/no-transaction.json
++++ b/fixtures/billing.cashout.denied/invalid/no-transaction.json
@@@ -9,8 +9,7 @@
"value_cents": 5000,
"status": "denied",
"payout_method": {
-- "type": "paypal",
-- "address": "[email protected]"
++ "type": "paypal"
},
"escrow_until": "2026-09-30T10:00:00.000Z",
"request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
ddiff --git a/fixtures/billing.cashout.denied/valid/denied.json b/fixtures/billing.cashout.denied/valid/denied.json
iindex 645f6553..63be1aee 100644
---- a/fixtures/billing.cashout.denied/valid/denied.json
++++ b/fixtures/billing.cashout.denied/valid/denied.json
@@@ -9,8 +9,7 @@
"value_cents": 5000,
"status": "denied",
"payout_method": {
-- "type": "paypal",
-- "address": "[email protected]"
++ "type": "paypal"
},
"escrow_until": "2026-09-30T10:00:00.000Z",
"request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
ddiff --git a/fixtures/billing.cashout.paid/invalid/float-bits.json b/fixtures/billing.cashout.paid/invalid/float-bits.json
iindex 925d70d3..d0fa86e1 100644
---- a/fixtures/billing.cashout.paid/invalid/float-bits.json
++++ b/fixtures/billing.cashout.paid/invalid/float-bits.json
@@@ -9,8 +9,7 @@
"value_cents": 5000,
"status": "paid",
"payout_method": {
-- "type": "paypal",
-- "address": "[email protected]"
++ "type": "paypal"
},
"escrow_until": "2026-09-30T10:00:00.000Z",
"request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
ddiff --git a/fixtures/billing.cashout.paid/valid/paypal.json b/fixtures/billing.cashout.paid/valid/paypal.json
iindex 0fc9c84c..feb1674c 100644
---- a/fixtures/billing.cashout.paid/valid/paypal.json
++++ b/fixtures/billing.cashout.paid/valid/paypal.json
@@@ -9,8 +9,7 @@
"value_cents": 5000,
"status": "paid",
"payout_method": {
-- "type": "paypal",
-- "address": "[email protected]"
++ "type": "paypal"
},
"escrow_until": "2026-09-30T10:00:00.000Z",
"request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
ddiff --git a/fixtures/billing.cashout.requested/invalid/payout-address.json b/fixtures/billing.cashout.requested/invalid/payout-address.json
nnew file mode 100644
iindex 00000000..b080e3f2
---- /dev/null
++++ b/fixtures/billing.cashout.requested/invalid/payout-address.json
@@@ -0,0 +1,25 @@
++{
++ "cashout": {
++ "id": "co_01JAB3C4D5E6F7G8H9J0K1MNQ5",
++ "subject": {
++ "type": "user",
++ "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ"
++ },
++ "amount_bits": 5000,
++ "value_cents": 5000,
++ "status": "requested",
++ "payout_method": {
++ "type": "paypal",
++ "address": "[email protected]"
++ },
++ "escrow_until": "2026-09-30T10:00:00.000Z",
++ "request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
++ "settle_txn": null,
++ "payout_provider": null,
++ "payout_reference": null,
++ "reason": null,
++ "created_at": "2026-09-23T10:00:00.000Z",
++ "updated_at": "2026-09-23T10:00:00.000Z"
++ },
++ "transaction_id": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6"
++}
ddiff --git a/fixtures/billing.cashout.requested/invalid/wrong-status.json b/fixtures/billing.cashout.requested/invalid/wrong-status.json
iindex 7e30c74d..5fe5df50 100644
---- a/fixtures/billing.cashout.requested/invalid/wrong-status.json
++++ b/fixtures/billing.cashout.requested/invalid/wrong-status.json
@@@ -9,8 +9,7 @@
"value_cents": 5000,
"status": "paid",
"payout_method": {
-- "type": "paypal",
-- "address": "[email protected]"
++ "type": "paypal"
},
"escrow_until": "2026-09-30T10:00:00.000Z",
"request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
ddiff --git a/fixtures/billing.cashout.requested/valid/paypal.json b/fixtures/billing.cashout.requested/valid/paypal.json
iindex 3fdc1c7e..797aa048 100644
---- a/fixtures/billing.cashout.requested/valid/paypal.json
++++ b/fixtures/billing.cashout.requested/valid/paypal.json
@@@ -9,8 +9,7 @@
"value_cents": 5000,
"status": "requested",
"payout_method": {
-- "type": "paypal",
-- "address": "[email protected]"
++ "type": "paypal"
},
"escrow_until": "2026-09-30T10:00:00.000Z",
"request_txn": "txn_01JAB3C4D5E6F7G8H9J0K1MNQ6",
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex 3e777770..687067b9 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -6185,7 +6185,19 @@
},
"payout_method": {
"type": "object",
-- "description": "{ type, address } as the creator entered it (e.g. a PayPal email)."
++ "required": [
++ "type"
++ ],
++ "additionalProperties": false,
++ "description": "The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.",
++ "properties": {
++ "type": {
++ "type": [
++ "string",
++ "null"
++ ]
++ }
++ }
},
"escrow_until": {
"type": "string"
@@@ -6290,7 +6302,19 @@
},
"payout_method": {
"type": "object",
-- "description": "{ type, address } as the creator entered it (e.g. a PayPal email)."
++ "required": [
++ "type"
++ ],
++ "additionalProperties": false,
++ "description": "The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.",
++ "properties": {
++ "type": {
++ "type": [
++ "string",
++ "null"
++ ]
++ }
++ }
},
"escrow_until": {
"type": "string"
@@@ -6395,7 +6419,19 @@
},
"payout_method": {
"type": "object",
-- "description": "{ type, address } as the creator entered it (e.g. a PayPal email)."
++ "required": [
++ "type"
++ ],
++ "additionalProperties": false,
++ "description": "The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.",
++ "properties": {
++ "type": {
++ "type": [
++ "string",
++ "null"
++ ]
++ }
++ }
},
"escrow_until": {
"type": "string"
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex 23bdef09..3a46bce2 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -6151,9 +6151,11 @@ export interface BillingCashoutRequestedPayload {
value_cents: number;
status: "requested";
/**
-- * { type, address } as the creator entered it (e.g. a PayPal email).
++ * The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.
*/
-- payout_method: {};
++ payout_method: {
++ type: string | null;
++ };
escrow_until: string;
request_txn: string;
settle_txn: string | null;
@@@ -6181,9 +6183,11 @@ export interface BillingCashoutPaidPayload {
value_cents: number;
status: "paid";
/**
-- * { type, address } as the creator entered it (e.g. a PayPal email).
++ * The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.
*/
-- payout_method: {};
++ payout_method: {
++ type: string | null;
++ };
escrow_until: string;
request_txn: string;
settle_txn: string | null;
@@@ -6211,9 +6215,11 @@ export interface BillingCashoutDeniedPayload {
value_cents: number;
status: "denied";
/**
-- * { type, address } as the creator entered it (e.g. a PayPal email).
++ * The payout method's kind only; the address (e.g. a PayPal email) stays in Billing and never travels on the event stream.
*/
-- payout_method: {};
++ payout_method: {
++ type: string | null;
++ };
escrow_until: string;
request_txn: string;
settle_txn: string | null;
ddiff --git a/package-lock.json b/package-lock.json
iindex ffb8df08..15273039 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -1,12 +1,12 @@
{
"name": "openvibe-contracts",
-- "version": "0.30.0",
++ "version": "0.30.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "openvibe-contracts",
-- "version": "0.30.0",
++ "version": "0.30.1",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 5884e30d..1a84079a 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.30.0",
++ "version": "0.30.1",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"types": "generated/typescript/index.d.ts",