openvibers/openvibe.network Commits
The ADR-033 sweep answers: Zone and Tools hold a person's rows too (#435)
Changes
@@@ -160,7 +160,11 @@ const DEFAULT_GRANTS = [// (its readers' lists; News#147), Run since 2026-10-30 (its jobs and runs; Run#115), Search since 2026-10-30 (its saved// searches and documents; Search#145), Sources since 2026-10-30 (its items and feeds; Sources#146) and Events since// 2026-10-30 (the bus itself keeps the events a person caused; Events#163). Each subscribed before this grant.-- ...['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events'].flatMap((svc) => [++ // Zone since 2026-10-30 (the telemetry samples that name a person; Zone#87) and Tools since 2026-10-30 (the++ // tool jobs a person owns; Tools#TBD): the two services the sweep found still holding a person's rows without++ // a way to ask for them. Zone subscribes to the account topics at its next boot; Tools already subscribes++ // for the sign-out cutoffs.++ ...['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events', 'zone', 'tools'].flatMap((svc) => [[svc, 'network.account.export.contribute', SELF_AUDIENCE, []],[svc, 'network.account.deletion.confirm', SELF_AUDIENCE, []],]),@@@ -93,11 +93,11 @@ const server = http.createServer(app);// ── Export ──const seeded = await accountData.expectedServices(db, 'network.account.export.contribute');-- assert.deepStrictEqual(seeded, ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'chat', 'codes', 'community', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'games', 'help', 'host', 'inventory', 'live', 'media', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work'],-- 'the holders of the contribute grant: the skeleton services answer too since 2026-10-08 and the older ones since 2026-10-09 (openvibe-sdk/account-data); Codes and Play since 2026-10-14 (run tasks; scores and unlocks); Space again since 2026-10-16 (its spaces); Billing since 2026-10-17 (money records); Reviews since 2026-10-17 (members\' reviews); Host since 2026-10-19 (the console and benchmarks); Meme since 2026-10-28 (votes, captions and reports), Vision and Exchange since 2026-10-28 (answers and checks; listings, installs and offers), Fun since 2026-10-28 (quests, plans, votes, checks, badges, rewards and reports), Cam since 2026-10-28 (cameras, grants, photos and stills), Bench since 2026-10-28 (tasks, rounds, entries, judgements and evals); AI, Coupons, News and Sources since 2026-10-30 (the ADR-033 sweep: their conversations and runs, their claims and coupons, their readers\' lists and their items and feeds)');++ assert.deepStrictEqual(seeded, ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'chat', 'codes', 'community', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'games', 'help', 'host', 'inventory', 'live', 'media', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'tools', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work', 'zone'],++ 'the holders of the contribute grant: the skeleton services answer too since 2026-10-08 and the older ones since 2026-10-09 (openvibe-sdk/account-data); Codes and Play since 2026-10-14 (run tasks; scores and unlocks); Space again since 2026-10-16 (its spaces); Billing since 2026-10-17 (money records); Reviews since 2026-10-17 (members\' reviews); Host since 2026-10-19 (the console and benchmarks); Meme since 2026-10-28 (votes, captions and reports), Vision and Exchange since 2026-10-28 (answers and checks; listings, installs and offers), Fun since 2026-10-28 (quests, plans, votes, checks, badges, rewards and reports), Cam since 2026-10-28 (cameras, grants, photos and stills), Bench since 2026-10-28 (tasks, rounds, entries, judgements and evals); AI, Coupons, News and Sources since 2026-10-30 (the ADR-033 sweep: their conversations and runs, their claims and coupons, their readers\' lists and their items and feeds), Zone and Tools since 2026-10-30 (the telemetry they keep and the tool jobs a person owns)');// The scenarios below follow five services; the newer ones are set aside here, exactly as an operator would// revoke a service's grant (the same rows, the same revoked_at).-- for (const svc of ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'codes', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'help', 'host', 'inventory', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work']) {++ for (const svc of ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'codes', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'help', 'host', 'inventory', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'tools', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work', 'zone']) {for (const cap of ['network.account.export.contribute', 'network.account.deletion.confirm']) {await db.prepare('UPDATE principal_grants SET revoked_at = ov_now() WHERE client_id = ? AND capability = ? AND revoked_at IS NULL').run(svc, cap);}@@@ -5,7 +5,8 @@** The three that subscribe to the two account topics themselves, through openvibe-sdk/account-data (startSubscriptions* creates the subscription on the bus), also hold events.subscription.manage on openvibe.events: Run (its jobs and-- * runs), Sources (its items and feeds) and Events (the bus itself keeps the events a person caused).++ * runs), Sources (its items and feeds) and Events (the bus itself keeps the events a person caused). Zone (its++ * telemetry) subscribes that way too, and Tools already subscribed for the sign-out cutoffs.** node test/adr033-sweep-grants.test.js*/@@@ -15,7 +16,7 @@ const principals = require('../server/identity/principals');const holds = (svc, cap, aud) => principals.DEFAULT_GRANTS.some((g) => g[0] === svc && g[1] === cap && g[2] === aud);--for (const svc of ['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events']) {++for (const svc of ['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events', 'zone', 'tools']) {assert.ok(holds(svc, 'network.account.export.contribute', principals.SELF_AUDIENCE), `${svc} answers the account export`);assert.ok(holds(svc, 'network.account.deletion.confirm', principals.SELF_AUDIENCE), `${svc} confirms the account deletion`);}
@@ -160,7 +160,11 @@ const DEFAULT_GRANTS = [
@@ -160,7 +160,11 @@ const DEFAULT_GRANTS = [
// (its readers' lists; News#147), Run since 2026-10-30 (its jobs and runs; Run#115), Search since 2026-10-30 (its saved
// (its readers' lists; News#147), Run since 2026-10-30 (its jobs and runs; Run#115), Search since 2026-10-30 (its saved
// searches and documents; Search#145), Sources since 2026-10-30 (its items and feeds; Sources#146) and Events since
// searches and documents; Search#145), Sources since 2026-10-30 (its items and feeds; Sources#146) and Events since
// 2026-10-30 (the bus itself keeps the events a person caused; Events#163). Each subscribed before this grant.
// 2026-10-30 (the bus itself keeps the events a person caused; Events#163). Each subscribed before this grant.
- ...['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events'].flatMap((svc) => [
+ // Zone since 2026-10-30 (the telemetry samples that name a person; Zone#87) and Tools since 2026-10-30 (the
+ // tool jobs a person owns; Tools#TBD): the two services the sweep found still holding a person's rows without
+ // a way to ask for them. Zone subscribes to the account topics at its next boot; Tools already subscribes
+ // for the sign-out cutoffs.
+ ...['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events', 'zone', 'tools'].flatMap((svc) => [
[svc, 'network.account.export.contribute', SELF_AUDIENCE, []],
[svc, 'network.account.export.contribute', SELF_AUDIENCE, []],
[svc, 'network.account.deletion.confirm', SELF_AUDIENCE, []],
[svc, 'network.account.deletion.confirm', SELF_AUDIENCE, []],
]),
]),
@@ -93,11 +93,11 @@ const server = http.createServer(app);
@@ -93,11 +93,11 @@ const server = http.createServer(app);
// ── Export ──
// ── Export ──
const seeded = await accountData.expectedServices(db, 'network.account.export.contribute');
const seeded = await accountData.expectedServices(db, 'network.account.export.contribute');
- assert.deepStrictEqual(seeded, ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'chat', 'codes', 'community', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'games', 'help', 'host', 'inventory', 'live', 'media', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work'],
- 'the holders of the contribute grant: the skeleton services answer too since 2026-10-08 and the older ones since 2026-10-09 (openvibe-sdk/account-data); Codes and Play since 2026-10-14 (run tasks; scores and unlocks); Space again since 2026-10-16 (its spaces); Billing since 2026-10-17 (money records); Reviews since 2026-10-17 (members\' reviews); Host since 2026-10-19 (the console and benchmarks); Meme since 2026-10-28 (votes, captions and reports), Vision and Exchange since 2026-10-28 (answers and checks; listings, installs and offers), Fun since 2026-10-28 (quests, plans, votes, checks, badges, rewards and reports), Cam since 2026-10-28 (cameras, grants, photos and stills), Bench since 2026-10-28 (tasks, rounds, entries, judgements and evals); AI, Coupons, News and Sources since 2026-10-30 (the ADR-033 sweep: their conversations and runs, their claims and coupons, their readers\' lists and their items and feeds)');
+ assert.deepStrictEqual(seeded, ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'chat', 'codes', 'community', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'games', 'help', 'host', 'inventory', 'live', 'media', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'tools', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work', 'zone'],
+ 'the holders of the contribute grant: the skeleton services answer too since 2026-10-08 and the older ones since 2026-10-09 (openvibe-sdk/account-data); Codes and Play since 2026-10-14 (run tasks; scores and unlocks); Space again since 2026-10-16 (its spaces); Billing since 2026-10-17 (money records); Reviews since 2026-10-17 (members\' reviews); Host since 2026-10-19 (the console and benchmarks); Meme since 2026-10-28 (votes, captions and reports), Vision and Exchange since 2026-10-28 (answers and checks; listings, installs and offers), Fun since 2026-10-28 (quests, plans, votes, checks, badges, rewards and reports), Cam since 2026-10-28 (cameras, grants, photos and stills), Bench since 2026-10-28 (tasks, rounds, entries, judgements and evals); AI, Coupons, News and Sources since 2026-10-30 (the ADR-033 sweep: their conversations and runs, their claims and coupons, their readers\' lists and their items and feeds), Zone and Tools since 2026-10-30 (the telemetry they keep and the tool jobs a person owns)');
// The scenarios below follow five services; the newer ones are set aside here, exactly as an operator would
// The scenarios below follow five services; the newer ones are set aside here, exactly as an operator would
// revoke a service's grant (the same rows, the same revoked_at).
// revoke a service's grant (the same rows, the same revoked_at).
- for (const svc of ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'codes', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'help', 'host', 'inventory', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work']) {
+ for (const svc of ['actor', 'ai', 'bench', 'billing', 'blog', 'bot', 'cam', 'codes', 'coupons', 'deals', 'domains', 'exchange', 'food', 'fun', 'help', 'host', 'inventory', 'media-hub', 'meme', 'news', 'play', 'quest', 'rent', 'reviews', 'services', 'sources', 'space', 'tips', 'tools', 'trade', 'vip', 'vision', 'watch', 'wiki', 'work', 'zone']) {
for (const cap of ['network.account.export.contribute', 'network.account.deletion.confirm']) {
for (const cap of ['network.account.export.contribute', 'network.account.deletion.confirm']) {
await db.prepare('UPDATE principal_grants SET revoked_at = ov_now() WHERE client_id = ? AND capability = ? AND revoked_at IS NULL').run(svc, cap);
await db.prepare('UPDATE principal_grants SET revoked_at = ov_now() WHERE client_id = ? AND capability = ? AND revoked_at IS NULL').run(svc, cap);
}
}
@@ -5,7 +5,8 @@
@@ -5,7 +5,8 @@
*
*
* The three that subscribe to the two account topics themselves, through openvibe-sdk/account-data (startSubscriptions
* The three that subscribe to the two account topics themselves, through openvibe-sdk/account-data (startSubscriptions
* creates the subscription on the bus), also hold events.subscription.manage on openvibe.events: Run (its jobs and
* creates the subscription on the bus), also hold events.subscription.manage on openvibe.events: Run (its jobs and
- * runs), Sources (its items and feeds) and Events (the bus itself keeps the events a person caused).
+ * runs), Sources (its items and feeds) and Events (the bus itself keeps the events a person caused). Zone (its
+ * telemetry) subscribes that way too, and Tools already subscribed for the sign-out cutoffs.
*
*
* node test/adr033-sweep-grants.test.js
* node test/adr033-sweep-grants.test.js
*/
*/
@@ -15,7 +16,7 @@ const principals = require('../server/identity/principals');
@@ -15,7 +16,7 @@ const principals = require('../server/identity/principals');
const holds = (svc, cap, aud) => principals.DEFAULT_GRANTS.some((g) => g[0] === svc && g[1] === cap && g[2] === aud);
const holds = (svc, cap, aud) => principals.DEFAULT_GRANTS.some((g) => g[0] === svc && g[1] === cap && g[2] === aud);
-for (const svc of ['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events']) {
+for (const svc of ['ai', 'coupons', 'news', 'run', 'search', 'sources', 'events', 'zone', 'tools']) {
assert.ok(holds(svc, 'network.account.export.contribute', principals.SELF_AUDIENCE), `${svc} answers the account export`);
assert.ok(holds(svc, 'network.account.export.contribute', principals.SELF_AUDIENCE), `${svc} answers the account export`);
assert.ok(holds(svc, 'network.account.deletion.confirm', principals.SELF_AUDIENCE), `${svc} confirms the account deletion`);
assert.ok(holds(svc, 'network.account.deletion.confirm', principals.SELF_AUDIENCE), `${svc} confirms the account deletion`);
}
}