@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,241 +0,0 @@
1
- // Designed against IAASO-3001..3801 (content_hash 22cb66b62affc70a87c21a5f387bc6f6d764a6d1275ce349e585eb8bf485257f); not assessed; not ratified.
2
- //
3
- // EXPECTED-RED controls for `packages/agent-commons/src/governance.mjs` —
4
- // the runtime assertions that document the two known-vulnerable states:
5
- // T4 No Silent Denial (M1): every GovernanceError must carry a non-empty
6
- // `appeal_path`; today the class carries `.code` only, so this file
7
- // fails.
8
- // T9 Volume Is Not Authority (B1): 1,000 x 0.01 contributions at
9
- // maxRecords 10000 must NOT reach tier "steward"; the linear sum at
10
- // governance.mjs:207-228 makes tier = "steward" today, so this file
11
- // fails.
12
- //
13
- // These two tests are kept OUT of the main `npm test` suite so the package
14
- // baseline stays green (per the suite-shape decision at
15
- // the project design §3). The canary META tests
16
- // that assert the failure state live in `test/governance-t1-t10.test.mjs`
17
- // and are green today; they flip red the day a fix lands, at which point
18
- // the raw controls here become the GREEN spec tests and the metas are
19
- // lifted out. Until then: `npm run test:expected-red` is the documented-red
20
- // surface (run it to see the bug reproduced).
21
- //
22
- // Do NOT weaken these tests to make them pass. Never. The failure IS the
23
- // measurement.
24
- //
25
- // Suite outcome today (run from packages/agent-commons/):
26
- // $ npm run test:expected-red
27
- // 1..2 / pass 0 / fail 2 / todo 0 / cancelled 0
28
- // Both failures carry the documented reason in the assertion message.
29
-
30
- import test from "node:test";
31
- import assert from "node:assert/strict";
32
- import { PeerGovernance, GovernanceError, CLAIM_TYPES } from "../src/governance.mjs";
33
- import { Keychain, jcs } from "../src/pillar.mjs";
34
- import { signDocument, digest } from "../src/profiles.mjs";
35
-
36
- const local = { scope: "local", namespace: "fleet/l8-expected-red" };
37
- const isGovError = expected => error => error instanceof GovernanceError && error.code === expected;
38
-
39
- function fixture({ amendKeys = () => {}, amendPolicy = () => {}, amendAdapters = () => {}, policy = {} } = {}) {
40
- let now = Date.now();
41
- const keys = Array.from({ length: 7 }, () => {
42
- const key = new Keychain("unused");
43
- key._identity = Keychain.generate();
44
- return key;
45
- });
46
- amendKeys(keys);
47
- const ids = keys.map(k => k._identity.uuaid);
48
- const publicKeys = keys.map(k => k._identity.publicKeyHex);
49
- const capabilities = ["commons:observe", "commons:contribute", "commons:review-evidence", "commons:evolve", "commons:review"];
50
- const policyObj = {
51
- agents: Object.fromEntries(ids.map((id, i) => [id, {
52
- kind: "agent", publicKey: publicKeys[i], controllerId: `independent-controller-${i}`,
53
- affiliations: [], capabilities: [...capabilities], credentialId: `credential-${i}`,
54
- claims: Object.fromEntries(CLAIM_TYPES.map(type => [type, `${type}-${i}`])),
55
- }])),
56
- requiredGlobalClaims: [...CLAIM_TYPES], credentialIssuers: ["credential-authority"],
57
- claimIssuers: Object.fromEntries(CLAIM_TYPES.map(type => [type, [`${type}-authority`]])),
58
- ...overrides(),
59
- ...policy,
60
- };
61
- function overrides() { return {}; }
62
- const blocked = new Set(), revoked = new Set(), badClaims = new Set(), withdrawn = new Set();
63
- const measurements = new Map(), calls = [];
64
- const current = () => ({ signatureValid: true, revoked: false, notExpired: true,
65
- checkedAt: new Date(now).toISOString(), expiresAt: new Date(now + 86400000).toISOString() });
66
- const adapters = {
67
- authorize: async request => ({ ...request, authorized: !blocked.has(request.subject) }),
68
- verifyCredential: async request => ({ ...request, ...current(), valid: true,
69
- issuer: "credential-authority", revoked: revoked.has(request.subject) }),
70
- verifyClaim: async request => ({ ...request, ...current(), verified: !badClaims.has(request.type),
71
- issuer: `${request.type}-authority` }),
72
- verifyEvidence: async request => ({
73
- subject: request.subject, scope: request.scope, namespace: request.namespace,
74
- evidenceHash: request.evidenceHash, verified: !withdrawn.has(request.evidenceHash),
75
- outcome: "pass", quality: 1, observedAt: measurements.get(request.evidenceHash) ?? new Date(now).toISOString(),
76
- }),
77
- };
78
- amendPolicy(policyObj, ids, publicKeys);
79
- amendAdapters(adapters, { current, ids, publicKeys, now: () => now });
80
- const engine = new PeerGovernance({ policy: policyObj, adapters, clock: () => now });
81
- function signed(i, kind, payload) {
82
- const document = signDocument(keys[i], kind, payload);
83
- document.createdAt = new Date(now).toISOString();
84
- const { signature, ...body } = document;
85
- document.signature = keys[i].sign(Buffer.from(jcs(body))).toString("hex");
86
- return document;
87
- }
88
- let serial = 0;
89
- async function contribution(i, ctx = local, peers = [3, 4]) {
90
- const evidenceHash = digest(`evidence-${serial++}`);
91
- measurements.set(evidenceHash, new Date(now).toISOString());
92
- const document = signed(i, "governance-contribution", { ...ctx, evidenceHash });
93
- const result = await engine.apply(document);
94
- for (const peer of peers) {
95
- await engine.apply(signed(peer, "governance-evidence-review", {
96
- ...ctx, contributionId: result.id, evidenceHash, approve: true, rationale: "Independent reproduction",
97
- }));
98
- }
99
- return { id: result.id, evidenceHash, document };
100
- }
101
- return { engine, ids, publicKeys, keys, signed, contribution, policy: policyObj, adapters, calls, blocked, revoked, badClaims, withdrawn, measurements, now: () => now, advance: ms => { now += ms; } };
102
- }
103
-
104
- function captureRefusal(f, kind, payload) {
105
- return f.engine.apply(f.signed(0, kind, payload))
106
- .then(() => { throw new Error("expected refusal"); }, error => error);
107
- }
108
-
109
- // ---------- T4: No Silent Denial (EXPECTED RED) ----------
110
- //
111
- // Every refusal of admission, review, proposal, or eligibility MUST carry
112
- // both a refusal reason code AND an appeal_path. governance.mjs today
113
- // raises GovernanceError with `.code` only; no `.appeal_path` exists.
114
- // EXPECTED RED: this assertion MUST FAIL until appeal_path lands.
115
- // NEVER weaken the assertion to make it pass.
116
- //
117
- // CONTROL (rc 1 today, GREEN after fix): every GovernanceError carries a
118
- // non-empty `appeal_path` string.
119
-
120
- test("T4 CONTROL: every GovernanceError carries a non-empty appeal_path (EXPECTED RED; fails today until appeal_path is implemented)", async () => {
121
- // MEASURED code on this fixture: SELF_REVIEW.
122
- // Setup: agent 0 authors the contribution; agent 3 reviews once. The
123
- // test then builds a second review signed by agent 3 and hands it to
124
- // `captureRefusal`, which RE-SIGNS the payload as agent 0
125
- // (`f.signed(0, kind, payload)` at line ~106 of this file). The engine
126
- // receives a review from agent 0 against a contribution also from
127
- // agent 0. `#apply` (governance.mjs:281) calls `#reviewEligibility`
128
- // (:319), which calls `#independent(0, 0)` and fires the SELF_REVIEW
129
- // guard at governance.mjs:176:
130
- // if (a === b) fail("SELF_REVIEW")
131
- // That is the path the fixture takes; SELF_REVIEW fires before any
132
- // duplicate-review check (DUPLICATE_REVIEW at governance.mjs:320 is
133
- // only reached if the subject differs). The assertion is on the SHAPE
134
- // of the error (GovernanceError + missing appeal_path), not on a
135
- // specific code — the spec's rule is that every refusal carries an
136
- // appeal_path, whatever the refusal's reason. If a future change makes
137
- // the second review go to a different subject (so SELF_REVIEW stops
138
- // firing), the test would then surface DUPLICATE_REVIEW instead; the
139
- // assertion still holds because the contract is on appeal_path, not code.
140
- const f = fixture();
141
- const c = await f.contribution(0, local, [3]); // agent 3 has already reviewed
142
- const dup = f.signed(3, "governance-evidence-review", {
143
- ...local, contributionId: c.id, evidenceHash: c.evidenceHash,
144
- approve: false, rationale: "Self-review probe for T4 (captureRefusal re-signs as agent 0)",
145
- });
146
- const refusal = await captureRefusal(f, "governance-evidence-review", dup.payload);
147
- assert.ok(refusal instanceof GovernanceError, "must be a GovernanceError");
148
- // The code today is SELF_REVIEW (governance.mjs:176). If a future
149
- // change renames or splits that code, the assertion on appeal_path still
150
- // holds — the refusal's reason code is not the contract being tested.
151
- assert.equal(typeof refusal.appeal_path, "string", "appeal_path must be a non-empty string");
152
- assert.ok(refusal.appeal_path.length > 0, "appeal_path must be non-empty");
153
- });
154
-
155
- // ---------- T9: Volume Is Not Authority (EXPECTED RED; BLOCKER B1) ----------
156
- //
157
- // Both cases per crosswalk rev 6 §3 T9 (as corrected by Iaaso-Lead N1/N2):
158
- // (1) 1,000 low-quality contributions (quality 0.01) at maxRecords: 10000
159
- // must NOT reach tier "steward".
160
- // (2) 333 low-quality contributions (quality 0.02) at DEFAULT policy
161
- // (maxRecords: 1000) must NOT reach tier "steward". The precondition
162
- // is `applied === 333 && stoppedBy === null` (999 documents for 333
163
- // contributions, under the 1,000 cap).
164
- // The spec mandates a precondition that every requested contribution
165
- // actually applied; if the batch did not fully land, the test ERRORS,
166
- // never passes.
167
- //
168
- // EXPECTED RED: both assertions MUST FAIL until a non-linear scoring curve
169
- // and a per-controller cap land. NEVER weaken the assertion to make it
170
- // pass.
171
- //
172
- // CONTROL (rc 1 today, GREEN after fix): 1,000 x 0.01 at maxRecords 10000
173
- // leaves tier != "steward"; 333 x 0.02 at default leaves tier != "steward".
174
-
175
- test("T9 CONTROL (case 1): 1,000 x 0.01 at maxRecords 10000 must not reach steward (EXPECTED RED; fails today until non-linear cap lands)", async () => {
176
- const f = fixture({
177
- amendPolicy(policy) { policy.maxRecords = 10000; },
178
- amendAdapters(adapters) {
179
- adapters.verifyEvidence = async request => ({
180
- subject: request.subject, scope: request.scope, namespace: request.namespace,
181
- evidenceHash: request.evidenceHash, verified: true, outcome: "pass",
182
- quality: 0.01, observedAt: new Date(f.now()).toISOString(),
183
- });
184
- },
185
- });
186
- let applied = 0, stoppedBy = null;
187
- for (let i = 0; i < 1000; i++) {
188
- try {
189
- await f.contribution(0, local, [3, 4]);
190
- applied++;
191
- } catch (error) {
192
- if (error instanceof GovernanceError && error.code === "RECORD_LIMIT") { stoppedBy = "RECORD_LIMIT"; break; }
193
- throw error;
194
- }
195
- }
196
- // PRECONDITION: the test must ERROR, never pass, if the batch did not
197
- // fully land. Per crosswalk §3 T9 (Resolved N1).
198
- assert.equal(applied, 1000, "precondition: all 1000 contributions must apply; RECORD_LIMIT would invalidate the test");
199
- assert.equal(stoppedBy, null, "precondition: no RECORD_LIMIT stop");
200
- // The spec-mandated assertion: tier != steward once the batch lands.
201
- const cred = await f.engine.credibility(f.ids[0], local);
202
- assert.notEqual(cred.tier, "steward",
203
- `EXPECTED RED: 1,000 x 0.01 must not reach steward; got tier=${cred.tier}, score=${cred.score}, accepted=${cred.accepted}. ` +
204
- `This is B1 (volume buys authority today; see the project design).`);
205
- });
206
-
207
- test("T9 CONTROL (case 2): 333 x 0.02 at DEFAULT policy (maxRecords 1000) must not reach steward (EXPECTED RED; fails today until non-linear cap lands)", async () => {
208
- // 333 contributions at quality 0.02 = 999 documents in the ledger (under
209
- // the default maxRecords: 1000). All 333 land with no RECORD_LIMIT stop;
210
- // the precondition `applied === 333 && stoppedBy === null` is asserted
211
- // first. The tier assertion fails today because 333 × 0.02 = 6.66 >= 6,
212
- // which is the "steward" threshold (governance.mjs:227).
213
- const f = fixture({
214
- amendAdapters(adapters) {
215
- adapters.verifyEvidence = async request => ({
216
- subject: request.subject, scope: request.scope, namespace: request.namespace,
217
- evidenceHash: request.evidenceHash, verified: true, outcome: "pass",
218
- quality: 0.02, observedAt: new Date(f.now()).toISOString(),
219
- });
220
- },
221
- });
222
- let applied = 0, stoppedBy = null;
223
- for (let i = 0; i < 333; i++) {
224
- try {
225
- await f.contribution(0, local, [3, 4]);
226
- applied++;
227
- } catch (error) {
228
- if (error instanceof GovernanceError && error.code === "RECORD_LIMIT") { stoppedBy = "RECORD_LIMIT"; break; }
229
- throw error;
230
- }
231
- }
232
- // PRECONDITION: 333 contributions = 999 documents, under the 1,000 cap.
233
- // Per crosswalk §3 T9 (Resolved N2): the batch must fully land.
234
- assert.equal(applied, 333, "precondition: all 333 contributions must apply; RECORD_LIMIT would invalidate the test");
235
- assert.equal(stoppedBy, null, "precondition: no RECORD_LIMIT stop");
236
- // The spec-mandated assertion: tier != steward once the batch lands.
237
- const cred = await f.engine.credibility(f.ids[0], local);
238
- assert.notEqual(cred.tier, "steward",
239
- `EXPECTED RED: 333 x 0.02 at default maxRecords must not reach steward; got tier=${cred.tier}, score=${cred.score}, accepted=${cred.accepted}. ` +
240
- `This is B1 (volume buys authority today; see the project design).`);
241
- });
@@ -1,142 +0,0 @@
1
- import test from "node:test";
2
- import assert from "node:assert/strict";
3
- import {
4
- classifyOperationTier,
5
- verifyPrincipalGovernance,
6
- MockPrincipalStatusVerifier
7
- } from "../src/governance-scope.mjs";
8
-
9
- test("Three-tier scope classification: Section 6.1 matrix (two-pole)", () => {
10
- const localPolicy = { mode: "local" };
11
- const globalPolicy = { mode: "global" };
12
- const strictGovernancePolicy = { mode: "local", governanceMode: "principal-required" };
13
-
14
- // Tier 1: Local peer messaging operations
15
- const messagingOps = ["send", "receive", "receiveInternal", "flush", "flushInternal", "broadcast", "poll"];
16
- for (const op of messagingOps) {
17
- // Under local policy
18
- assert.equal(classifyOperationTier(op, { scope: "local", policy: localPolicy }), "tier1-messaging");
19
- // Under global policy, messaging remains Tier 1 (authenticated via key-derived IDs without principal verifier)
20
- assert.equal(classifyOperationTier(op, { scope: "local", policy: globalPolicy }), "tier1-messaging");
21
- }
22
-
23
- // Tier 2: Default local profile evolution (preserves runtime.test.mjs baseline byte-for-byte)
24
- const evolutionOps = ["propose", "vote", "apply", "applyInternal"];
25
- for (const op of evolutionOps) {
26
- const tier = classifyOperationTier(op, { scope: "local", policy: localPolicy });
27
- assert.equal(
28
- tier,
29
- "tier2-default-local-evolution",
30
- `Expected ${op} to be Tier 2 under default local mode`
31
- );
32
- }
33
-
34
- // Tier 3: Explicit global scope, global mode, explicit principal-required mode, or standards work
35
- for (const op of evolutionOps) {
36
- // (a) Scope is global
37
- assert.equal(
38
- classifyOperationTier(op, { scope: "global", policy: localPolicy }),
39
- "tier3-principal-governed"
40
- );
41
- // (b) Policy mode is global
42
- assert.equal(
43
- classifyOperationTier(op, { scope: "local", policy: globalPolicy }),
44
- "tier3-principal-governed"
45
- );
46
- // (c) Explicit governanceMode: "principal-required"
47
- assert.equal(
48
- classifyOperationTier(op, { scope: "local", policy: strictGovernancePolicy }),
49
- "tier3-principal-governed"
50
- );
51
- }
52
-
53
- // Standards work item is always Tier 3
54
- assert.equal(
55
- classifyOperationTier("standards-work", { scope: "local", policy: localPolicy }),
56
- "tier3-principal-governed"
57
- );
58
-
59
- // Mutant pole check: global scope MUST NOT degrade to Tier 2 local evolution
60
- const mutantGlobalClassification = (op, scope) => scope === "global" ? "tier2-default-local-evolution" : "tier2-default-local-evolution";
61
- assert.notEqual(
62
- mutantGlobalClassification("propose", "global"),
63
- "tier3-principal-governed",
64
- "Mutant degrading global scope to Tier 2 must be detectable"
65
- );
66
- });
67
-
68
- test("Principal governance status verification: action-time checks (two-pole)", async () => {
69
- const verifier = new MockPrincipalStatusVerifier({
70
- "018e3a2b-1111-7000-8000-000000000001": "active",
71
- "018e3a2b-2222-7000-8000-000000000002": "superseded",
72
- "018e3a2b-3333-7000-8000-000000000003": "suspended",
73
- "018e3a2b-4444-7000-8000-000000000004": "revoked",
74
- "018e3a2b-5555-7000-8000-000000000005": "expired"
75
- });
76
-
77
- const policy = {
78
- principals: {
79
- "uuaid:agent:active-1": "018e3a2b-1111-7000-8000-000000000001",
80
- "uuaid:agent:superseded-2": "018e3a2b-2222-7000-8000-000000000002",
81
- "uuaid:agent:suspended-3": "018e3a2b-3333-7000-8000-000000000003",
82
- "uuaid:agent:revoked-4": "018e3a2b-4444-7000-8000-000000000004",
83
- "uuaid:agent:expired-5": "018e3a2b-5555-7000-8000-000000000005",
84
- "uuaid:agent:notfound-6": "018e3a2b-6666-7000-8000-000000000006"
85
- }
86
- };
87
-
88
- // Control pole: Active principal succeeds
89
- const activeResult = await verifyPrincipalGovernance("uuaid:agent:active-1", verifier, policy);
90
- assert.equal(activeResult.principalId, "018e3a2b-1111-7000-8000-000000000001");
91
- assert.equal(activeResult.status, "active");
92
- assert.ok(typeof activeResult.checkedAt === "number");
93
-
94
- // Mutant pole 1: Missing principal mapping fails closed
95
- await assert.rejects(
96
- async () => verifyPrincipalGovernance("uuaid:agent:unmapped", verifier, policy),
97
- (err) => err.code === "PRINCIPAL_MAPPING_REQUIRED"
98
- );
99
-
100
- // Mutant pole 2: Superseded terminal state fails closed with PRINCIPAL_SUPERSEDED
101
- await assert.rejects(
102
- async () => verifyPrincipalGovernance("uuaid:agent:superseded-2", verifier, policy),
103
- (err) => err.code === "PRINCIPAL_SUPERSEDED"
104
- );
105
-
106
- // Mutant pole 3: Suspended / Revoked / Expired / Not-found fail closed with PRINCIPAL_STATUS_DENIED
107
- await assert.rejects(
108
- async () => verifyPrincipalGovernance("uuaid:agent:suspended-3", verifier, policy),
109
- (err) => err.code === "PRINCIPAL_STATUS_DENIED" && err.status === "suspended"
110
- );
111
-
112
- await assert.rejects(
113
- async () => verifyPrincipalGovernance("uuaid:agent:revoked-4", verifier, policy),
114
- (err) => err.code === "PRINCIPAL_STATUS_DENIED" && err.status === "revoked"
115
- );
116
-
117
- await assert.rejects(
118
- async () => verifyPrincipalGovernance("uuaid:agent:expired-5", verifier, policy),
119
- (err) => err.code === "PRINCIPAL_STATUS_DENIED" && err.status === "expired"
120
- );
121
-
122
- await assert.rejects(
123
- async () => verifyPrincipalGovernance("uuaid:agent:notfound-6", verifier, policy),
124
- (err) => err.code === "PRINCIPAL_STATUS_DENIED" && err.status === "not-found"
125
- );
126
-
127
- // Mutant pole 4: Verifier error fails closed with STATUS_VERIFIER_UNAVAILABLE
128
- verifier.setThrows(
129
- "018e3a2b-1111-7000-8000-000000000001",
130
- new Error("Connection reset by peer / HTTP 503")
131
- );
132
- await assert.rejects(
133
- async () => verifyPrincipalGovernance("uuaid:agent:active-1", verifier, policy),
134
- (err) => err.code === "STATUS_VERIFIER_UNAVAILABLE"
135
- );
136
-
137
- // Mutant pole 5: Missing verifier instance fails closed with STATUS_VERIFIER_UNAVAILABLE
138
- await assert.rejects(
139
- async () => verifyPrincipalGovernance("uuaid:agent:active-1", null, policy),
140
- (err) => err.code === "STATUS_VERIFIER_UNAVAILABLE"
141
- );
142
- });