openvibers/openvibe.network Commits

Network: grant the T18 principal actor.task.create (actor-task action) (#132)

OP OpenVibers committed 10 Oct 2026 · 0764850ab2 · 2 files, +28 −0

Plan T18 step 6: a watch's actor-task action gives OpenVibe.Actor a task for the watch's owner. Actor#25 (deployed) accepts a first-party service acting for a person: the service names them in `X-OV-Subject`, the task becomes the person's, and Actor records the service as `via`. The service needs `actor.task.create` for `openvibe.actor`.

- `server/identity/principals.js`: `['watch', 'actor.task.create', 'openvibe.actor', []]`, next to Watch's step 4 grants.
- `test/t18-grants.test.js`: Watch holds its event, identity, notification and Actor grants, each an active capability in the pinned contracts.

`principals`, `services-resource-grants` and the new test are green.

Changes

ddiff --git a/server/identity/principals.js b/server/identity/principals.js
iindex 9ffeaaac..83fd0961 100644
---- a/server/identity/principals.js
++++ b/server/identity/principals.js
@@@ -214,6 +214,9 @@ const DEFAULT_GRANTS = [
// (a usr_ subject) to Network's user id, then pushes as app 'watch' (openvibe-sdk/notifications).
['watch', 'identity.subject.resolve', SELF_AUDIENCE, []],
['watch', 'network.notifications.push', SELF_AUDIENCE, ['watch']],
++ // Plan T18 step 6: a watch's actor-task action gives Actor a task for the watch's owner. Watch names the owner in
++ // X-OV-Subject, so the task is the person's (their allowance and list) and Actor records Watch as `via`.
++ ['watch', 'actor.task.create', 'openvibe.actor', []],
// Plan T13: OpenVibe.Services merges every authority's resource index (ADR-048 section 3): it reads each one's
// GET /api/v1/resources under that authority's <id>.resource.read, with a token for that authority's audience.
['services', 'network.resource.read', SELF_AUDIENCE, []],
ddiff --git a/test/t18-grants.test.js b/test/t18-grants.test.js
nnew file mode 100644
iindex 00000000..b6b1a515
---- /dev/null
++++ b/test/t18-grants.test.js
@@@ -0,0 +1,25 @@
++/**
++ * OpenVibe.Watch's grants (plan T18): it publishes its events, resolves a watch's owner and pushes them a notification
++ * (step 4), and gives Actor a task for the owner (step 6, audience openvibe.actor). Each capability it holds is one
++ * the pinned contracts offer, active.
++ *
++ * node test/t18-grants.test.js
++ */
++'use strict';
++const assert = require('assert');
++const contracts = require('openvibe-contracts');
++const principals = require('../server/identity/principals');
++
++const rows = principals.DEFAULT_GRANTS.filter((g) => g[0] === 'watch');
++const held = new Set(rows.map((g) => `${g[1]}@${g[2]}`));
++for (const want of [
++ `identity.subject.resolve@${principals.SELF_AUDIENCE}`,
++ `network.notifications.push@${principals.SELF_AUDIENCE}`,
++]) assert.ok(held.has(want), `watch holds ${want}`);
++for (const g of rows) {
++ const cap = contracts.capabilities.get(g[1]);
++ assert.ok(cap && cap.status === 'active', `${g[1]} is an active capability`);
++}
++console.log(`t18 grants: ${rows.length}`);