openvibers/openvibe.services Commits
openvibe-contracts v0.131.0 (was v0.130.0) (#31)
Changes
@@@ -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.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).++- **openvibe-contracts v0.131.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.130.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.131.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.130.0++- openvibe-contracts: v0.131.0- openvibe-sdk: v0.38.0- openvibe-shared: v3.0.0<!-- versions:end -->@@@ -7,11 +7,11 @@"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db)","port": 4930,"domain": "openvibe.services",-- "contracts": "openvibe-contracts v0.130.0",++ "contracts": "openvibe-contracts v0.131.0","sdk": "openvibe-sdk v0.38.0","shared": "openvibe-shared v3.0.0","packages": [-- "openvibe-contracts v0.130.0",++ "openvibe-contracts v0.131.0","openvibe-sdk v0.38.0","openvibe-shared v3.0.0"],@@@ -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.130.0",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.131.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.130.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.130.0",-- "integrity": "sha512-QtI1DNY2iZUOXFYFRsa8IEx1eWhplNVk6/mRzARDR0hi7sV/Q+64CUeDZeb865XUQ5KryBhjiFwLCfaRqaPeig==",++ "version": "0.131.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.131.0",++ "integrity": "sha512-ZojAzdJCkPnUPvZcS583p7roPmfaG4u8RL1r9yFrn+77JO9yg7Nmz2gvjQoTtX2AzWR7tI1bCtFd9MhprUioCg==","license": "AGPL-3.0-only","dependencies": {"ajv": "^8.17.1",@@@ -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.130.0",++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.131.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"@@@ -1,9 +1,9 @@'use strict';/**-- * server/authorities/index.js against the REAL pinned openvibe-contracts (v0.130.0): the registry is++ * server/authorities/index.js against the REAL pinned openvibe-contracts (v0.131.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 eight authorities of the pin (0.130.0 added-- * watch, actor, bot and chat, plan T13 step 8 phase 2), their manifest++ * active <id>.resource.read — and never hand-maintained. The nine authorities of the pin (0.130.0 added++ * watch, actor, bot and chat, 0.131.0 OpenRestream; 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.@@@ -17,13 +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'];++const AUTHORITIES = ['actor', 'bot', 'chat', 'events', 'host', 'media', 'network', 'openre', 'watch'];async function main() {-- await check('the pin lists nine active <id>.resource.read capabilities, eight of them authorities', () => {++ await check('the pin lists ten active <id>.resource.read capabilities, nine 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, ['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']);++ 'media.resource.read', 'network.resource.read', 'openre.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'));@@@ -41,6 +41,7 @@ async function main() {actor: 'http://127.0.0.1:4950',bot: 'http://127.0.0.1:4630',chat: 'http://127.0.0.1:4400',++ openre: 'http://127.0.0.1:4500',};for (const [id, origin] of Object.entries(expected)) {const a = registry.get(id);
@@ -102,7 +102,7 @@ There is no polling loop: the index reads the authorities on each request (step
@@ -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.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`).
- **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).
- **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.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).
+- **openvibe-contracts v0.131.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).
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).
@@ -144,7 +144,7 @@ one receipt per export and deletion in `account_data_events` (migration 0003).
- The resource index's owner becomes NULL.
- 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 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.130.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.131.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.
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).
@@ -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).
Part of the [OpenVibe network](https://openvibe.network). Built in the open by [OpenVibers](https://github.com/OpenVibers).
<!-- versions:start -->
<!-- versions:start -->
-- openvibe-contracts: v0.130.0
+- openvibe-contracts: v0.131.0
- openvibe-sdk: v0.38.0
- openvibe-sdk: v0.38.0
- openvibe-shared: v3.0.0
- openvibe-shared: v3.0.0
<!-- versions:end -->
<!-- versions:end -->
@@ -7,11 +7,11 @@
@@ -7,11 +7,11 @@
"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db)",
"runtime": "node 22, express 4, PostgreSQL 18 (openvibe-sdk/db)",
"port": 4930,
"port": 4930,
"domain": "openvibe.services",
"domain": "openvibe.services",
- "contracts": "openvibe-contracts v0.130.0",
+ "contracts": "openvibe-contracts v0.131.0",
"sdk": "openvibe-sdk v0.38.0",
"sdk": "openvibe-sdk v0.38.0",
"shared": "openvibe-shared v3.0.0",
"shared": "openvibe-shared v3.0.0",
"packages": [
"packages": [
- "openvibe-contracts v0.130.0",
+ "openvibe-contracts v0.131.0",
"openvibe-sdk v0.38.0",
"openvibe-sdk v0.38.0",
"openvibe-shared v3.0.0"
"openvibe-shared v3.0.0"
],
],
@@ -16,7 +16,7 @@
@@ -16,7 +16,7 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.130.0",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.131.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.38.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",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v3.0.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
@@ -890,9 +890,9 @@
@@ -890,9 +890,9 @@
}
}
},
},
"node_modules/openvibe-contracts": {
"node_modules/openvibe-contracts": {
- "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==",
+ "version": "0.131.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.131.0",
+ "integrity": "sha512-ZojAzdJCkPnUPvZcS583p7roPmfaG4u8RL1r9yFrn+77JO9yg7Nmz2gvjQoTtX2AzWR7tI1bCtFd9MhprUioCg==",
"license": "AGPL-3.0-only",
"license": "AGPL-3.0-only",
"dependencies": {
"dependencies": {
"ajv": "^8.17.1",
"ajv": "^8.17.1",
@@ -27,7 +27,7 @@
@@ -27,7 +27,7 @@
"express-rate-limit": "^7.5.0",
"express-rate-limit": "^7.5.0",
"helmet": "^8.1.0",
"helmet": "^8.1.0",
"iovalkey": "^0.4.0",
"iovalkey": "^0.4.0",
- "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.130.0",
+ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.131.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.38.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",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v3.0.0",
"pg": "^8.23.0"
"pg": "^8.23.0"
@@ -1,9 +1,9 @@
@@ -1,9 +1,9 @@
'use strict';
'use strict';
/**
/**
- * server/authorities/index.js against the REAL pinned openvibe-contracts (v0.130.0): the registry is
+ * server/authorities/index.js against the REAL pinned openvibe-contracts (v0.131.0): the registry is
* derived from the released service manifests — every non-placeholder service whose manifest lists an
* derived from the released service manifests — every non-placeholder service whose manifest lists an
- * 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
+ * active <id>.resource.read — and never hand-maintained. The nine authorities of the pin (0.130.0 added
+ * watch, actor, bot and chat, 0.131.0 OpenRestream; plan T13 step 8 phase 2), their manifest
* loopback origins and their audiences; Services itself (read in process: server/registry/self-authority.js),
* 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
* Codes (retired codes.resource.read at 0.113.0, when its portal moved here), placeholders and services without
* the capability are not authorities.
* the capability are not authorities.
@@ -17,13 +17,13 @@ const { createAuthorities } = require('../server/authorities');
@@ -17,13 +17,13 @@ const { createAuthorities } = require('../server/authorities');
const { check, done } = require('./helpers/app');
const { check, done } = require('./helpers/app');
const quiet = { warn() {}, log() {}, error() {} };
const quiet = { warn() {}, log() {}, error() {} };
-const AUTHORITIES = ['actor', 'bot', 'chat', 'events', 'host', 'media', 'network', 'watch'];
+const AUTHORITIES = ['actor', 'bot', 'chat', 'events', 'host', 'media', 'network', 'openre', 'watch'];
async function main() {
async function main() {
- await check('the pin lists nine active <id>.resource.read capabilities, eight of them authorities', () => {
+ await check('the pin lists ten active <id>.resource.read capabilities, nine 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();
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, ['actor.resource.read', 'bot.resource.read', 'chat.resource.read', 'events.resource.read', 'host.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']);
+ 'media.resource.read', 'network.resource.read', 'openre.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');
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).
// 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'));
assert.ok(!createAuthorities(loadConfig({}), { log: quiet }).ids().includes('services'));
@@ -41,6 +41,7 @@ async function main() {
@@ -41,6 +41,7 @@ async function main() {
actor: 'http://127.0.0.1:4950',
actor: 'http://127.0.0.1:4950',
bot: 'http://127.0.0.1:4630',
bot: 'http://127.0.0.1:4630',
chat: 'http://127.0.0.1:4400',
chat: 'http://127.0.0.1:4400',
+ openre: 'http://127.0.0.1:4500',
};
};
for (const [id, origin] of Object.entries(expected)) {
for (const [id, origin] of Object.entries(expected)) {
const a = registry.get(id);
const a = registry.get(id);