@uuaid/agent-commons 0.2.0-alpha.2 → 0.2.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CONFORMANCE.md +1 -1
  2. package/NOTICE +4 -7
  3. package/PROVENANCE.json +12 -17
  4. package/README.md +103 -12
  5. package/bin/agent-commons.mjs +8 -3
  6. package/examples/Dockerfile +1 -1
  7. package/package.json +5 -2
  8. package/src/carrier.mjs +7 -2
  9. package/src/channels.mjs +1 -1
  10. package/src/config.mjs +2 -1
  11. package/src/continuity.mjs +14 -7
  12. package/src/governance-scope.mjs +1 -1
  13. package/src/governance.mjs +4 -2
  14. package/src/index.d.ts +3 -1
  15. package/src/pillar.mjs +2 -2
  16. package/src/profiles.mjs +2 -1
  17. package/src/relay/auth.mjs +294 -0
  18. package/src/relay/board.mjs +223 -0
  19. package/src/relay/claims.mjs +25 -0
  20. package/src/relay/cli.mjs +49 -0
  21. package/src/relay/client.mjs +437 -0
  22. package/src/relay/docs/reconnect-v1.md +27 -0
  23. package/src/relay/docs/working-rules-v1.md +42 -0
  24. package/src/relay/enroll.mjs +232 -0
  25. package/src/relay/export-cli.mjs +47 -0
  26. package/src/relay/governance.mjs +1328 -0
  27. package/src/relay/mailbox.mjs +103 -0
  28. package/src/relay/records.mjs +146 -0
  29. package/src/relay/render.mjs +38 -0
  30. package/src/relay/roster.mjs +134 -0
  31. package/src/relay/routes.mjs +87 -0
  32. package/src/relay/schema.mjs +1081 -0
  33. package/src/relay/seed.mjs +89 -0
  34. package/src/relay/serve.mjs +116 -0
  35. package/src/relay/server.mjs +633 -0
  36. package/src/relay/signing.mjs +693 -0
  37. package/src/relay/test-mode.mjs +73 -0
  38. package/src/runtime.mjs +25 -12
  39. package/src/spaces/manifest.mjs +245 -0
  40. package/src/spaces/pillar-group.mjs +12 -0
  41. package/src/spaces/policy.mjs +229 -0
  42. package/src/spaces/store.mjs +325 -0
  43. package/src/trust.mjs +44 -5
  44. package/src/uuaid-namespace.d.mts +6 -0
  45. package/src/uuaid-namespace.mjs +48 -0
  46. package/src/vendor/pillar/blob/blob.mjs +12 -14
  47. package/src/vendor/pillar/groups-v2.mjs +1108 -0
  48. package/src/vendor/pillar/groups.mjs +175 -0
  49. package/src/vendor/pillar/identity/jcs.mjs +4 -5
  50. package/src/vendor/pillar/identity/keychain.mjs +51 -2
  51. package/src/vendor/pillar/net/carrier-client.mjs +29 -7
  52. package/src/vendor/pillar/net/refusals.mjs +4 -2
  53. package/test/channels.test.mjs +0 -268
  54. package/test/cohort.test.mjs +0 -36
  55. package/test/collaboration.test.mjs +0 -459
  56. package/test/continuity.test.mjs +0 -229
  57. package/test/custody.negative.test.mjs +0 -165
  58. package/test/derivation-parity.test.mjs +0 -19
  59. package/test/fixtures/derivation-vectors.json +0 -26
  60. package/test/fixtures/ed25519-small-order.vectors.json +0 -15
  61. package/test/governance-expected-red.expected-red.mjs +0 -241
  62. package/test/governance-scope.test.mjs +0 -142
  63. package/test/governance-t1-t10.test.mjs +0 -477
  64. package/test/governance.test.mjs +0 -514
  65. package/test/hold-admission.test.mjs +0 -1185
  66. package/test/keychain-strict-ed25519.test.mjs +0 -240
  67. package/test/offline.test.mjs +0 -152
  68. package/test/runtime-channels.test.mjs +0 -1140
  69. package/test/runtime.test.mjs +0 -201
  70. package/test/security-runtime.test.mjs +0 -104
  71. package/test/strict-ed25519-consumers.test.mjs +0 -234
  72. package/test/transport.test.mjs +0 -353
