openvibers/openvibe.services Commits

openvibe-contracts v0.130.0 (was v0.129.0) (#30)

OP OpenVibers committed 10 Oct 2026 · b8af92c40b · 5 files, +25 −18

* openvibe-contracts v0.130.0 (was v0.129.0)

Opened by scripts/pin-bump.js in OpenVibers/OpenVibe.Shared after the v0.130.0 release.

* authorities test: contracts v0.130.0 has eight authorities (watch, actor, bot, chat added)

Changes

ddiff --git a/README.md b/README.md
iindex d8302b9..0a065f8 100644
---- a/README.md
++++ b/README.md
@@@ -102,7 +102,7 @@ There is no polling loop: the index reads the authorities on each request (step
- **OpenVibe.Events** — the outbox relay publishes `services.app.*` with Services' service token (`events.event.publish`); the Events playground calls it with the app's token (`events.app.publish`); the project archive pulls the project's app events with a Network export token (`events.app.read`).
- **OpenVibe.Media** — the Media playground uploads with the app's token into the project's namespace; the project archive lists the project's objects, namespaces and download URLs with a Network export token (`media.object.list`, `media.object.read`).
- **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-actor limit counters (optional).
--- **openvibe-contracts v0.129.0**, **openvibe-sdk v0.35.1**, **openvibe-shared v3.0.0** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).
++- **openvibe-contracts v0.130.0**, **openvibe-sdk v0.35.1**, **openvibe-shared v3.0.0** (pinned tag tarballs; the docs show the tag and the package version, and say so when they differ).
No path in Services sends or accepts a shared loopback key (tested by grep and at runtime).
@@@ -144,7 +144,7 @@ one receipt per export and deletion in `account_data_events` (migration 0003).
- The resource index's owner becomes NULL.
- The append-only release log, the control log and the staff trust tiers stay attributed, for accountability.
--The Services service manifest, `services.release.manage|read`, `services.resource.read` and `services.app-manifest@1` are released in openvibe-contracts v0.129.0 (they replaced the `codes.*` forms, retired that release); the CI contracts check is blocking.
++The Services service manifest, `services.release.manage|read`, `services.resource.read` and `services.app-manifest@1` are released in openvibe-contracts v0.130.0 (they replaced the `codes.*` forms, retired that release); the CI contracts check is blocking.
For the playgrounds to succeed end to end (not Services' code; configuration elsewhere): Network `DEV_SANDBOX_AUDIENCES` including `openvibe.media` and `openvibe.events`, a staff-set allowance containing `media.object.upload` and `events.app.publish` for the project, a Media tenant keyed by the project id, and OpenVibe.Events serving `events.app.publish` for app tokens. On 2026-09-23 these were in place on production: a sandbox app uploaded to Media (tenant `prj_…-sandbox`) and published and read app events through public endpoints. That run used curl, not the playgrounds, and it is not yet a committed, repeatable check.
@@@ -251,7 +251,7 @@ Reporting a vulnerability: [SECURITY.md](SECURITY.md).
Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).
<!-- versions:start -->
--- openvibe-contracts: v0.129.0
++- openvibe-contracts: v0.130.0
- openvibe-sdk: v0.38.0
- openvibe-shared: v3.0.0
<!-- versions:end -->
ddiff --git a/STATUS.json b/STATUS.json
iindex 6aed608..4d6352e 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -7,11 +7,11 @@
"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db)",
"port": 4930,
"domain": "openvibe.services",
-- "contracts": "openvibe-contracts v0.129.0",
++ "contracts": "openvibe-contracts v0.130.0",
"sdk": "openvibe-sdk v0.38.0",
"shared": "openvibe-shared v3.0.0",
"packages": [
-- "openvibe-contracts v0.129.0",
++ "openvibe-contracts v0.130.0",
"openvibe-sdk v0.38.0",
"openvibe-shared v3.0.0"
],
ddiff --git a/package-lock.json b/package-lock.json
iindex 280ba50..d26faa9 100644
---- a/package-lock.json
++++ b/package-lock.json
@@@ -16,7 +16,7 @@
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.129.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.130.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.38.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v3.0.0",
"pg": "^8.23.0"
@@@ -890,9 +890,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.129.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.129.0",
-- "integrity": "sha512-Ly0F/ap6wmAf8hYpNrOhMLsU3cZYBjsFDW2P1F/xVmHVsRDzAPAZDXtFcohP0UNeZgyxgrR0BI0pPG5guD/Efw==",
++ "version": "0.130.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.130.0",
++ "integrity": "sha512-QtI1DNY2iZUOXFYFRsa8IEx1eWhplNVk6/mRzARDR0hi7sV/Q+64CUeDZeb865XUQ5KryBhjiFwLCfaRqaPeig==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex a681577..6a98291 100644
---- a/package.json
++++ b/package.json
@@@ -27,7 +27,7 @@
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
-- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.129.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.130.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.38.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v3.0.0",
"pg": "^8.23.0"
ddiff --git a/test/authorities.test.js b/test/authorities.test.js
iindex 36086a3..7097f46 100644
---- a/test/authorities.test.js
++++ b/test/authorities.test.js
@@@ -1,8 +1,9 @@
'use strict';
/**
-- * server/authorities/index.js against the REAL pinned openvibe-contracts (v0.113.0): the registry is
++ * server/authorities/index.js against the REAL pinned openvibe-contracts (v0.130.0): the registry is
* derived from the released service manifests — every non-placeholder service whose manifest lists an
-- * active <id>.resource.read — and never hand-maintained. The four authorities of the pin, their manifest
++ * active <id>.resource.read — and never hand-maintained. The eight authorities of the pin (0.130.0 added
++ * watch, actor, bot and chat, plan T13 step 8 phase 2), their manifest
* loopback origins and their audiences; Services itself (read in process: server/registry/self-authority.js),
* Codes (retired codes.resource.read at 0.113.0, when its portal moved here), placeholders and services without
* the capability are not authorities.
@@@ -16,11 +17,13 @@ const { createAuthorities } = require('../server/authorities');
const { check, done } = require('./helpers/app');
const quiet = { warn() {}, log() {}, error() {} };
++const AUTHORITIES = ['actor', 'bot', 'chat', 'events', 'host', 'media', 'network', 'watch'];
async function main() {
-- await check('the pin lists five active <id>.resource.read capabilities, four of them authorities', () => {
++ await check('the pin lists nine active <id>.resource.read capabilities, eight of them authorities', () => {
const ids = contracts.capabilities.manifests.filter((c) => /^([a-z][a-z0-9-]{0,31})\.resource\.read$/.test(c.id) && c.status === 'active').map((c) => c.id).sort();
-- assert.deepStrictEqual(ids, ['events.resource.read', 'host.resource.read', 'media.resource.read', 'network.resource.read', 'services.resource.read']);
++ assert.deepStrictEqual(ids, ['actor.resource.read', 'bot.resource.read', 'chat.resource.read', 'events.resource.read', 'host.resource.read',
++ 'media.resource.read', 'network.resource.read', 'services.resource.read', 'watch.resource.read']);
assert.strictEqual(contracts.capabilities.get('codes.resource.read').status, 'retired', 'Codes owns no resources since 0.113.0');
// services.resource.read is Services' own id; Services is never its own authority (the next check).
assert.ok(!createAuthorities(loadConfig({}), { log: quiet }).ids().includes('services'));
@@@ -28,12 +31,16 @@ async function main() {
await check('the registry is built from those manifests, with the manifest origins and audiences', () => {
const registry = createAuthorities(loadConfig({}), { log: quiet });
-- assert.deepStrictEqual(registry.ids(), ['events', 'host', 'media', 'network']);
++ assert.deepStrictEqual(registry.ids(), AUTHORITIES);
const expected = {
network: 'http://127.0.0.1:4000',
media: 'http://127.0.0.1:4100',
events: 'http://127.0.0.1:4300',
host: 'http://127.0.0.1:4910',
++ watch: 'http://127.0.0.1:4730',
++ actor: 'http://127.0.0.1:4950',
++ bot: 'http://127.0.0.1:4630',
++ chat: 'http://127.0.0.1:4400',
};
for (const [id, origin] of Object.entries(expected)) {
const a = registry.get(id);
@@@ -46,12 +53,12 @@ async function main() {
assert.strictEqual(a.publicOrigin, contracts.services.get(id).publicOrigin);
}
assert.strictEqual(registry.get('nope'), null);
-- assert.strictEqual(registry.size(), 4);
++ assert.strictEqual(registry.size(), AUTHORITIES.length);
});
await check('Services, placeholders and services without the capability are not authorities', () => {
const registry = createAuthorities(loadConfig({}), { log: quiet });
-- for (const id of ['services', 'codes', 'run', 'actor', 'watch', 'actor-console', 'sites']) {
++ for (const id of ['services', 'codes', 'run', 'space', 'tools', 'actor-console', 'sites']) {
if (!contracts.services.get(id)) continue;
assert.strictEqual(registry.get(id), null, `${id} must not be an authority`);
}
@@@ -63,7 +70,7 @@ async function main() {
const registry = createAuthorities(loadConfig({ SERVICES_MEDIA_URL: 'http://127.0.0.1:4999', SERVICES_RUN_URL: 'http://127.0.0.1:4888' }), { log: quiet });
assert.strictEqual(registry.get('media').internalOrigin, 'http://127.0.0.1:4999');
assert.strictEqual(registry.get('run'), null, 'an override for a service without the capability changes nothing');
-- assert.deepStrictEqual(registry.ids(), ['events', 'host', 'media', 'network']);
++ assert.deepStrictEqual(registry.ids(), AUTHORITIES);
});
await check('every registry entry satisfies the rule the registry claims', () => {