openvibers/openvibe.services Commits

Services: contracts 0.165 — Watch is the first authority that takes control requests (#55)

OP OpenVibers committed 30 days ago · 5dc7c20c82 · 4 files, +13 −8

Plan T13 step 10: Watch takes control requests (Watch#57, Contracts 0.165.0 `watch.resource.control`).

- Services enables control for an authority whose manifest lists an active `<id>.resource.control`. With the pin at 0.165, Watch is the first. A person's suspend, resume or delete of a watch in their project now reaches Watch instead of answering `resources.authority_unsupported`.
- Contracts pin 0.154 → 0.165.
- `contracts` test: the three planned capabilities (recipe run, usage and cost reads, Contracts 0.164) are listed and stay `planned`.
- `control` test: only Watch has an active control capability.

Network#183 grants `services` the capability for audience `openvibe.watch`.

**Tests:** suite 44/44.

Changes

ddiff --git a/package-lock.json b/package-lock.json
iindex 88db693..e7997b9 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.154.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.165.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.44.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.1.3",
"pg": "^8.23.0"
@@@ -890,9 +890,9 @@
}
},
"node_modules/openvibe-contracts": {
-- "version": "0.154.0",
-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.154.0",
-- "integrity": "sha512-QRGUnH85VczGeVDDNlogKjKYUd7/BJno0sHP7pycj8h/YcdnrzjbuAtsKErHTk7LY54zBBa1n7sKhRyRaBQ42A==",
++ "version": "0.165.0",
++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.165.0",
++ "integrity": "sha512-IfBo0pI0lAqSGvtjA7PWjzf2apWMOrY1wAvHB9miGUgVOsjlLbkE8ND8SSutExoLGmZRsf+pePcCw2QbGjTjIA==",
"license": "AGPL-3.0-only",
"dependencies": {
"ajv": "^8.17.1",
ddiff --git a/package.json b/package.json
iindex 346eff5..5b4d566 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.154.0",
++ "openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.165.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.44.0",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.1.3",
"pg": "^8.23.0"
ddiff --git a/test/contracts.test.js b/test/contracts.test.js
iindex bff245a..204ffd9 100644
---- a/test/contracts.test.js
++++ b/test/contracts.test.js
@@@ -32,7 +32,11 @@ const CONTROL = 'services.resource.control';
await check('its capabilities exist, are owned by services, and are the ones the API guards', async () => {
// services.resource.read (ADR-048, the resource index) is released too. It stays 'planned' until the
// contracts follow-up flips it after this ships, so only the two release capabilities are active.
-- assert.deepStrictEqual([...manifest.capabilities].sort(), [MANAGE, READ, RESOURCE_READ, CONTROL].sort());
++ // Contracts 0.164 also lists three planned capabilities (recipe run, usage and cost reads): declared, not served
++ // or guarded yet, so they stay planned here.
++ const PLANNED = ['services.recipe.run', 'services.usage.read', 'services.cost.read'];
++ assert.deepStrictEqual([...manifest.capabilities].sort(), [MANAGE, READ, RESOURCE_READ, CONTROL, ...PLANNED].sort());
++ for (const id of PLANNED) assert.strictEqual(contracts.capabilities.get(id).status, 'planned', `${id} is not guarded by this code`);
for (const id of [MANAGE, READ]) {
const c = contracts.capabilities.get(id);
assert.ok(c, id);
ddiff --git a/test/control.test.js b/test/control.test.js
iindex f1356d6..4478941 100644
---- a/test/control.test.js
++++ b/test/control.test.js
@@@ -84,10 +84,11 @@ function registryOf(list) {
const prj = ids.newId('project');
const object = resources.format({ service: 'media', project_id: prj, type: 'object', id: ids.newId('media') });
-- await check('every real authority without an active <id>.resource.control takes no control requests', async () => {
++ await check('only an authority with an active <id>.resource.control takes control requests (Watch, contracts 0.165)', async () => {
const real = createAuthorities(t.config, { log: { warn() {} } });
assert.ok(real.size() > 0);
-- for (const a of real.list()) assert.strictEqual(a.control, null, `${a.id} lists no active control capability in the pinned contracts`);
++ const TAKES = { watch: 'watch.resource.control' };
++ for (const a of real.list()) assert.strictEqual(a.control, TAKES[a.id] || null, `${a.id}: the control capability in the pinned contracts`);
});
await check('the gate: anonymous 401, no capability 403, an app token 403, a malformed request 400 — nothing forwarded', async () => {