@armoriq/policy-ir 0.1.0

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.
@@ -0,0 +1,942 @@
1
+ // vectors/canonical.json
2
+ var canonical_default = [
3
+ {
4
+ name: "empty object",
5
+ input: {},
6
+ canonical: "{}"
7
+ },
8
+ {
9
+ name: "keys sorted bytewise",
10
+ input: {
11
+ "9": 6,
12
+ "10": 5,
13
+ b: 1,
14
+ a: 2,
15
+ B: 3,
16
+ _: 4
17
+ },
18
+ canonical: '{"10":5,"9":6,"B":3,"_":4,"a":2,"b":1}'
19
+ },
20
+ {
21
+ name: "nested and arrays keep order",
22
+ input: {
23
+ z: [
24
+ 3,
25
+ 1,
26
+ {
27
+ y: null,
28
+ x: [
29
+ true,
30
+ false
31
+ ]
32
+ }
33
+ ],
34
+ a: "x"
35
+ },
36
+ canonical: '{"a":"x","z":[3,1,{"x":[true,false],"y":null}]}'
37
+ },
38
+ {
39
+ name: "undefined members dropped, null kept",
40
+ input: {
41
+ b: null,
42
+ c: 0
43
+ },
44
+ canonical: '{"b":null,"c":0}'
45
+ },
46
+ {
47
+ name: "ascii escapes",
48
+ input: {
49
+ s: 'quote " backslash \\ tab newline \n \xE9 \u2713 \u{1F600}'
50
+ },
51
+ canonical: '{"s":"quote \\" backslash \\\\ tab \\t newline \\n \\u00e9 \\u2713 \\ud83d\\ude00"}'
52
+ },
53
+ {
54
+ name: "numbers",
55
+ input: {
56
+ i: 42,
57
+ f: 0.5,
58
+ neg: -1,
59
+ exp: 1e21,
60
+ small: 1e-7,
61
+ zero: 0,
62
+ negzero: 0
63
+ },
64
+ canonical: '{"exp":1e+21,"f":0.5,"i":42,"neg":-1,"negzero":0,"small":1e-7,"zero":0}'
65
+ },
66
+ {
67
+ name: "unicode key",
68
+ input: {
69
+ \u043A\u043B\u044E\u0447: 1,
70
+ key: 2
71
+ },
72
+ canonical: '{"key":2,"\\u043a\\u043b\\u044e\\u0447":1}'
73
+ }
74
+ ];
75
+
76
+ // vectors/hash.json
77
+ var hash_default = [
78
+ {
79
+ name: "hold on create_payment above 5000",
80
+ document: {
81
+ schemaVersion: "armor.policy.v2",
82
+ policyId: "11111111-1111-4111-8111-111111111111",
83
+ target: {
84
+ agent: "d5c85519-3b8e-4f1e-9d2a-000000000001",
85
+ mcpServers: [
86
+ "github"
87
+ ]
88
+ },
89
+ layer: "agent",
90
+ defaults: {
91
+ tools: "hold",
92
+ network: "block",
93
+ files: "allow",
94
+ skills: "allow"
95
+ },
96
+ capture: {
97
+ arguments: true,
98
+ redact: [
99
+ "*token*"
100
+ ],
101
+ maxBytesPerCall: 16384,
102
+ sample: 1
103
+ },
104
+ expiresAt: "never",
105
+ statements: [
106
+ {
107
+ id: "st-pay-hold",
108
+ subject: null,
109
+ match: {
110
+ tool: "create_payment",
111
+ keyTier: "exact",
112
+ order: 0
113
+ },
114
+ effect: "hold",
115
+ conditions: [
116
+ {
117
+ field: "args.amount",
118
+ op: "gt",
119
+ value: 5e3,
120
+ schemaBinding: {
121
+ schemaHash: "sha256:1111111111111111111111111111111111111111111111111111111111111111"
122
+ }
123
+ }
124
+ ],
125
+ approval: {
126
+ approvers: 2,
127
+ roles: [
128
+ "finance_lead"
129
+ ]
130
+ },
131
+ expiresAt: "never",
132
+ provenance: {
133
+ ruleKey: "create_payment",
134
+ variant: 0,
135
+ source: "yaml",
136
+ layer: "agent"
137
+ }
138
+ },
139
+ {
140
+ id: "st-files-ssh",
141
+ subject: null,
142
+ match: {
143
+ capability: "files"
144
+ },
145
+ effect: "block",
146
+ conditions: [
147
+ {
148
+ field: "path",
149
+ op: "glob",
150
+ value: "~/.ssh/**"
151
+ }
152
+ ],
153
+ expiresAt: "never",
154
+ provenance: {
155
+ ruleKey: "files.deny",
156
+ variant: 0,
157
+ source: "yaml",
158
+ layer: "agent"
159
+ }
160
+ }
161
+ ]
162
+ },
163
+ policyHash: "sha256:007f204da14735e58b74d23a4909ee972d53cc2c8bd293217b71cab3d7b292bb"
164
+ },
165
+ {
166
+ name: "org floor with no statements",
167
+ document: {
168
+ schemaVersion: "armor.policy.v2",
169
+ policyId: "22222222-2222-4222-8222-222222222222",
170
+ target: {
171
+ org: "*"
172
+ },
173
+ layer: "floor",
174
+ defaults: {
175
+ tools: "hold",
176
+ network: "block",
177
+ files: "allow",
178
+ skills: "allow"
179
+ },
180
+ capture: {
181
+ arguments: false,
182
+ redact: [],
183
+ maxBytesPerCall: 0,
184
+ sample: 0
185
+ },
186
+ expiresAt: "2027-01-01T00:00:00Z",
187
+ statements: []
188
+ },
189
+ policyHash: "sha256:02a98fe3c5263f505f72562a87154fc3bd67f561ffb0f264f7fb5b90bd3d65c4"
190
+ }
191
+ ];
192
+
193
+ // vectors/schema-hash-vectors.json
194
+ var schema_hash_vectors_default = {
195
+ _comment: [
196
+ "Golden vectors for the tool-inventory canonicalizer (Tool Inventory PRD T4, armoriq/conmap-auto#968).",
197
+ "Three implementations must agree byte-for-byte: conmap src/tool-inventory/canonical.ts,",
198
+ "armoriq-sdk-customer (python) and armoriq-sdk-customer-ts. conmap is the source of truth;",
199
+ "each SDK keeps a byte-identical copy of this file plus its sha256 in a sibling .sha256, and a",
200
+ "test in each repo asserts the file still hashes to it -- so changing a vector forces all three",
201
+ "copies to move together.",
202
+ "canonicalJson = sorted keys, compact separators, ensure_ascii escaping. This is NOT RFC 8785;",
203
+ "see the header of canonical.ts for why, and vector 5 for the number forms left outside the",
204
+ "agreed set."
205
+ ],
206
+ algorithm: {
207
+ canonicalJson: "sorted keys, no whitespace, ASCII-escaped (json.dumps sort_keys=True separators=(',',':') ensure_ascii=True)",
208
+ schemaHash: "'sha256:' + sha256_hex(canonicalJson(strip description/title only where they are annotation keywords (never as names under properties/patternProperties/$defs/definitions/dependentSchemas or strings in required, never inside enum/const/default/examples values), resolve local #/ $ref)); null when inputSchema is null",
209
+ manifestHash: "'sha256:' + sha256_hex(canonicalJson({name, description|null, annotations|{}, inputSchema|null}))"
210
+ },
211
+ vectors: [
212
+ {
213
+ id: 1,
214
+ name: "key-order-irrelevant",
215
+ note: "Object keys are sorted, so two spellings that differ only in key order produce identical bytes.",
216
+ inputSchema: {
217
+ type: "object",
218
+ required: [
219
+ "b"
220
+ ],
221
+ properties: {
222
+ b: {
223
+ type: "string"
224
+ },
225
+ a: {
226
+ type: "number"
227
+ }
228
+ }
229
+ },
230
+ schemaHash: "sha256:597b8b01f9b5b640dd6856455c6156c631bb3e36768be54f79f21c89392c064d",
231
+ equivalentSpellings: [
232
+ {
233
+ properties: {
234
+ a: {
235
+ type: "number"
236
+ },
237
+ b: {
238
+ type: "string"
239
+ }
240
+ },
241
+ required: [
242
+ "b"
243
+ ],
244
+ type: "object"
245
+ }
246
+ ]
247
+ },
248
+ {
249
+ id: 2,
250
+ name: "nested-description-and-title-stripped",
251
+ note: "description and title are removed wherever they are schema annotation keywords, so prose-only edits never move schemaHash. Equals vector 1.",
252
+ inputSchema: {
253
+ title: "Thing",
254
+ description: "top level prose",
255
+ type: "object",
256
+ required: [
257
+ "b"
258
+ ],
259
+ properties: {
260
+ a: {
261
+ type: "number",
262
+ description: "the a"
263
+ },
264
+ b: {
265
+ title: "B",
266
+ type: "string",
267
+ description: "the b"
268
+ }
269
+ }
270
+ },
271
+ schemaHash: "sha256:597b8b01f9b5b640dd6856455c6156c631bb3e36768be54f79f21c89392c064d",
272
+ equalsVector: 1
273
+ },
274
+ {
275
+ id: 3,
276
+ name: "local-ref-resolved",
277
+ note: "A local #/$defs pointer is inlined before hashing, so spelling a shape out and pointing at it hash the same.",
278
+ inputSchema: {
279
+ type: "object",
280
+ $defs: {
281
+ Id: {
282
+ type: "string",
283
+ pattern: "^[a-z]+$"
284
+ }
285
+ },
286
+ properties: {
287
+ id: {
288
+ $ref: "#/$defs/Id"
289
+ }
290
+ }
291
+ },
292
+ schemaHash: "sha256:ed8f92e2b3119b897b4c3fb2322e4a94aefb4e345b2520c95ef96459ff532073"
293
+ },
294
+ {
295
+ id: 4,
296
+ name: "unicode-including-astral-plane",
297
+ note: "Non-ASCII escapes as \\uXXXX; an astral-plane character (U+1F600, U+1F680) escapes as its UTF-16 surrogate pair, matching Python ensure_ascii and JS charCodeAt iteration. All keys here are ASCII on purpose: JS sorts keys by UTF-16 code unit and Python by code point, which differ for astral-plane KEYS, so those are outside the agreed set.",
298
+ inputSchema: {
299
+ type: "string",
300
+ enum: [
301
+ "caf\xE9",
302
+ "\u65E5\u672C\u8A9E",
303
+ "\u{1F600}"
304
+ ],
305
+ const: "na\xEFve \u{1F680}"
306
+ },
307
+ schemaHash: "sha256:bd1abce15a0b8bcd6e5c0571a22858e1e14d889ed9ffc68fc2c06f4c5c68be40"
308
+ },
309
+ {
310
+ id: 5,
311
+ name: "number-forms",
312
+ note: "Numbers are emitted by the host JSON writer, not RFC 8785. Integers and decimals are distinct canonical bytes.",
313
+ knownDivergence: 'A float-valued integer diverges across languages (Python json.dumps(1.0) -> "1.0", JSON.stringify(1.0) -> "1"), as does -0.0 (Python "-0.0", JS "0"). Neither appears in a real JSON Schema, and neither is in this vector: agreeing on them requires a shared number formatter, which is the RFC 8785 migration, not a patch here.',
314
+ inputSchema: {
315
+ type: "number",
316
+ multipleOf: 1,
317
+ minimum: 0,
318
+ maximum: 10,
319
+ default: 2.5,
320
+ exclusiveMinimum: -1
321
+ },
322
+ schemaHash: "sha256:bcafbb074da1b4c0217c2438646e132ab73398dc1570efd186017abdf21f5029"
323
+ },
324
+ {
325
+ id: 6,
326
+ name: "empty-object-schema",
327
+ note: "An empty schema {} is a real, hashable schema. It is NOT the same fact as 'no schema' (vector 7).",
328
+ inputSchema: {},
329
+ schemaHash: "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"
330
+ },
331
+ {
332
+ id: 7,
333
+ name: "null-schema-has-no-hash",
334
+ note: "No schema at all: schemaHash is null, never the hash of {} and never the hash of the string 'null'. FR-7 warns on exactly this row.",
335
+ inputSchema: null,
336
+ schemaHash: null,
337
+ manifestDoc: {
338
+ name: "unschemad_tool",
339
+ description: "declared with a name only"
340
+ },
341
+ manifestHash: "sha256:61f5054dde7e535542c2e04a739dc78d1341504f798c7642ab9ad29f1b456bee"
342
+ },
343
+ {
344
+ id: 8,
345
+ name: "array-order-is-significant",
346
+ note: "Canonicalization sorts object keys and never sequences: reordering prefixItems is a different schema.",
347
+ inputSchema: {
348
+ type: "array",
349
+ prefixItems: [
350
+ {
351
+ type: "string"
352
+ },
353
+ {
354
+ type: "number"
355
+ },
356
+ {
357
+ type: "boolean"
358
+ }
359
+ ],
360
+ items: {
361
+ anyOf: [
362
+ {
363
+ type: "null"
364
+ },
365
+ {
366
+ type: "string"
367
+ }
368
+ ]
369
+ }
370
+ },
371
+ schemaHash: "sha256:9dd8bbfb2bc524842d1203e4f914a5743cceaa228fcf328182f4bc9260fb747e"
372
+ },
373
+ {
374
+ id: 9,
375
+ name: "nested-required-arrays",
376
+ note: "required lists nested inside properties survive verbatim, order included, at every depth.",
377
+ inputSchema: {
378
+ type: "object",
379
+ required: [
380
+ "outer"
381
+ ],
382
+ properties: {
383
+ outer: {
384
+ type: "object",
385
+ required: [
386
+ "z",
387
+ "a"
388
+ ],
389
+ properties: {
390
+ z: {
391
+ type: "string"
392
+ },
393
+ a: {
394
+ type: "object",
395
+ required: [
396
+ "q"
397
+ ],
398
+ properties: {
399
+ q: {
400
+ type: "integer"
401
+ }
402
+ }
403
+ }
404
+ }
405
+ }
406
+ }
407
+ },
408
+ schemaHash: "sha256:864f94090821218ef480510c415eaac315715d2f8ee3be1cbc7517594b51ab13"
409
+ },
410
+ {
411
+ id: 10,
412
+ name: "booleans-nulls-and-escaped-strings",
413
+ note: "true/false/null literals, and a string carrying a quote, a backslash, a tab, a newline and a control character.",
414
+ inputSchema: {
415
+ type: "object",
416
+ additionalProperties: false,
417
+ deprecated: true,
418
+ properties: {
419
+ q: {
420
+ type: "string",
421
+ default: 'he said "hi" one\\two\nthree',
422
+ const: null
423
+ }
424
+ }
425
+ },
426
+ schemaHash: "sha256:f5cdf2e3025ce09cb931b6cc918484a14de97a057e9667874593f0a3bc50877c"
427
+ },
428
+ {
429
+ id: 11,
430
+ name: "argument-named-description-is-kept",
431
+ note: "`description` and `title` are stripped only as schema annotation keywords, never as argument names under `properties`, `required`, `patternProperties`, `$defs`, `definitions` or `dependentSchemas`. create_ticket(title, description, priority) must NOT hash like create_ticket(priority). The annotation on `priority` is stripped; the two argument names are kept. `equivalentSpellings` differs only in annotation prose and must hash identically; `distinctSpelling` drops the two arguments and must NOT.",
432
+ inputSchema: {
433
+ type: "object",
434
+ properties: {
435
+ title: {
436
+ type: "string",
437
+ title: "Title",
438
+ description: "Short summary"
439
+ },
440
+ description: {
441
+ type: "string",
442
+ description: "Long form body"
443
+ },
444
+ priority: {
445
+ type: "integer",
446
+ description: "P0-P3"
447
+ }
448
+ },
449
+ required: [
450
+ "title",
451
+ "description"
452
+ ]
453
+ },
454
+ schemaHash: "sha256:996c1f968a21b24a3f171a432a3de33257901beb2d172e3dfa3d345b7e3e6a3c",
455
+ equivalentSpellings: [
456
+ {
457
+ type: "object",
458
+ properties: {
459
+ title: {
460
+ type: "string"
461
+ },
462
+ description: {
463
+ type: "string",
464
+ title: "Body"
465
+ },
466
+ priority: {
467
+ type: "integer"
468
+ }
469
+ },
470
+ required: [
471
+ "title",
472
+ "description"
473
+ ]
474
+ }
475
+ ],
476
+ distinctSpelling: {
477
+ type: "object",
478
+ properties: {
479
+ priority: {
480
+ type: "integer"
481
+ }
482
+ }
483
+ }
484
+ },
485
+ {
486
+ id: 12,
487
+ name: "real-mcp-input-schema",
488
+ note: "A verbatim MCP tools/list inputSchema (GitHub MCP create_issue), prose included, with the manifestHash of the full tool entry.",
489
+ inputSchema: {
490
+ type: "object",
491
+ properties: {
492
+ owner: {
493
+ type: "string",
494
+ description: "Repository owner"
495
+ },
496
+ repo: {
497
+ type: "string",
498
+ description: "Repository name"
499
+ },
500
+ title: {
501
+ type: "string",
502
+ description: "Issue title"
503
+ },
504
+ body: {
505
+ type: "string",
506
+ description: "Issue body content"
507
+ },
508
+ assignees: {
509
+ type: "array",
510
+ items: {
511
+ type: "string"
512
+ },
513
+ description: "Usernames to assign"
514
+ },
515
+ labels: {
516
+ type: "array",
517
+ items: {
518
+ type: "string"
519
+ },
520
+ description: "Labels to apply"
521
+ },
522
+ milestone: {
523
+ type: "number",
524
+ description: "Milestone number"
525
+ }
526
+ },
527
+ required: [
528
+ "owner",
529
+ "repo",
530
+ "title"
531
+ ],
532
+ additionalProperties: false,
533
+ $schema: "http://json-schema.org/draft-07/schema#"
534
+ },
535
+ schemaHash: "sha256:b06130f66f945f4ca2bc4474340c7f934c5e7b10168978fb8f507ecc146c091b",
536
+ manifestDoc: {
537
+ name: "create_issue",
538
+ description: "Create a new issue in a GitHub repository",
539
+ annotations: {
540
+ readOnlyHint: false,
541
+ destructiveHint: false,
542
+ idempotentHint: false
543
+ },
544
+ inputSchema: {
545
+ type: "object",
546
+ properties: {
547
+ owner: {
548
+ type: "string",
549
+ description: "Repository owner"
550
+ },
551
+ repo: {
552
+ type: "string",
553
+ description: "Repository name"
554
+ },
555
+ title: {
556
+ type: "string",
557
+ description: "Issue title"
558
+ },
559
+ body: {
560
+ type: "string",
561
+ description: "Issue body content"
562
+ },
563
+ assignees: {
564
+ type: "array",
565
+ items: {
566
+ type: "string"
567
+ },
568
+ description: "Usernames to assign"
569
+ },
570
+ labels: {
571
+ type: "array",
572
+ items: {
573
+ type: "string"
574
+ },
575
+ description: "Labels to apply"
576
+ },
577
+ milestone: {
578
+ type: "number",
579
+ description: "Milestone number"
580
+ }
581
+ },
582
+ required: [
583
+ "owner",
584
+ "repo",
585
+ "title"
586
+ ],
587
+ additionalProperties: false,
588
+ $schema: "http://json-schema.org/draft-07/schema#"
589
+ }
590
+ },
591
+ manifestHash: "sha256:a0bc53dbf453b8c5860924781ddc912d1b118a64adb3ee4b5089bf599b936113"
592
+ },
593
+ {
594
+ id: 13,
595
+ name: "data-literals-are-not-schemas",
596
+ note: "The values of `enum`, `const`, `default` and `examples` are data, not schema nodes: a `title` or `description` key inside them is part of the value and is kept verbatim. `equivalentSpellings` reorders keys inside the literals only; `distinctSpelling` removes those keys from the literals and must NOT hash equal.",
597
+ inputSchema: {
598
+ type: "object",
599
+ properties: {
600
+ payload: {
601
+ type: "object",
602
+ default: {
603
+ title: "Untitled",
604
+ description: "",
605
+ priority: 2
606
+ },
607
+ examples: [
608
+ {
609
+ title: "First",
610
+ description: "Body"
611
+ }
612
+ ]
613
+ },
614
+ kind: {
615
+ type: "object",
616
+ enum: [
617
+ {
618
+ title: "bug"
619
+ },
620
+ {
621
+ title: "task"
622
+ }
623
+ ],
624
+ const: {
625
+ description: "fixed"
626
+ }
627
+ }
628
+ }
629
+ },
630
+ schemaHash: "sha256:cae41d7dfcc5d51cf9ce1756903979b1fc5754fa8e95a69d9e5bec5df0266dc8",
631
+ equivalentSpellings: [
632
+ {
633
+ properties: {
634
+ kind: {
635
+ const: {
636
+ description: "fixed"
637
+ },
638
+ enum: [
639
+ {
640
+ title: "bug"
641
+ },
642
+ {
643
+ title: "task"
644
+ }
645
+ ],
646
+ type: "object"
647
+ },
648
+ payload: {
649
+ examples: [
650
+ {
651
+ description: "Body",
652
+ title: "First"
653
+ }
654
+ ],
655
+ default: {
656
+ priority: 2,
657
+ description: "",
658
+ title: "Untitled"
659
+ },
660
+ type: "object"
661
+ }
662
+ },
663
+ type: "object"
664
+ }
665
+ ],
666
+ distinctSpelling: {
667
+ type: "object",
668
+ properties: {
669
+ payload: {
670
+ type: "object",
671
+ default: {
672
+ priority: 2
673
+ },
674
+ examples: [
675
+ {}
676
+ ]
677
+ },
678
+ kind: {
679
+ type: "object",
680
+ enum: [
681
+ {},
682
+ {}
683
+ ],
684
+ const: {}
685
+ }
686
+ }
687
+ }
688
+ }
689
+ ]
690
+ };
691
+
692
+ // vectors/evaluate.json
693
+ var evaluate_default = [
694
+ { id: "VE-1", name: "absent argument in when falls through to the next variant", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-pay-hold", subject: null, conditions: [{ field: "args.amount", op: "gt", value: 5e3, schemaBinding: { schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } }], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "hold", approval: { approvers: 2, roles: ["finance_lead"] } }, { id: "st-pay-allow", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 1, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 1 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: { recipient: "acme" }, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "allow", statementId: "st-pay-allow", layer: "agent", ruleKey: "create_payment" } },
695
+ { id: "VE-8", name: "hold carries its resolved approval", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-pay-hold", subject: null, conditions: [{ field: "args.amount", op: "gt", value: 5e3, schemaBinding: { schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } }], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "hold", approval: { approvers: 2, roles: ["finance_lead"] } }, { id: "st-pay-allow", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 1, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 1 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: { amount: 9e3 }, timestamp: "2026-09-18T12:00:00Z", schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, expect: { verdict: "hold", statementId: "st-pay-hold", layer: "agent", ruleKey: "create_payment", approval: { approvers: 2, roles: ["finance_lead"] }, obligations: [] } },
696
+ { id: "VE-2", name: "schema drift still evaluates by name and attaches schema_drift", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-pay-hold", subject: null, conditions: [{ field: "args.amount", op: "gt", value: 5e3, schemaBinding: { schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } }], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "hold", approval: { approvers: 2, roles: ["finance_lead"] } }, { id: "st-pay-allow", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 1, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 1 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: { amount: 9e3 }, timestamp: "2026-09-18T12:00:00Z", schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }, expect: { verdict: "hold", statementId: "st-pay-hold", layer: "agent", ruleKey: "create_payment", obligations: [{ type: "schema_drift", statementId: "st-pay-hold", bound: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", observed: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }] } },
697
+ { id: "VE-3", name: "exact key beats glob key", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-glob", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "mcp__github__*", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "mcp__github__*", keyTier: "glob", order: 0 }, effect: "allow" }, { id: "st-exact", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "mcp__github__create_issue", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "mcp__github__create_issue", keyTier: "exact", order: 0 }, effect: "hold" }] } }, input: { tool: "mcp__github__create_issue", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "hold", statementId: "st-exact", layer: "agent", ruleKey: "mcp__github__create_issue" } },
698
+ { id: "VE-3b", name: "longer glob beats shorter glob", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-short", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "mcp__*", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "mcp__*", keyTier: "glob", order: 0 }, effect: "allow" }, { id: "st-long", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "mcp__github__*", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "mcp__github__*", keyTier: "glob", order: 0 }, effect: "hold" }] } }, input: { tool: "mcp__github__delete_repo", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "hold", statementId: "st-long", layer: "agent", ruleKey: "mcp__github__*" } },
699
+ { id: "VE-4", name: "floor merge: files.deny blocks a Read the agent allows", bound: { floor: { schemaVersion: "armor.policy.v2", policyId: "p-floor", target: { org: "*" }, layer: "floor", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-ssh", subject: null, conditions: [{ field: "path", op: "glob", value: "**/.ssh/**" }], expiresAt: "never", provenance: { ruleKey: "files", variant: 0, source: "yaml", layer: "floor" }, match: { capability: "files" }, effect: "block" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-read", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "Read", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "Read", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "Read", arguments: { file_path: "/home/u/.ssh/id_rsa" }, timestamp: "2026-09-18T12:00:00Z", capabilities: ["files"], derived: { path: "/home/u/.ssh/id_rsa" } }, expect: { verdict: "block", statementId: "st-ssh", layer: "floor", ruleKey: "files" } },
700
+ { id: "VE-4b", name: "floor capability rule does not fire outside its path glob", bound: { floor: { schemaVersion: "armor.policy.v2", policyId: "p-floor", target: { org: "*" }, layer: "floor", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-ssh", subject: null, conditions: [{ field: "path", op: "glob", value: "**/.ssh/**" }], expiresAt: "never", provenance: { ruleKey: "files", variant: 0, source: "yaml", layer: "floor" }, match: { capability: "files" }, effect: "block" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-read", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "Read", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "Read", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "Read", arguments: { file_path: "/home/u/notes.md" }, timestamp: "2026-09-18T12:00:00Z", capabilities: ["files"], derived: { path: "/home/u/notes.md" } }, expect: { verdict: "allow", statementId: "st-read", layer: "agent", ruleKey: "Read" } },
701
+ { id: "VE-5", name: "member overlay loosens the base for alice only", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-base", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "block" }, { id: "st-alice", subject: { membershipId: "m-alice" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: { amount: 10 }, timestamp: "2026-09-18T12:00:00Z", member: { membershipId: "m-alice" } }, expect: { verdict: "allow", statementId: "st-alice", layer: "member", ruleKey: "create_payment" } },
702
+ { id: "VE-5a", name: "everyone else keeps the base verdict", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-base", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "block" }, { id: "st-alice", subject: { membershipId: "m-alice" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: { amount: 10 }, timestamp: "2026-09-18T12:00:00Z", member: { membershipId: "m-carol" } }, expect: { verdict: "block", statementId: "st-base", layer: "agent", ruleKey: "create_payment" } },
703
+ { id: "VE-5b", name: "member overlay tightens the base for bob", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-base", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "search_transactions", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "search_transactions", keyTier: "exact", order: 0 }, effect: "allow" }, { id: "st-bob", subject: { email: "Bob@Example.com" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "search_transactions", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "search_transactions", keyTier: "exact", order: 0 }, effect: "block" }] } }, input: { tool: "search_transactions", arguments: {}, timestamp: "2026-09-18T12:00:00Z", member: { email: "bob@example.com" } }, expect: { verdict: "block", statementId: "st-bob", layer: "member", ruleKey: "search_transactions" } },
704
+ { id: "VE-5c", name: "org floor beats any member grant", bound: { floor: { schemaVersion: "armor.policy.v2", policyId: "p-floor", target: { org: "*" }, layer: "floor", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-floor", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "delete_all", variant: 0, source: "yaml", layer: "floor" }, match: { tool: "delete_all", keyTier: "exact", order: 0 }, effect: "block" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-alice", subject: { membershipId: "m-alice" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "delete_all", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "delete_all", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "delete_all", arguments: {}, timestamp: "2026-09-18T12:00:00Z", member: { membershipId: "m-alice" } }, expect: { verdict: "block", statementId: "st-floor", layer: "floor", ruleKey: "delete_all" } },
705
+ { id: "VE-5d", name: "expired member rule is skipped", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-base", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "block" }, { id: "st-alice", subject: { membershipId: "m-alice" }, conditions: [], expiresAt: "2026-01-01T00:00:00Z", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: {}, timestamp: "2026-09-18T12:00:00Z", member: { membershipId: "m-alice" } }, expect: { verdict: "block", statementId: "st-base", layer: "agent", ruleKey: "create_payment" } },
706
+ { id: "VE-5e", name: "member key specificity: membershipId beats email beats group", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-group", subject: { group: "finance" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "x", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "x", keyTier: "exact", order: 0 }, effect: "block" }, { id: "st-email", subject: { email: "alice@example.com" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "x", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "x", keyTier: "exact", order: 0 }, effect: "hold" }, { id: "st-id", subject: { membershipId: "m-alice" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "x", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "x", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "x", arguments: {}, timestamp: "2026-09-18T12:00:00Z", member: { membershipId: "m-alice", email: "alice@example.com", groups: ["finance"] } }, expect: { verdict: "allow", statementId: "st-id", layer: "member", ruleKey: "x" } },
707
+ { id: "VE-5f", name: "member key specificity: email beats group when no membershipId rule exists", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-group", subject: { group: "finance" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "x", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "x", keyTier: "exact", order: 0 }, effect: "block" }, { id: "st-email", subject: { email: "alice@example.com" }, conditions: [], expiresAt: "never", provenance: { ruleKey: "x", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "x", keyTier: "exact", order: 0 }, effect: "hold" }] } }, input: { tool: "x", arguments: {}, timestamp: "2026-09-18T12:00:00Z", member: { membershipId: "m-alice", email: "alice@example.com", groups: ["finance"] } }, expect: { verdict: "hold", statementId: "st-email", layer: "member", ruleKey: "x" } },
708
+ { id: "VE-6", name: "unknown tool goes to the most specific tools.default, never a wildcard", bound: { floor: { schemaVersion: "armor.policy.v2", policyId: "p-floor", target: { org: "*" }, layer: "floor", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-pay-hold", subject: null, conditions: [{ field: "args.amount", op: "gt", value: 5e3, schemaBinding: { schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } }], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "hold", approval: { approvers: 2, roles: ["finance_lead"] } }, { id: "st-pay-allow", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 1, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 1 }, effect: "allow" }] } }, input: { tool: "brand_new_tool", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "hold", statementId: null, layer: "agent", ruleKey: "tools.default" } },
709
+ { id: "VE-7", name: "variant order: first match wins", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-rm", subject: null, conditions: [{ field: "args.command", op: "regex", value: "\\brm\\s+-rf\\b" }], expiresAt: "never", provenance: { ruleKey: "Bash", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "Bash", keyTier: "exact", order: 0 }, effect: "block" }, { id: "st-safe", subject: null, conditions: [{ field: "program", op: "in", value: ["git", "ls", "rm"] }], expiresAt: "never", provenance: { ruleKey: "Bash", variant: 1, source: "yaml", layer: "agent" }, match: { tool: "Bash", keyTier: "exact", order: 1 }, effect: "allow" }] } }, input: { tool: "Bash", arguments: { command: "rm -rf /tmp/x" }, timestamp: "2026-09-18T12:00:00Z", derived: { program: "rm" } }, expect: { verdict: "block", statementId: "st-rm", layer: "agent", ruleKey: "Bash" } },
710
+ { id: "VE-9", name: "provenance names the deciding statement, key and variant", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-pay-hold", subject: null, conditions: [{ field: "args.amount", op: "gt", value: 5e3, schemaBinding: { schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } }], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "hold", approval: { approvers: 2, roles: ["finance_lead"] } }, { id: "st-pay-allow", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 1, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 1 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: { amount: 1 }, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "allow", statementId: "st-pay-allow", layer: "agent", ruleKey: "create_payment" } },
711
+ { id: "VE-11", name: "agent policy overrides group policy, loosening", bound: { group: { schemaVersion: "armor.policy.v2", policyId: "p-group", target: { group: "payments" }, layer: "group", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-g", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "group" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "hold" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-a", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "create_payment", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "create_payment", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "create_payment", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "allow", statementId: "st-a", layer: "agent", ruleKey: "create_payment" } },
712
+ { id: "VE-11b", name: "agent policy overrides group policy, tightening", bound: { group: { schemaVersion: "armor.policy.v2", policyId: "p-group", target: { group: "payments" }, layer: "group", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-g", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "Read", variant: 0, source: "yaml", layer: "group" }, match: { tool: "Read", keyTier: "exact", order: 0 }, effect: "allow" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-a", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "Read", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "Read", keyTier: "exact", order: 0 }, effect: "block" }] } }, input: { tool: "Read", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "block", statementId: "st-a", layer: "agent", ruleKey: "Read" } },
713
+ { id: "VE-12", name: "group policy applies when the agent policy is silent", bound: { group: { schemaVersion: "armor.policy.v2", policyId: "p-group", target: { group: "payments" }, layer: "group", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-g", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "search_transactions", variant: 0, source: "yaml", layer: "group" }, match: { tool: "search_transactions", keyTier: "exact", order: 0 }, effect: "hold" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-a", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "Read", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "Read", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "search_transactions", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "hold", statementId: "st-g", layer: "group", ruleKey: "search_transactions" } },
714
+ { id: "VE-13", name: "floor beats both group and agent", bound: { floor: { schemaVersion: "armor.policy.v2", policyId: "p-floor", target: { org: "*" }, layer: "floor", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-f", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "delete_all", variant: 0, source: "yaml", layer: "floor" }, match: { tool: "delete_all", keyTier: "exact", order: 0 }, effect: "block" }] }, group: { schemaVersion: "armor.policy.v2", policyId: "p-group", target: { group: "payments" }, layer: "group", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-g", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "delete_all", variant: 0, source: "yaml", layer: "group" }, match: { tool: "delete_all", keyTier: "exact", order: 0 }, effect: "allow" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-a", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "delete_all", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "delete_all", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "delete_all", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "block", statementId: "st-f", layer: "floor", ruleKey: "delete_all" } },
715
+ { id: "VE-13b", name: "a floor hold tightens an agent allow but yields to an agent block", bound: { floor: { schemaVersion: "armor.policy.v2", policyId: "p-floor", target: { org: "*" }, layer: "floor", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-f", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "deploy", variant: 0, source: "yaml", layer: "floor" }, match: { tool: "deploy", keyTier: "exact", order: 0 }, effect: "hold" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-a", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "deploy", variant: 0, source: "yaml", layer: "agent" }, match: { tool: "deploy", keyTier: "exact", order: 0 }, effect: "allow" }] } }, input: { tool: "deploy", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "hold", statementId: "st-f", layer: "floor", ruleKey: "deploy" } },
716
+ { id: "VE-14", name: "capability rule binds by tag only: tagged tool holds", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-destructive", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "destructive", variant: 0, source: "yaml", layer: "agent" }, match: { capability: "destructive" }, effect: "hold" }] } }, input: { tool: "mcp__jira__delete_issue", arguments: {}, timestamp: "2026-09-18T12:00:00Z", capabilities: ["destructive"] }, expect: { verdict: "hold", statementId: "st-destructive", layer: "agent", ruleKey: "destructive" } },
717
+ { id: "VE-14b", name: "capability rule binds by tag only: untagged tool on the same server gets tools.default", bound: { agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [{ id: "st-destructive", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "destructive", variant: 0, source: "yaml", layer: "agent" }, match: { capability: "destructive" }, effect: "hold" }] } }, input: { tool: "mcp__jira__list_issues", arguments: {}, timestamp: "2026-09-18T12:00:00Z", capabilities: [] }, expect: { verdict: "allow", statementId: null, layer: "agent", ruleKey: "tools.default" } },
718
+ { id: "VE-15", name: "an expired document contributes nothing", bound: { group: { schemaVersion: "armor.policy.v2", policyId: "p-group", target: { group: "payments" }, layer: "group", defaults: { tools: "hold", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "2026-01-01T00:00:00Z", statements: [{ id: "st-g", subject: null, conditions: [], expiresAt: "never", provenance: { ruleKey: "x", variant: 0, source: "yaml", layer: "group" }, match: { tool: "x", keyTier: "exact", order: 0 }, effect: "block" }] }, agent: { schemaVersion: "armor.policy.v2", policyId: "p-agent", target: { agent: "aaaaaaaa-0000-4000-8000-000000000001" }, layer: "agent", defaults: { tools: "allow", network: "block", files: "allow", skills: "allow" }, capture: { arguments: true, redact: ["*token*"], maxBytesPerCall: 16384, sample: 1 }, expiresAt: "never", statements: [] } }, input: { tool: "x", arguments: {}, timestamp: "2026-09-18T12:00:00Z" }, expect: { verdict: "allow", statementId: null, layer: "agent", ruleKey: "tools.default" } }
719
+ ];
720
+
721
+ // vectors/document.json
722
+ var document_default = [
723
+ { id: "VC-1", name: "the full v2 document parses and validates", yaml: `apiVersion: armor.io/v2
724
+ kind: Policy
725
+ metadata:
726
+ name: vector
727
+ orgId: 11111111-1111-4111-8111-111111111111
728
+ target:
729
+ agent: aaaaaaaa-0000-4000-8000-000000000001
730
+ mcpServers: [github]
731
+ spec:
732
+ tools:
733
+ default: hold
734
+ rules:
735
+ Read: allow
736
+ "mcp__github__*": allow
737
+ destructive: hold
738
+ file.write:
739
+ - when: {path: {glob: "**/*.tf"}}
740
+ action: hold
741
+ controls: [SOC2-CC8.1]
742
+ - action: allow
743
+ Bash:
744
+ - when: {command: {matches: '(^|\\s)rm\\s+-[a-zA-Z]*[rf]'}}
745
+ action: block
746
+ reason: recursive force delete
747
+ controls: [SOC2-CC6.1]
748
+ - when: {program: {in: [ls, grep, cat, git]}, writeRedirection: {eq: false}}
749
+ action: allow
750
+ - action: hold
751
+ create_payment:
752
+ - when: {args.amount: {gt: 5000}}
753
+ action: hold
754
+ approval: {approvers: 2, roles: [finance_lead]}
755
+ controls: [SOC2-CC6.1, SOC2-CC7.2]
756
+ - action: allow
757
+ files:
758
+ deny: ["~/.ssh/**", "**/.env*", "**/*.pem"]
759
+ allowOutsideWorkspace: false
760
+ network:
761
+ default: block
762
+ allow: ["*.github.com", {host: api.stripe.com, reason: payments}]
763
+ deny: [{host: 169.254.169.254, reason: AWS IMDS credentials endpoint}]
764
+ skills:
765
+ default: allow
766
+ hold: ["*:deploy*"]
767
+ members:
768
+ "alice@armoriq.io":
769
+ tools:
770
+ rules:
771
+ create_payment:
772
+ - action: allow
773
+ expiresAt: 2026-12-31T00:00:00Z
774
+ expiresAt: never
775
+ "bob@armoriq.io":
776
+ tools: {rules: {search_transactions: block}}
777
+ "team:interns":
778
+ tools: {default: block}
779
+ capture:
780
+ arguments: true
781
+ redact: ["*token*", "*secret*", "authorization"]
782
+ maxBytesPerCall: 16384
783
+ sample: 1.0
784
+ approvalDefaults: {approvers: 1, roles: [admin]}
785
+ `, expect: { errors: [], warnings: ["loosening_grant"] } },
786
+ { id: "VC-2", name: "an unknown key is a compile error", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n denyTools: [rm]\n", expect: { errors: ["unknown_key"], warnings: [] } },
787
+ { id: "VC-2b", name: "a v1 status field is an unknown key", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n status: active\n", expect: { errors: ["unknown_key"], warnings: [] } },
788
+ { id: "VC-5", name: "a variant after an unconditional one is unreachable", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n Bash:\n - action: allow\n - when: {args.command: {matches: 'rm'}}\n action: block\n", expect: { errors: ["unreachable_variant"], warnings: [] } },
789
+ { id: "VC-6", name: "a hold with no approver and no approvalDefaults is an error", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n create_payment: hold\n", expect: { errors: ["hold_without_approver"], warnings: [] } },
790
+ { id: "VC-6b", name: "a hold resolved by approvalDefaults is clean", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n create_payment: hold\n approvalDefaults: {approvers: 1, roles: [admin]}\n", expect: { errors: [], warnings: [] } },
791
+ { id: "VC-6c", name: "an approval that names nobody is unresolvable", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n create_payment:\n - action: hold\n approval: {approvers: 2}\n", expect: { errors: ["approval_unresolvable"], warnings: [] } },
792
+ { id: "VC-7", name: "a member grant that loosens the base is flagged for review", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n create_payment: block\n members:\n "alice@armoriq.io":\n tools: {rules: {create_payment: allow}}\n', expect: { errors: [], warnings: ["loosening_grant"] } },
793
+ { id: "VC-7t", name: "a member rule that tightens the base is not flagged", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n search_transactions: allow\n members:\n "bob@armoriq.io":\n tools: {rules: {search_transactions: block}}\n', expect: { errors: [], warnings: [] } },
794
+ { id: "VC-17", name: "device: local is accepted", yaml: `apiVersion: armor.io/v2
795
+ kind: Policy
796
+ metadata:
797
+ name: vector
798
+ target: {device: local}
799
+ spec:
800
+ tools:
801
+ default: hold
802
+ rules:
803
+ Read: allow
804
+ "mcp__github__*": allow
805
+ destructive: hold
806
+ file.write:
807
+ - when: {path: {glob: "**/*.tf"}}
808
+ action: hold
809
+ controls: [SOC2-CC8.1]
810
+ - action: allow
811
+ Bash:
812
+ - when: {command: {matches: '(^|\\s)rm\\s+-[a-zA-Z]*[rf]'}}
813
+ action: block
814
+ reason: recursive force delete
815
+ controls: [SOC2-CC6.1]
816
+ - when: {program: {in: [ls, grep, cat, git]}, writeRedirection: {eq: false}}
817
+ action: allow
818
+ - action: hold
819
+ create_payment:
820
+ - when: {args.amount: {gt: 5000}}
821
+ action: hold
822
+ approval: {approvers: 2, roles: [finance_lead]}
823
+ controls: [SOC2-CC6.1, SOC2-CC7.2]
824
+ - action: allow
825
+ files:
826
+ deny: ["~/.ssh/**", "**/.env*", "**/*.pem"]
827
+ allowOutsideWorkspace: false
828
+ network:
829
+ default: block
830
+ allow: ["*.github.com", {host: api.stripe.com, reason: payments}]
831
+ deny: [{host: 169.254.169.254, reason: AWS IMDS credentials endpoint}]
832
+ skills:
833
+ default: allow
834
+ hold: ["*:deploy*"]
835
+ capture:
836
+ arguments: true
837
+ redact: ["*token*", "*secret*", "authorization"]
838
+ maxBytesPerCall: 16384
839
+ sample: 1.0
840
+ approvalDefaults: {approvers: 1, roles: [admin]}
841
+ `, expect: { errors: [], warnings: [] } },
842
+ { id: "VC-17b", name: "target product is an unknown key", yaml: `apiVersion: armor.io/v2
843
+ kind: Policy
844
+ metadata:
845
+ name: vector
846
+ orgId: 11111111-1111-4111-8111-111111111111
847
+ target: {product: armorclaude}
848
+ spec:
849
+ tools:
850
+ default: hold
851
+ rules:
852
+ Read: allow
853
+ "mcp__github__*": allow
854
+ destructive: hold
855
+ file.write:
856
+ - when: {path: {glob: "**/*.tf"}}
857
+ action: hold
858
+ controls: [SOC2-CC8.1]
859
+ - action: allow
860
+ Bash:
861
+ - when: {command: {matches: '(^|\\s)rm\\s+-[a-zA-Z]*[rf]'}}
862
+ action: block
863
+ reason: recursive force delete
864
+ controls: [SOC2-CC6.1]
865
+ - when: {program: {in: [ls, grep, cat, git]}, writeRedirection: {eq: false}}
866
+ action: allow
867
+ - action: hold
868
+ create_payment:
869
+ - when: {args.amount: {gt: 5000}}
870
+ action: hold
871
+ approval: {approvers: 2, roles: [finance_lead]}
872
+ controls: [SOC2-CC6.1, SOC2-CC7.2]
873
+ - action: allow
874
+ files:
875
+ deny: ["~/.ssh/**", "**/.env*", "**/*.pem"]
876
+ allowOutsideWorkspace: false
877
+ network:
878
+ default: block
879
+ allow: ["*.github.com", {host: api.stripe.com, reason: payments}]
880
+ deny: [{host: 169.254.169.254, reason: AWS IMDS credentials endpoint}]
881
+ skills:
882
+ default: allow
883
+ hold: ["*:deploy*"]
884
+ members:
885
+ "alice@armoriq.io":
886
+ tools:
887
+ rules:
888
+ create_payment:
889
+ - action: allow
890
+ expiresAt: 2026-12-31T00:00:00Z
891
+ expiresAt: never
892
+ "bob@armoriq.io":
893
+ tools: {rules: {search_transactions: block}}
894
+ "team:interns":
895
+ tools: {default: block}
896
+ capture:
897
+ arguments: true
898
+ redact: ["*token*", "*secret*", "authorization"]
899
+ maxBytesPerCall: 16384
900
+ sample: 1.0
901
+ approvalDefaults: {approvers: 1, roles: [admin]}
902
+ `, expect: { errors: ["target_form", "unknown_key"], warnings: [] } },
903
+ { id: "VC-18", name: "products and precedence are local only", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\nprecedence: device-first\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n products:\n claude-code: {tools: {rules: {Bash: block}}}\n", expect: { errors: ["local_only_section", "local_only_section"], warnings: [] } },
904
+ { id: "VC-18b", name: "members is enterprise only", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\ntarget: {device: local}\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n members:\n "alice@armoriq.io": {tools: {rules: {Read: block}}}\n', expect: { errors: ["enterprise_only_section"], warnings: [] } },
905
+ { id: "VC-11c", name: "a condition takes exactly one operator", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n create_payment:\n - when: {args.amount: {gt: 5000, lt: 9000}}\n action: block\n", expect: { errors: ["condition_operator"], warnings: [] } },
906
+ { id: "VC-11d", name: "a numeric operator rejects a string operand", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n create_payment:\n - when: {args.amount: {gt: "5000"}}\n action: block\n', expect: { errors: ["condition_operand"], warnings: [] } },
907
+ { id: "VC-11e", name: "matches rejects a lookaround the Rego evaluator cannot run", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n default: hold\n rules:\n Bash:\n - when: {command: {matches: '(?=rm)'}}\n action: block\n", expect: { errors: ["condition_operand"], warnings: [] } },
908
+ { id: "VC-1b", name: "tools.default is required", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\n mcpServers: [github]\nspec:\n tools:\n rules:\n Read: allow\n", expect: { errors: ["expected_verdict"], warnings: [] } }
909
+ ];
910
+
911
+ // vectors/compile.json
912
+ var compile_default = [
913
+ { id: "VC-14", name: "schemaHash of the declared tool is bound on every args condition (FR-14)", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n create_payment:\n - when: {args.amount: {gt: 5000}}\n action: hold\n approval: {approvers: 2, roles: [finance_lead]}\n - action: allow\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: [], statementIds: ["st-create-payment-0", "st-create-payment-1"], bindings: { "st-create-payment-0": "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" } } },
914
+ { id: "VC-15", name: "an unknown control identifier compiles with a warning naming it", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n Read:\n - action: allow\n controls: [SOC2-CC6.1, NOT-A-CONTROL]\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: ["unknown_control"], statementIds: ["st-read-0"] } },
915
+ { id: "VC-8", name: "a rule key not in the inventory compiles with a warning", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n nonexistent_tool: block\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: ["unknown_tool_key"], statementIds: ["st-nonexistent-tool-0"] } },
916
+ { id: "VC-8b", name: "an observed-only tool compiles without a binding and says so", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n observed_only:\n - when: {args.x: {exists: true}}\n action: block\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: ["observed_only_tool"], bindings: { "st-observed-only-0": null } } },
917
+ { id: "VC-9", name: "an args key the schema does not declare compiles with a warning", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n create_payment:\n - when: {args.nonexistent: {gt: 5}}\n action: block\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: ["unknown_argument"] } },
918
+ { id: "VC-3", name: "exact and glob keys lower with their tier and the exact key binds", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n mcp__github__create_issue: hold\n "mcp__github__*": allow\n approvalDefaults: {approvers: 1, roles: [admin]}\n', inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: [], statementIds: ["st-mcp-github-create-issue-0", "st-mcp-github-0"] } },
919
+ { id: "VC-4", name: "two same-length globs matching one real tool is a compile error", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n "mcp__github__*": allow\n "*_create_issue": block\n approvalDefaults: {approvers: 1, roles: [admin]}\n', inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: ["ambiguous_glob"], warnings: [] } },
920
+ { id: "VC-3c", name: "a bare name declared on two owners asks for the qualified form", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n shared_tool: allow\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "shared_tool", owner: { type: "mcp_server", id: "srv-a", name: "a" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "shared_tool", owner: { type: "mcp_server", id: "srv-b", name: "b" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }], expect: { errors: ["ambiguous_tool_key"], warnings: [] } },
921
+ { id: "VC-14c", name: "a capability key compiles as a capability statement and the report lists uncovered tools", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n destructive: hold\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: [], statementIds: ["st-destructive-0"], report: { sections: { tools: "enforced" }, notCoveredByCapabilityRules: ["Read", "create_payment", "mcp__github__list_issues", "observed_only"] } } },
922
+ { id: "VC-11", name: "enforceability on an enterprise target: files and network argument-only, skills and secrets inert", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n approvalDefaults: {approvers: 1, roles: [admin]}\n files: {deny: ["~/.ssh/**"]}\n network: {default: block, allow: ["*.github.com"]}\n skills: {hold: ["*:deploy*"]}\n secrets: {envBlocklist: [AWS_SECRET_ACCESS_KEY]}\n', inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: [], statementIds: ["st-read-0", "st-files-block-0", "st-network-allow-0", "st-skills-hold-0", "st-secrets-block-0"], report: { sections: { tools: "enforced", files: "argument-only", network: "argument-only", skills: "inert", secrets: "inert" }, notCoveredByCapabilityRules: [] } } },
923
+ { id: "VC-11b", name: "enforceability on a local device: every section enforced", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\ntarget: {device: local}\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n approvalDefaults: {approvers: 1, roles: [admin]}\n files: {deny: ["~/.ssh/**"], allowOutsideWorkspace: false}\n secrets: {envBlocklist: [GITHUB_TOKEN]}\n', inventory: [], expect: { errors: [], warnings: ["unknown_tool_key"], statementIds: ["st-read-0", "st-files-block-0", "st-files-block-1", "st-secrets-block-0"], report: { sections: { tools: "enforced", files: "enforced", secrets: "enforced" }, notCoveredByCapabilityRules: [] } } },
924
+ { id: "VC-12", name: "a group target compiles with layer group", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n group: payments\nspec:\n tools:\n default: hold\n rules:\n Read: allow\n approvalDefaults: {approvers: 1, roles: [admin]}\n", inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: [], statementIds: ["st-read-0"] } },
925
+ { id: "VC-16", name: "member rule expiry earlier than its scope wins; scope expiry bounds a rule with none", yaml: 'apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\n orgId: 11111111-1111-4111-8111-111111111111\ntarget:\n agent: aaaaaaaa-0000-4000-8000-000000000001\nspec:\n tools:\n default: hold\n rules:\n create_payment: block\n approvalDefaults: {approvers: 1, roles: [admin]}\n members:\n "alice@armoriq.io":\n tools:\n rules:\n create_payment:\n - action: allow\n expiresAt: 2026-06-01T00:00:00Z\n Read: allow\n expiresAt: 2026-12-31T00:00:00Z\n', inventory: [{ name: "create_payment", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true }, { name: "Read", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", inputSchema: { type: "object", properties: { file_path: { type: "string" } } }, declared: true }, { name: "create_issue", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__create_issue", capabilities: ["destructive"] }, { name: "list_issues", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__list_issues", capabilities: [] }, { name: "delete_repo", owner: { type: "mcp_server", id: "srv-github", name: "github" }, schemaHash: "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", inputSchema: { type: "object", properties: { amount: { type: "number" }, recipient: { type: "string" } } }, declared: true, qualifiedName: "mcp__github__delete_repo", capabilities: ["destructive"] }, { name: "observed_only", owner: { type: "agent", id: "agent-1", name: "support-agent" }, schemaHash: null, declared: false }], expect: { errors: [], warnings: ["loosening_grant", "loosening_grant"], statementIds: ["st-create-payment-0", "st-create-payment-alice-armoriq-io-0", "st-read-alice-armoriq-io-0"], expiries: { "st-create-payment-alice-armoriq-io-0": "2026-06-01T00:00:00.000Z", "st-read-alice-armoriq-io-0": "2026-12-31T00:00:00.000Z" } } },
926
+ { id: "VC-18c", name: "under device-first a products overlay may only tighten", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\ntarget: {device: local}\nspec:\n tools:\n default: hold\n rules:\n Bash: hold\n approvalDefaults: {approvers: 1, roles: [admin]}\n products:\n claude-code: {tools: {rules: {Bash: allow}}}\n", inventory: [], expect: { errors: ["device_first_loosening"], warnings: ["loosening_grant", "unknown_tool_key", "unknown_tool_key"] } },
927
+ { id: "VC-18d", name: "under agent-first a products overlay may loosen, flagged for review", yaml: "apiVersion: armor.io/v2\nkind: Policy\nmetadata:\n name: vector\nprecedence: agent-first\ntarget: {device: local}\nspec:\n tools:\n default: hold\n rules:\n Bash: hold\n approvalDefaults: {approvers: 1, roles: [admin]}\n products:\n claude-code: {tools: {rules: {Bash: allow}}}\n", inventory: [], expect: { errors: [], warnings: ["loosening_grant", "unknown_tool_key", "unknown_tool_key"], statementIds: ["st-bash-0", "st-bash-claude-code-0"] } }
928
+ ];
929
+
930
+ // src/vectors.ts
931
+ var vectors = {
932
+ canonical: canonical_default,
933
+ hash: hash_default,
934
+ schemaHash: schema_hash_vectors_default,
935
+ evaluate: evaluate_default,
936
+ document: document_default,
937
+ compile: compile_default
938
+ };
939
+ export {
940
+ vectors
941
+ };
942
+ //# sourceMappingURL=vectors.js.map