openvibers/openvibe.contracts Commits

Guard that usage rollups carry no money and one capability takes…

OP OpenVibers committed 4 Oct 2026 · 969bc3919e · 1 file, +15 −0

Asked: Follow-up of https://github.com/OpenVibers/OpenVibe.Network/pull/42 (Document that usage rollups are counts, never money, and guard it): its review asked for a change in OpenVibe.Contracts that the PR cannot make from OpenVibe.Network. The review said: VERDICT: FIX
Harness job contracts-follow-up-of-https-github-com--202711.

Changes

ddiff --git a/test/usage-topics.test.js b/test/usage-topics.test.js
iindex 65f7290f..4cf836c9 100644
---- a/test/usage-topics.test.js
++++ b/test/usage-topics.test.js
@@@ -4,6 +4,7 @@
const assert = require('assert');
const fs = require('fs');
const path = require('path');
++const { capabilities, services, schema } = require('..');
const dir = path.join(__dirname, '..', 'manifests', 'services');
const MAY_CONSUME = new Set(['network', 'codes', 'zone']);
@@@ -22,4 +23,18 @@ for (const c of consumers) {
}
assert.ok(!consumers.some((c) => c.id === 'billing'), 'billing never consumes a *.usage.recorded topic');
assert.ok(consumers.some((c) => c.id === 'network'), 'network consumes the usage rollups it adds up per project');
++
++// The capability the Network default grant names must exist, be owned and listed by Billing, and be the
++// estate's ONE money input: a second capability taking a platform.usage-sample reading, or a route added
++// for it, is a change of who rates, not a new endpoint. The rollup payload carries no money field.
++const record = capabilities.get('billing.usage.record');
++assert.ok(record && record.owner === 'billing' && record.status === 'active', 'billing.usage.record exists as an active Billing capability');
++assert.ok(services.get('billing').capabilities.includes('billing.usage.record'), 'the Billing manifest lists billing.usage.record');
++assert.strictEqual(record.inputSchema, 'platform.usage-sample@1', 'the money input is a platform.usage-sample@1 reading');
++const moneyInputs = capabilities.manifests.filter((c) => c.inputSchema === 'platform.usage-sample@1');
++assert.deepStrictEqual(moneyInputs.map((c) => c.id), ['billing.usage.record'], 'billing.usage.record is the only capability that takes a usage reading');
++const billing = services.get('billing');
++assert.ok(!(billing.eventsProduced || []).some(isUsageTopic) && !(billing.eventsConsumed || []).some(isUsageTopic), 'Billing neither produces nor consumes a *.usage.recorded topic');
++const props = Object.keys(schema('common.usage-recorded').properties);
++assert.ok(!props.some((p) => /cost|price|amount|currency|money|charge|vibes|usd/i.test(p)), 'no field of a usage rollup is money');
console.log(`usage-topics ok: ${consumers.map((c) => c.id).join(', ')} consume a *.usage.recorded topic`);