openvibers/openvibe.services Commits
Services: contracts 0.165 — Watch is the first authority that takes control requests (#55)
Changes
@@@ -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",@@@ -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"@@@ -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);@@@ -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 () => {
@@ -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.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-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",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.1.3",
"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.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",
"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.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-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",
"openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.1.3",
"pg": "^8.23.0"
"pg": "^8.23.0"
@@ -32,7 +32,11 @@ const CONTROL = 'services.resource.control';
@@ -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 () => {
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
// 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.
// 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]) {
for (const id of [MANAGE, READ]) {
const c = contracts.capabilities.get(id);
const c = contracts.capabilities.get(id);
assert.ok(c, id);
assert.ok(c, id);
@@ -84,10 +84,11 @@ function registryOf(list) {
@@ -84,10 +84,11 @@ function registryOf(list) {
const prj = ids.newId('project');
const prj = ids.newId('project');
const object = resources.format({ service: 'media', project_id: prj, type: 'object', id: ids.newId('media') });
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() {} } });
const real = createAuthorities(t.config, { log: { warn() {} } });
assert.ok(real.size() > 0);
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 () => {
await check('the gate: anonymous 401, no capability 403, an app token 403, a malformed request 400 — nothing forwarded', async () => {