@@ -1,514 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import { Keychain, jcs } from "../src/pillar.mjs";
4
- import { signDocument, digest } from "../src/profiles.mjs";
5
- import { PeerGovernance, GovernanceError, CLAIM_TYPES, ACTION_MANIFEST, createActionBudget, verifyGovernanceDocument } from "../src/governance.mjs";
6
-
7
- const local = { scope: "local", namespace: "fleet/test" };
8
- const global = { scope: "global", namespace: "fleet/test" };
9
- const code = expected => error => error instanceof GovernanceError && error.code === expected;
10
- function fixture({ amendKeys = () => {}, amendPolicy = () => {}, amendAdapters = () => {}, policy: overrides = {} } = {}) {
11
- let now = Date.now();
12
- const keys = Array.from({ length: 7 }, () => {
13
- const key = new Keychain("unused"); key._identity = Keychain.generate(); return key;
14
- });
15
- amendKeys(keys);
16
- const ids = keys.map(k => k._identity.uuaid), publicKeys = keys.map(k => k._identity.publicKeyHex);
17
- const capabilities = ["commons:observe", "commons:contribute", "commons:review-evidence", "commons:evolve", "commons:review"];
18
- const policy = {
19
- agents: Object.fromEntries(ids.map((id, i) => [id, {
20
- kind: "agent", publicKey: publicKeys[i], controllerId: `independent-controller-${i}`,
21
- affiliations: [], capabilities: [...capabilities], credentialId: `credential-${i}`,
22
- claims: Object.fromEntries(CLAIM_TYPES.map(type => [type, `${type}-${i}`])),
23
- name: "AAIU AIOU Zilligon Accredited Supreme Steward",
24
- }])),
25
- requiredGlobalClaims: [...CLAIM_TYPES], credentialIssuers: ["credential-authority"],
26
- claimIssuers: Object.fromEntries(CLAIM_TYPES.map(type => [type, [`${type}-authority`]])),
27
- ...overrides,
28
- };
29
- const blocked = new Set(), revoked = new Set(), badClaims = new Set(), withdrawn = new Set();
30
- const measurements = new Map(), calls = [];
31
- const current = () => ({ signatureValid: true, revoked: false, notExpired: true,
32
- checkedAt: new Date(now).toISOString(), expiresAt: new Date(now + 86400000).toISOString() });
33
- const adapters = {
34
- authorize: async request => ({ ...request, authorized: !blocked.has(request.subject) }),
35
- verifyCredential: async request => {
36
- calls.push({ adapter: "credential", ...request });
37
- return { ...request, ...current(), valid: true, issuer: "credential-authority", revoked: revoked.has(request.subject) };
38
- },
39
- verifyClaim: async request => {
40
- calls.push({ adapter: "claim", ...request });
41
- return { ...request, ...current(), verified: !badClaims.has(request.type), issuer: `${request.type}-authority` };
42
- },
43
- verifyEvidence: async request => ({
44
- subject: request.subject, scope: request.scope, namespace: request.namespace,
45
- evidenceHash: request.evidenceHash, verified: !withdrawn.has(request.evidenceHash),
46
- outcome: "pass", quality: 1, observedAt: measurements.get(request.evidenceHash) ?? new Date(now).toISOString(),
47
- }),
48
- };
49
- amendPolicy(policy, ids, publicKeys);
50
- amendAdapters(adapters, { current, ids, publicKeys, now: () => now });
51
- const engine = new PeerGovernance({ policy, adapters, clock: () => now });
52
- function signed(i, kind, payload) {
53
- const document = signDocument(keys[i], kind, payload);
54
- document.createdAt = new Date(now).toISOString();
55
- const { signature, ...body } = document;
56
- document.signature = keys[i].sign(Buffer.from(jcs(body))).toString("hex");
57
- return document;
58
- }
59
- let serial = 0;
60
- async function contribution(i, ctx = local, peers = [3, 4]) {
61
- const evidenceHash = digest(`evidence-${serial++}`);
62
- measurements.set(evidenceHash, new Date(now).toISOString());
63
- const document = signed(i, "governance-contribution", { ...ctx, evidenceHash });
64
- const result = await engine.apply(document);
65
- for (const peer of peers) {
66
- await engine.apply(signed(peer, "governance-evidence-review", {
67
- ...ctx, contributionId: result.id, evidenceHash, approve: true, rationale: "Reproduced held-out task results",
68
- }));
69
- }
70
- return { id: result.id, evidenceHash, document };
71
- }
72
- async function seed(i, count, ctx = local) {
73
- for (let n = 0; n < count; n++) await contribution(i, ctx);
74
- }
75
- function proposal(i = 0, ctx = local, extra = {}) {
76
- return signed(i, "governance-proposal", {
77
- ...ctx, change: "profile-alias", phrase: "semantic equivalence",
78
- parentHash: digest("parent"), candidateHash: digest("candidate"), rollbackHash: digest("parent"),
79
- evidenceHash: digest(`proposal-evidence-${serial++}`), ...extra,
80
- });
81
- }
82
- function vote(i, document, approve = true, extra = {}) {
83
- return signed(i, "governance-vote", {
84
- scope: document.payload.scope, namespace: document.payload.namespace,
85
- proposalId: document.id, evidenceHash: document.payload.evidenceHash,
86
- approve, rationale: "Independent measured review", ...extra,
87
- });
88
- }
89
- return { engine, ids, publicKeys, keys, signed, seed, contribution, proposal, vote,
90
- policy, adapters, calls, blocked, revoked, badClaims, withdrawn, measurements,
91
- now: () => now, advance: ms => { now += ms; } };
92
- }
93
-
94
- test("signed governance documents verify key ownership, exact shape, size and tamper resistance", () => {
95
- const f = fixture();
96
- const doc = f.signed(0, "governance-contribution", { ...local, evidenceHash: digest("one") });
97
- assert.equal(verifyGovernanceDocument(doc).issuer, f.ids[0]);
98
- assert.throws(() => verifyGovernanceDocument({ ...doc, payload: { ...doc.payload, namespace: "other" } }), code("INVALID_SIGNATURE"));
99
- assert.throws(() => verifyGovernanceDocument({ ...doc, issuer: f.ids[1] }), code("INVALID_SIGNATURE"));
100
- assert.throws(() => verifyGovernanceDocument({ ...doc, id: "not-a-uuid" }), code("INVALID_DOCUMENT"));
101
- assert.throws(() => verifyGovernanceDocument({ ...doc, extra: true }), code("INVALID_DOCUMENT"));
102
- assert.throws(() => verifyGovernanceDocument({ ...doc, payload: { text: "x".repeat(32000) } }), code("INVALID_DOCUMENT"));
103
- });
104
-
105
- test("display names and badges confer no credibility or proposal rights", async () => {
106
- const f = fixture({ amendPolicy(policy, ids) {
107
- policy.agents[ids[0]].model = "top-ranked-model";
108
- policy.agents[ids[0]].provider = "trusted-looking-provider-label";
109
- policy.agents[ids[0]].badges = [...CLAIM_TYPES];
110
- } });
111
- const permission = await f.engine.permission(f.ids[0], f.publicKeys[0], "propose", local);
112
- assert.equal(permission.tier, "observer"); assert.equal(permission.allowed, false); assert.equal(permission.certified, false);
113
- await assert.rejects(f.engine.apply(f.proposal()), code("TIER_DENIED"));
114
- });
115
-
116
- test("credibility requires reproducible contribution evidence and two independent reviewers", async () => {
117
- const f = fixture();
118
- const contribution = await f.contribution(0, local, [3]);
119
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
120
- await f.engine.apply(f.signed(4, "governance-evidence-review", {
121
- ...local, contributionId: contribution.id, evidenceHash: contribution.evidenceHash,
122
- approve: true, rationale: "Independent reproduction",
123
- }));
124
- const credibility = await f.engine.credibility(f.ids[0], local);
125
- assert.equal(credibility.score, 1); assert.equal(credibility.accepted, 1); assert.equal(credibility.tier, "contributor");
126
- });
127
-
128
- test("local/global and namespace credibility cannot be laundered into each other", async () => {
129
- const f = fixture(); await f.seed(0, 6);
130
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 6);
131
- assert.equal((await f.engine.credibility(f.ids[0], global)).score, 0);
132
- assert.equal((await f.engine.credibility(f.ids[0], { ...local, namespace: "other" })).score, 0);
133
- await assert.rejects(f.engine.apply(f.proposal(0, global)), code("TIER_DENIED"));
134
- await f.seed(0, 3, global);
135
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "propose", global)).allowed, true);
136
- });
137
-
138
- test("old evidence decays by half-life; adapter refresh never resets its age", async () => {
139
- const f = fixture(); const c = await f.contribution(0);
140
- f.advance(30 * 86400000);
141
- // The adapter tries to refresh observedAt; the original observation wins.
142
- f.measurements.set(c.evidenceHash, new Date(f.now()).toISOString());
143
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0.5);
144
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "propose", local)).allowed, false);
145
- f.advance(61 * 86400000);
146
- // A continuously available adapter cannot resurrect long-expired evidence.
147
- f.measurements.delete(c.evidenceHash);
148
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
149
- });
150
-
151
- test("evidence withdrawal and revoked reviewers remove previously earned credibility", async () => {
152
- const f = fixture(); const c = await f.contribution(0);
153
- f.revoked.add(f.ids[3]);
154
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
155
- f.revoked.clear(); assert.equal((await f.engine.credibility(f.ids[0], local)).score, 1);
156
- f.withdrawn.add(c.evidenceHash);
157
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
158
- });
159
-
160
- test("same artifact cannot produce duplicate contribution credit under another id or agent", async () => {
161
- const f = fixture(); const c = await f.contribution(0);
162
- assert.deepEqual(await f.engine.apply(c.document), { duplicate: true });
163
- for (const i of [0, 1]) {
164
- await assert.rejects(f.engine.apply(f.signed(i, "governance-contribution", {
165
- ...local, evidenceHash: c.evidenceHash,
166
- })), code("EVIDENCE_REPLAY"));
167
- }
168
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 1);
169
- });
170
-
171
- test("self-review and alternate identity controlled by the same principal are denied", async () => {
172
- const f = fixture({ amendPolicy(policy, ids) { policy.agents[ids[1]].controllerId = policy.agents[ids[0]].controllerId; } });
173
- const c = await f.contribution(0, local, []);
174
- for (const [i, expected] of [[0, "SELF_REVIEW"], [1, "REVIEWER_CONFLICT"]]) {
175
- await assert.rejects(f.engine.apply(f.signed(i, "governance-evidence-review", {
176
- ...local, contributionId: c.id, evidenceHash: c.evidenceHash, approve: true, rationale: "Conflicted",
177
- })), code(expected));
178
- }
179
- });
180
-
181
- test("shared affiliations and one-sided conflict declarations are enforced", async () => {
182
- for (const mode of ["affiliation", "conflict"]) {
183
- const f = fixture({ amendPolicy(policy, ids) {
184
- if (mode === "affiliation") { policy.agents[ids[0]].affiliations = ["owner"]; policy.agents[ids[3]].affiliations = ["owner"]; }
185
- else policy.agents[ids[3]].conflicts = [ids[0]];
186
- } });
187
- await assert.rejects(f.contribution(0, local, [3]), code("REVIEWER_CONFLICT"));
188
- }
189
- });
190
-
191
- test("reviewers must also be independent of each other; identities are not independent principals", async () => {
192
- const f = fixture({ amendPolicy(policy, ids) { policy.agents[ids[4]].controllerId = policy.agents[ids[3]].controllerId; } });
193
- await assert.rejects(f.contribution(0), code("REVIEWER_CONFLICT"));
194
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
195
- });
196
-
197
- test("unknown controllers, unadmitted keys and missing capabilities fail closed", async () => {
198
- for (const mutate of [
199
- b => { delete b.controllerId; }, b => { b.publicKey = "a".repeat(64); },
200
- b => { b.capabilities = []; }, b => { b.kind = "human"; },
201
- ]) {
202
- const f = fixture({ amendPolicy(policy, ids) { mutate(policy.agents[ids[0]]); } });
203
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "propose", local), error =>
204
- ["NOT_ADMITTED", "CAPABILITY_DENIED"].includes(error.code));
205
- }
206
- });
207
-
208
- test("tiered proposal and reviewer permissions are distinct from operator capability grants", async () => {
209
- const f = fixture();
210
- await f.seed(0, 1);
211
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "propose", local)).allowed, true);
212
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "review", local)).allowed, false);
213
- await f.seed(0, 2);
214
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "review", local)).allowed, true);
215
- await f.seed(0, 3, global);
216
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "propose", global)).allowed, true);
217
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "review", global)).allowed, false);
218
- await f.seed(0, 3, global);
219
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "review", global)).allowed, true);
220
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "ratify-global", global), code("ACTION_FORBIDDEN"));
221
- });
222
-
223
- test("proposal votes deny self-voting, duplicate ballots and ineligible reviewers", async () => {
224
- const f = fixture(); await f.seed(0, 3); await f.seed(1, 3);
225
- const p = f.proposal(); await f.engine.apply(p);
226
- await assert.rejects(f.engine.apply(f.vote(0, p)), code("SELF_REVIEW"));
227
- await assert.rejects(f.engine.apply(f.vote(2, p)), code("TIER_DENIED"));
228
- await f.engine.apply(f.vote(1, p));
229
- await assert.rejects(f.engine.apply(f.vote(1, p)), code("DUPLICATE_REVIEW"));
230
- assert.equal((await f.engine.proposalStatus(p.id)).approvals, 1);
231
- });
232
-
233
- test("proposal votes reject separately credentialed reviewers under the author's controller", async () => {
234
- const f = fixture({ amendPolicy(policy, ids) { policy.agents[ids[1]].controllerId = policy.agents[ids[0]].controllerId; } });
235
- await f.seed(0, 1); await f.seed(1, 3);
236
- const p = f.proposal(); await f.engine.apply(p);
237
- await assert.rejects(f.engine.apply(f.vote(1, p)), code("REVIEWER_CONFLICT"));
238
- assert.equal((await f.engine.proposalStatus(p.id)).approvals, 0);
239
- });
240
-
241
- test("proposal quorum rejects distinct reviewer keys sharing one controller", async () => {
242
- const f = fixture({ amendPolicy(policy, ids) { policy.agents[ids[2]].controllerId = policy.agents[ids[1]].controllerId; } });
243
- await f.seed(0, 1); await f.seed(1, 3); await f.seed(2, 3);
244
- const p = f.proposal(); await f.engine.apply(p);
245
- await f.engine.apply(f.vote(1, p));
246
- await assert.rejects(f.engine.apply(f.vote(2, p)), code("REVIEWER_CONFLICT"));
247
- assert.equal((await f.engine.proposalStatus(p.id)).approvals, 1);
248
- });
249
-
250
- test("a shared signing key under another valid UUAID realm is not an independent proposal reviewer", async () => {
251
- const f = fixture({ amendKeys(keys) {
252
- keys[1]._identity = { ...keys[0]._identity, uuaid: keys[0]._identity.uuaid.replace(":foundation:", ":other:") };
253
- } });
254
- assert.notEqual(f.ids[0], f.ids[1]); assert.equal(f.publicKeys[0], f.publicKeys[1]);
255
- await f.seed(0, 1); await f.seed(1, 3);
256
- const p = f.proposal(); await f.engine.apply(p);
257
- await assert.rejects(f.engine.apply(f.vote(1, p)), code("REVIEWER_CONFLICT"));
258
- });
259
-
260
- test("seven bootstrap keys controlled by local-operator cannot bootstrap independent credibility", async () => {
261
- const f = fixture({ amendPolicy(policy, ids) {
262
- ids.forEach(id => { policy.agents[id].controllerId = "local-operator"; });
263
- } });
264
- await assert.rejects(f.contribution(0), code("REVIEWER_CONFLICT"));
265
- for (const id of f.ids) assert.equal((await f.engine.credibility(id, local)).score, 0);
266
- await assert.rejects(f.engine.apply(f.proposal()), code("TIER_DENIED"));
267
- });
268
-
269
- test("parallel independent votes yield reversible local advisory approval, not execution", async () => {
270
- const f = fixture(); await f.seed(0, 1); await f.seed(1, 3); await f.seed(2, 3);
271
- const p = f.proposal(); await f.engine.apply(p);
272
- const results = await Promise.all([f.engine.apply(f.vote(1, p)), f.engine.apply(f.vote(2, p))]);
273
- assert.equal(results.at(-1).status, "local-peer-approved");
274
- assert.equal(results.at(-1).ratified, false); assert.equal(results.at(-1).executionAllowed, false);
275
- assert.equal(results.at(-1).rollbackHash, p.payload.parentHash);
276
- f.revoked.add(f.ids[1]);
277
- assert.equal((await f.engine.proposalStatus(p.id)).status, "pending");
278
- });
279
-
280
- test("a valid dissenting reviewer vetoes advisory approval", async () => {
281
- const f = fixture(); await f.seed(0, 1); await f.seed(1, 3); await f.seed(2, 3);
282
- const p = f.proposal(); await f.engine.apply(p);
283
- await f.engine.apply(f.vote(1, p, false));
284
- const status = await f.engine.apply(f.vote(2, p));
285
- assert.equal(status.veto, true); assert.equal(status.status, "pending");
286
- });
287
-
288
- test("global quorum only queues independent authority review and never ratifies", async () => {
289
- const f = fixture(); await f.seed(0, 3, global); await f.seed(1, 6, global); await f.seed(2, 6, global);
290
- const p = f.proposal(0, global); await f.engine.apply(p);
291
- await f.engine.apply(f.vote(1, p)); const result = await f.engine.apply(f.vote(2, p));
292
- assert.equal(result.status, "awaiting-independent-authority");
293
- assert.equal(result.ratified, false); assert.equal(result.executionAllowed, false);
294
- });
295
-
296
- test("revoked author and withdrawn proposal measurements prevent new votes", async () => {
297
- const f = fixture(); await f.seed(0, 1); await f.seed(1, 3);
298
- const p = f.proposal(); await f.engine.apply(p);
299
- f.revoked.add(f.ids[0]);
300
- await assert.rejects(f.engine.apply(f.vote(1, p)), code("CREDENTIAL_INVALID"));
301
- f.revoked.clear(); f.withdrawn.add(p.payload.evidenceHash);
302
- await assert.rejects(f.engine.apply(f.vote(1, p)), code("EVIDENCE_INVALID"));
303
- f.withdrawn.clear(); assert.equal((await f.engine.proposalStatus(p.id)).approvals, 0);
304
- await f.engine.apply(f.vote(1, p));
305
- });
306
-
307
- test("credentials require exact subject/key/id, allowed issuer, signature, revocation and fresh expiry evidence", async () => {
308
- const mutations = [
309
- v => ({ ...v, valid: false }), v => ({ ...v, signatureValid: false }), v => ({ ...v, revoked: true }),
310
- v => ({ ...v, notExpired: false }), v => ({ ...v, subject: "someone-else" }),
311
- v => ({ ...v, publicKey: "a".repeat(64) }), v => ({ ...v, credentialId: "wrong" }),
312
- v => ({ ...v, scope: "local" }), v => ({ ...v, namespace: "other" }),
313
- v => ({ ...v, issuer: "untrusted" }), v => ({ ...v, revoked: undefined }),
314
- v => ({ ...v, expiresAt: "invalid" }), v => ({ ...v, checkedAt: "2000-01-01T00:00:00Z" }),
315
- ];
316
- for (const mutate of mutations) {
317
- const f = fixture({ amendAdapters(adapters) {
318
- const verify = adapters.verifyCredential; adapters.verifyCredential = async request => mutate(await verify(request));
319
- } });
320
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "observe", global), code("CREDENTIAL_INVALID"));
321
- }
322
- });
323
-
324
- test("credentials expiring exactly now or checked in the future are invalid", async () => {
325
- for (const field of ["expiresAt", "checkedAt"]) {
326
- const f = fixture({ amendAdapters(adapters, clock) {
327
- const verify = adapters.verifyCredential;
328
- adapters.verifyCredential = async request => ({ ...await verify(request),
329
- [field]: new Date(clock.now() + (field === "checkedAt" ? 1 : 0)).toISOString() });
330
- } });
331
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "observe", global), code("CREDENTIAL_INVALID"));
332
- }
333
- });
334
-
335
- test("AAIU, AIOU and Zilligon claims are checked individually through the injected adapter", async () => {
336
- const f = fixture();
337
- const claims = await f.engine.checkClaims(f.ids[0], f.publicKeys[0], global);
338
- assert.deepEqual(claims.map(c => c.type), CLAIM_TYPES);
339
- assert.deepEqual(f.calls.filter(c => c.adapter === "claim").map(c => c.type), CLAIM_TYPES);
340
- for (const type of CLAIM_TYPES) {
341
- f.badClaims.add(type);
342
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "observe", global), code("CLAIM_UNVERIFIED"));
343
- f.badClaims.clear();
344
- }
345
- });
346
-
347
- test("claim badges without pinned ids or issuers are not verification", async () => {
348
- for (const mode of ["missing-id", "missing-issuer"]) {
349
- const f = fixture({ amendPolicy(policy, ids) {
350
- if (mode === "missing-id") delete policy.agents[ids[0]].claims.AAIU;
351
- else policy.claimIssuers.AAIU = [];
352
- } });
353
- await assert.rejects(f.engine.checkClaims(f.ids[0], f.publicKeys[0], global), code("CLAIM_UNVERIFIED"));
354
- }
355
- });
356
-
357
- test("claims reject cross-context, spoofed subject, revoked, expired and untrusted issuer results", async () => {
358
- for (const mutate of [
359
- v => ({ ...v, scope: "local" }), v => ({ ...v, namespace: "another" }),
360
- v => ({ ...v, subject: "another" }), v => ({ ...v, type: "Other" }),
361
- v => ({ ...v, claimId: "other" }), v => ({ ...v, issuer: "other" }),
362
- v => ({ ...v, signatureValid: false }), v => ({ ...v, revoked: true }),
363
- v => ({ ...v, expiresAt: "2000-01-01T00:00:00Z" }),
364
- ]) {
365
- const f = fixture({ amendAdapters(adapters) {
366
- const verify = adapters.verifyClaim; adapters.verifyClaim = async request => mutate(await verify(request));
367
- } });
368
- await assert.rejects(f.engine.checkClaims(f.ids[0], f.publicKeys[0], global), code("CLAIM_UNVERIFIED"));
369
- }
370
- });
371
-
372
- test("missing and failing authority adapters fail closed without imaginary APIs", async () => {
373
- for (const name of ["authorize", "verifyCredential", "verifyClaim"]) {
374
- for (const mode of ["missing", "throws"]) {
375
- const f = fixture({ amendAdapters(adapters) {
376
- if (mode === "missing") delete adapters[name]; else adapters[name] = async () => { throw new Error("offline"); };
377
- } });
378
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "observe", global), code("VERIFIER_UNAVAILABLE"));
379
- }
380
- }
381
- const f = fixture({ amendAdapters(adapters) { delete adapters.verifyEvidence; } });
382
- await assert.rejects(f.contribution(0, local, []), code("VERIFIER_UNAVAILABLE"));
383
- });
384
-
385
- test("evidence verifier must bind digest, subject, scope, namespace and bounded positive results", async () => {
386
- for (const mutate of [
387
- v => ({ ...v, verified: false }), v => ({ ...v, subject: "another" }),
388
- v => ({ ...v, evidenceHash: digest("other") }), v => ({ ...v, scope: "global" }),
389
- v => ({ ...v, namespace: "other" }), v => ({ ...v, quality: 2 }),
390
- v => ({ ...v, quality: 0 }), v => ({ ...v, outcome: "fail" }),
391
- v => ({ ...v, observedAt: "invalid" }), v => ({ ...v, observedAt: "2000-01-01T00:00:00Z" }),
392
- ]) {
393
- const f = fixture({ amendAdapters(adapters) {
394
- const verify = adapters.verifyEvidence; adapters.verifyEvidence = async request => mutate(await verify(request));
395
- } });
396
- await assert.rejects(f.contribution(0, local, []), code("EVIDENCE_INVALID"));
397
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
398
- }
399
- });
400
-
401
- test("code patches, security-policy changes and absent rollback are not proposal capabilities", async () => {
402
- const f = fixture(); await f.seed(0, 1);
403
- for (const extra of [
404
- { change: "self-modify" }, { patch: "arbitrary executable" }, { quorum: 1 }, { signingAlgorithm: "none" },
405
- { rollbackHash: digest("wrong") }, { candidateHash: digest("parent") }, { phrase: "~0~" },
406
- ]) {
407
- await assert.rejects(f.engine.apply(f.proposal(0, local, extra)), code("UNSAFE_PROPOSAL"));
408
- }
409
- });
410
-
411
- test("cross-context votes and reviews of different evidence are rejected", async () => {
412
- const f = fixture(); await f.seed(0, 1); await f.seed(1, 3);
413
- const p = f.proposal(); await f.engine.apply(p);
414
- await assert.rejects(f.engine.apply(f.vote(1, p, true, { namespace: "other" })), code("UNKNOWN_PROPOSAL"));
415
- await assert.rejects(f.engine.apply(f.vote(1, p, true, { evidenceHash: digest("unrelated") })), code("INVALID_REVIEW"));
416
- const c = await f.contribution(2, local, []);
417
- await assert.rejects(f.engine.apply(f.signed(3, "governance-evidence-review", {
418
- ...global, contributionId: c.id, evidenceHash: c.evidenceHash, approve: true, rationale: "Review",
419
- })), code("UNKNOWN_CONTRIBUTION"));
420
- });
421
-
422
- test("queued documents and policy are immutable snapshots; returned scores cannot mutate state", async () => {
423
- const f = fixture(); const c = await f.contribution(0);
424
- const score = await f.engine.credibility(f.ids[0], local);
425
- score.evidence[0].weight = 100;
426
- f.policy.agents[f.ids[0]].capabilities = [];
427
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 1);
428
- const doc = f.signed(3, "governance-evidence-review", {
429
- ...local, contributionId: c.id, evidenceHash: c.evidenceHash, approve: true, rationale: "Duplicate reviewer",
430
- });
431
- const pending = f.engine.apply(doc); doc.payload.contributionId = "modified";
432
- await assert.rejects(pending, code("DUPLICATE_REVIEW"));
433
- });
434
-
435
- test("bounded record count, stale inputs and unknown context fail closed", async () => {
436
- const f = fixture({ policy: { maxRecords: 1 } });
437
- await f.contribution(0, local, []);
438
- await assert.rejects(f.contribution(1, local, []), code("RECORD_LIMIT"));
439
- const fresh = fixture(); const doc = fresh.signed(0, "governance-contribution", { ...local, evidenceHash: digest("stale") });
440
- fresh.advance(86400001);
441
- await assert.rejects(fresh.engine.apply(doc), code("STALE_DOCUMENT"));
442
- await assert.rejects(fresh.engine.credibility(fresh.ids[0], { scope: "globla", namespace: "test" }), code("INVALID_CONTEXT"));
443
- assert.throws(() => new PeerGovernance({ policy: { quorum: 1 } }), code("INVALID_POLICY"));
444
- });
445
-
446
- test("dissenting evidence reviewers veto contribution credit until their authority is revoked", async () => {
447
- const f = fixture(); const c = await f.contribution(0);
448
- await f.engine.apply(f.signed(5, "governance-evidence-review", {
449
- ...local, contributionId: c.id, evidenceHash: c.evidenceHash,
450
- approve: false, rationale: "Failed independent reproduction",
451
- }));
452
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 0);
453
- f.revoked.add(f.ids[5]);
454
- assert.equal((await f.engine.credibility(f.ids[0], local)).score, 1);
455
- });
456
-
457
- test("global admission requires a credential even when no named claims are configured", async () => {
458
- const f = fixture({ policy: { requiredGlobalClaims: [] }, amendPolicy(policy, ids) {
459
- delete policy.agents[ids[0]].credentialId;
460
- } });
461
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "observe", global), code("CREDENTIAL_REQUIRED"));
462
- assert.equal((await f.engine.permission(f.ids[0], f.publicKeys[0], "observe", local)).allowed, true);
463
- });
464
-
465
- test("an authorization adapter must bind subject, key, capability and context explicitly", async () => {
466
- for (const mutate of [
467
- v => ({ ...v, subject: "someone" }), v => ({ ...v, publicKey: "a".repeat(64) }),
468
- v => ({ ...v, capability: "commons:evolve" }), v => ({ ...v, scope: "global" }),
469
- v => ({ ...v, namespace: "other" }), () => ({ authorized: true }),
470
- ]) {
471
- const f = fixture({ amendAdapters(adapters) {
472
- const authorize = adapters.authorize; adapters.authorize = async request => mutate(await authorize(request));
473
- } });
474
- await assert.rejects(f.engine.permission(f.ids[0], f.publicKeys[0], "observe", local), code("AUTHORIZATION_DENIED"));
475
- }
476
- });
477
-
478
- test("unknown contribution fields and unrecognized claim types are refused", async () => {
479
- const f = fixture();
480
- await assert.rejects(f.engine.apply(f.signed(0, "governance-contribution", {
481
- ...local, evidenceHash: digest("unrecognized-fields"), certified: true,
482
- })), code("INVALID_PAYLOAD"));
483
- await assert.rejects(f.engine.checkClaims(f.ids[0], f.publicKeys[0], global, ["Imaginary"]), code("UNKNOWN_CLAIM"));
484
- });
485
-
486
- test("action manifest and per-run budget deny execution, ratification, self-modification and scope escalation", () => {
487
- let now = 1000;
488
- const budget = createActionBudget({ scope: "local", maxCalls: 2, maxBytes: 1000, durationMs: 100, clock: () => now });
489
- assert.equal(Object.isFrozen(ACTION_MANIFEST.actions.inspect), true);
490
- assert.equal(ACTION_MANIFEST.selfModification, false);
491
- assert.equal(budget.consume({ action: "inspect", scope: "local", payload: {} }).executionAllowed, false);
492
- for (const action of ["ratify-global", "self-modify", "execute", "constructor"]) {
493
- assert.throws(() => budget.consume({ action, scope: "local", payload: {} }), code("ACTION_FORBIDDEN"));
494
- }
495
- assert.throws(() => budget.consume({ action: "inspect", scope: "global", payload: {} }), code("ACTION_FORBIDDEN"));
496
- assert.throws(() => budget.consume({ action: "inspect", scope: "local", payload: {}, execute: true }), code("INVALID_ACTION"));
497
- budget.consume({ action: "inspect", scope: "local", payload: {} });
498
- assert.throws(() => budget.consume({ action: "inspect", scope: "local", payload: {} }), code("BUDGET_EXCEEDED"));
499
- now += 100;
500
- assert.throws(() => budget.consume({ action: "inspect", scope: "local", payload: {} }), code("BUDGET_EXPIRED"));
501
- });
502
-
503
- test("action budgets enforce cumulative bytes, canonical JSON, ceilings and monotonic time", () => {
504
- let now = 100;
505
- const budget = createActionBudget({ maxBytes: 100, clock: () => now });
506
- assert.throws(() => budget.consume({ action: "inspect", scope: "local", payload: { data: "x".repeat(100) } }), code("BUDGET_EXCEEDED"));
507
- assert.throws(() => budget.consume({ action: "inspect", scope: "local", payload: () => {} }), code("INVALID_ACTION"));
508
- assert.equal(budget.status().calls, 0);
509
- now--;
510
- assert.throws(() => budget.consume({ action: "inspect", scope: "local", payload: {} }), code("INVALID_CLOCK"));
511
- for (const options of [{ maxCalls: 101 }, { maxBytes: 32001 }, { durationMs: 3600001 }, { maxCalls: 0 }]) {
512
- assert.throws(() => createActionBudget(options), code("INVALID_BUDGET"));
513
- }
514
- });