caveat-cli 0.20.3 → 0.21.1

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,1077 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __caveat_createRequire } from 'node:module';
3
+ const require = __caveat_createRequire(import.meta.url);
4
+
5
+ // src/privateEvidence/validation.ts
6
+ import { createHash } from "node:crypto";
7
+ import { TextDecoder, isDeepStrictEqual } from "node:util";
8
+ import { Ajv2020 } from "ajv/dist/2020.js";
9
+ import { visit } from "jsonc-parser";
10
+
11
+ // src/contracts/factory-private-evidence/capability.v1.schema.json
12
+ var capability_v1_schema_default = {
13
+ $schema: "https://json-schema.org/draft/2020-12/schema",
14
+ $id: "urn:caveat:factory-private-evidence-capability:v1",
15
+ title: "Draft: Caveat official private evidence capability v1",
16
+ type: "object",
17
+ additionalProperties: false,
18
+ required: [
19
+ "schema",
20
+ "product",
21
+ "package_version",
22
+ "public_diagnostic_schema",
23
+ "private_protocol",
24
+ "transports",
25
+ "max_channel_bytes",
26
+ "operation_receipt"
27
+ ],
28
+ properties: {
29
+ schema: {
30
+ const: "caveat.factory_private_evidence_capability.v1"
31
+ },
32
+ product: {
33
+ const: "caveat"
34
+ },
35
+ package_version: {
36
+ type: "string",
37
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$",
38
+ maxLength: 128
39
+ },
40
+ public_diagnostic_schema: {
41
+ const: "caveat.native_factory_diagnostics.v1"
42
+ },
43
+ private_protocol: {
44
+ const: "caveat.factory_private_evidence.v1"
45
+ },
46
+ transports: {
47
+ type: "array",
48
+ maxItems: 2,
49
+ uniqueItems: true,
50
+ items: {
51
+ oneOf: [
52
+ {
53
+ type: "object",
54
+ additionalProperties: false,
55
+ required: [
56
+ "id",
57
+ "platforms",
58
+ "launch_paths"
59
+ ],
60
+ properties: {
61
+ id: {
62
+ const: "posix-fd-v1"
63
+ },
64
+ platforms: {
65
+ type: "array",
66
+ minItems: 1,
67
+ maxItems: 2,
68
+ uniqueItems: true,
69
+ items: {
70
+ enum: [
71
+ "linux",
72
+ "darwin"
73
+ ]
74
+ }
75
+ },
76
+ launch_paths: {
77
+ type: "array",
78
+ minItems: 1,
79
+ maxItems: 1,
80
+ uniqueItems: true,
81
+ items: {
82
+ enum: [
83
+ "direct_node_entry"
84
+ ]
85
+ }
86
+ }
87
+ }
88
+ },
89
+ {
90
+ type: "object",
91
+ additionalProperties: false,
92
+ required: [
93
+ "id",
94
+ "platforms",
95
+ "launch_paths"
96
+ ],
97
+ properties: {
98
+ id: {
99
+ const: "windows-named-pipe-v1"
100
+ },
101
+ platforms: {
102
+ type: "array",
103
+ minItems: 1,
104
+ maxItems: 1,
105
+ uniqueItems: true,
106
+ items: {
107
+ enum: [
108
+ "win32"
109
+ ]
110
+ }
111
+ },
112
+ launch_paths: {
113
+ type: "array",
114
+ minItems: 1,
115
+ maxItems: 2,
116
+ uniqueItems: true,
117
+ items: {
118
+ enum: [
119
+ "native_exe",
120
+ "powershell_standard_shim"
121
+ ]
122
+ }
123
+ }
124
+ }
125
+ }
126
+ ]
127
+ },
128
+ allOf: [
129
+ {
130
+ contains: {
131
+ type: "object",
132
+ required: [
133
+ "id"
134
+ ],
135
+ properties: {
136
+ id: {
137
+ const: "posix-fd-v1"
138
+ }
139
+ }
140
+ },
141
+ minContains: 0,
142
+ maxContains: 1
143
+ },
144
+ {
145
+ contains: {
146
+ type: "object",
147
+ required: [
148
+ "id"
149
+ ],
150
+ properties: {
151
+ id: {
152
+ const: "windows-named-pipe-v1"
153
+ }
154
+ }
155
+ },
156
+ minContains: 0,
157
+ maxContains: 1
158
+ }
159
+ ]
160
+ },
161
+ max_channel_bytes: {
162
+ const: 16384
163
+ },
164
+ operation_receipt: {
165
+ const: "not_supported"
166
+ }
167
+ }
168
+ };
169
+
170
+ // src/contracts/factory-private-evidence/private-frame.v1.schema.json
171
+ var private_frame_v1_schema_default = {
172
+ $schema: "https://json-schema.org/draft/2020-12/schema",
173
+ $id: "urn:caveat:factory-private-evidence:v1",
174
+ title: "Draft: Caveat official private evidence NDJSON frame v1",
175
+ oneOf: [
176
+ {
177
+ type: "object",
178
+ additionalProperties: false,
179
+ required: [
180
+ "schema",
181
+ "collection_id",
182
+ "nonce",
183
+ "execution_id",
184
+ "type",
185
+ "product",
186
+ "product_version",
187
+ "public_diagnostic_schema",
188
+ "transport",
189
+ "process"
190
+ ],
191
+ properties: {
192
+ schema: {
193
+ const: "caveat.factory_private_evidence.v1"
194
+ },
195
+ collection_id: {
196
+ type: "string",
197
+ pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
198
+ },
199
+ nonce: {
200
+ type: "string",
201
+ pattern: "^[0-9a-f]{64}$"
202
+ },
203
+ execution_id: {
204
+ type: "string",
205
+ pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
206
+ },
207
+ type: {
208
+ const: "hello"
209
+ },
210
+ product: {
211
+ const: "caveat"
212
+ },
213
+ product_version: {
214
+ type: "string",
215
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$",
216
+ maxLength: 128
217
+ },
218
+ public_diagnostic_schema: {
219
+ const: "caveat.native_factory_diagnostics.v1"
220
+ },
221
+ transport: {
222
+ enum: [
223
+ "posix-fd-v1",
224
+ "windows-named-pipe-v1"
225
+ ]
226
+ },
227
+ process: {
228
+ type: "object",
229
+ additionalProperties: false,
230
+ required: [
231
+ "pid",
232
+ "parent_pid",
233
+ "start_identity",
234
+ "identity",
235
+ "exec_path",
236
+ "entry_realpath",
237
+ "package_version",
238
+ "build_id",
239
+ "missing_reasons"
240
+ ],
241
+ properties: {
242
+ pid: {
243
+ type: "integer",
244
+ minimum: 1,
245
+ maximum: 9007199254740991
246
+ },
247
+ parent_pid: {
248
+ anyOf: [
249
+ {
250
+ type: "integer",
251
+ minimum: 0,
252
+ maximum: 9007199254740991
253
+ },
254
+ {
255
+ type: "null"
256
+ }
257
+ ]
258
+ },
259
+ start_identity: {
260
+ type: "object",
261
+ additionalProperties: false,
262
+ required: [
263
+ "source",
264
+ "value"
265
+ ],
266
+ properties: {
267
+ source: {
268
+ enum: [
269
+ "linux_proc_start",
270
+ "windows_process_creation",
271
+ "os_process_start",
272
+ "unavailable"
273
+ ]
274
+ },
275
+ value: {
276
+ anyOf: [
277
+ {
278
+ type: "string",
279
+ minLength: 1,
280
+ maxLength: 256
281
+ },
282
+ {
283
+ type: "null"
284
+ }
285
+ ]
286
+ }
287
+ },
288
+ allOf: [
289
+ {
290
+ if: {
291
+ properties: {
292
+ source: {
293
+ const: "unavailable"
294
+ }
295
+ }
296
+ },
297
+ then: {
298
+ properties: {
299
+ value: {
300
+ type: "null"
301
+ }
302
+ }
303
+ },
304
+ else: {
305
+ properties: {
306
+ value: {
307
+ type: "string"
308
+ }
309
+ }
310
+ }
311
+ }
312
+ ]
313
+ },
314
+ identity: {
315
+ type: "object",
316
+ additionalProperties: false,
317
+ required: [
318
+ "kind",
319
+ "uid",
320
+ "gid",
321
+ "sid"
322
+ ],
323
+ properties: {
324
+ kind: {
325
+ enum: [
326
+ "uid_gid",
327
+ "windows_sid",
328
+ "unknown"
329
+ ]
330
+ },
331
+ uid: {
332
+ anyOf: [
333
+ {
334
+ type: "integer",
335
+ minimum: 0,
336
+ maximum: 9007199254740991
337
+ },
338
+ {
339
+ type: "null"
340
+ }
341
+ ]
342
+ },
343
+ gid: {
344
+ anyOf: [
345
+ {
346
+ type: "integer",
347
+ minimum: 0,
348
+ maximum: 9007199254740991
349
+ },
350
+ {
351
+ type: "null"
352
+ }
353
+ ]
354
+ },
355
+ sid: {
356
+ anyOf: [
357
+ {
358
+ type: "string",
359
+ pattern: "^S-1-[0-9]+(?:-[0-9]+)+$",
360
+ maxLength: 256
361
+ },
362
+ {
363
+ type: "null"
364
+ }
365
+ ]
366
+ }
367
+ },
368
+ allOf: [
369
+ {
370
+ if: {
371
+ properties: {
372
+ kind: {
373
+ const: "uid_gid"
374
+ }
375
+ }
376
+ },
377
+ then: {
378
+ properties: {
379
+ uid: {
380
+ type: "integer"
381
+ },
382
+ gid: {
383
+ type: "integer"
384
+ },
385
+ sid: {
386
+ type: "null"
387
+ }
388
+ }
389
+ }
390
+ },
391
+ {
392
+ if: {
393
+ properties: {
394
+ kind: {
395
+ const: "windows_sid"
396
+ }
397
+ }
398
+ },
399
+ then: {
400
+ properties: {
401
+ uid: {
402
+ type: "null"
403
+ },
404
+ gid: {
405
+ type: "null"
406
+ },
407
+ sid: {
408
+ type: "string"
409
+ }
410
+ }
411
+ }
412
+ },
413
+ {
414
+ if: {
415
+ properties: {
416
+ kind: {
417
+ const: "unknown"
418
+ }
419
+ }
420
+ },
421
+ then: {
422
+ properties: {
423
+ uid: {
424
+ type: "null"
425
+ },
426
+ gid: {
427
+ type: "null"
428
+ },
429
+ sid: {
430
+ type: "null"
431
+ }
432
+ }
433
+ }
434
+ }
435
+ ]
436
+ },
437
+ exec_path: {
438
+ anyOf: [
439
+ {
440
+ type: "string",
441
+ minLength: 1,
442
+ maxLength: 4096
443
+ },
444
+ {
445
+ type: "null"
446
+ }
447
+ ]
448
+ },
449
+ entry_realpath: {
450
+ anyOf: [
451
+ {
452
+ type: "string",
453
+ minLength: 1,
454
+ maxLength: 4096
455
+ },
456
+ {
457
+ type: "null"
458
+ }
459
+ ]
460
+ },
461
+ package_version: {
462
+ type: "string",
463
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$",
464
+ maxLength: 128
465
+ },
466
+ build_id: {
467
+ anyOf: [
468
+ {
469
+ type: "string",
470
+ minLength: 1,
471
+ maxLength: 256
472
+ },
473
+ {
474
+ type: "null"
475
+ }
476
+ ]
477
+ },
478
+ missing_reasons: {
479
+ type: "array",
480
+ uniqueItems: true,
481
+ items: {
482
+ enum: [
483
+ "parent_identity_unavailable",
484
+ "start_identity_unavailable",
485
+ "actor_identity_unavailable",
486
+ "exec_path_unavailable",
487
+ "entry_path_unavailable",
488
+ "build_id_unavailable"
489
+ ]
490
+ }
491
+ }
492
+ }
493
+ }
494
+ }
495
+ },
496
+ {
497
+ type: "object",
498
+ additionalProperties: false,
499
+ required: [
500
+ "schema",
501
+ "collection_id",
502
+ "nonce",
503
+ "execution_id",
504
+ "type",
505
+ "public_output",
506
+ "public_result",
507
+ "sync_observation",
508
+ "operation_receipt"
509
+ ],
510
+ properties: {
511
+ schema: {
512
+ const: "caveat.factory_private_evidence.v1"
513
+ },
514
+ collection_id: {
515
+ type: "string",
516
+ pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
517
+ },
518
+ nonce: {
519
+ type: "string",
520
+ pattern: "^[0-9a-f]{64}$"
521
+ },
522
+ execution_id: {
523
+ type: "string",
524
+ pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
525
+ },
526
+ type: {
527
+ const: "diagnostic_result"
528
+ },
529
+ public_output: {
530
+ type: "object",
531
+ additionalProperties: false,
532
+ required: [
533
+ "bytes",
534
+ "sha256"
535
+ ],
536
+ properties: {
537
+ bytes: {
538
+ type: "integer",
539
+ minimum: 0,
540
+ maximum: 9007199254740991
541
+ },
542
+ sha256: {
543
+ type: "string",
544
+ pattern: "^[0-9a-f]{64}$"
545
+ }
546
+ }
547
+ },
548
+ public_result: {
549
+ type: "object",
550
+ additionalProperties: false,
551
+ required: [
552
+ "schema",
553
+ "overall_status",
554
+ "planned_exit_code"
555
+ ],
556
+ properties: {
557
+ schema: {
558
+ const: "caveat.native_factory_diagnostics.v1"
559
+ },
560
+ overall_status: {
561
+ enum: [
562
+ "ready",
563
+ "not_ready",
564
+ "unverified"
565
+ ]
566
+ },
567
+ planned_exit_code: {
568
+ enum: [
569
+ 0,
570
+ 1
571
+ ]
572
+ }
573
+ },
574
+ allOf: [
575
+ {
576
+ if: {
577
+ properties: {
578
+ overall_status: {
579
+ const: "ready"
580
+ }
581
+ }
582
+ },
583
+ then: {
584
+ properties: {
585
+ planned_exit_code: {
586
+ const: 0
587
+ }
588
+ }
589
+ },
590
+ else: {
591
+ properties: {
592
+ planned_exit_code: {
593
+ const: 1
594
+ }
595
+ }
596
+ }
597
+ }
598
+ ]
599
+ },
600
+ sync_observation: {
601
+ type: "object",
602
+ additionalProperties: false,
603
+ required: [
604
+ "status",
605
+ "reason_code",
606
+ "repo_identity",
607
+ "local_head",
608
+ "remote_head",
609
+ "comparison",
610
+ "relation_counts"
611
+ ],
612
+ properties: {
613
+ status: {
614
+ enum: [
615
+ "ready",
616
+ "not_ready",
617
+ "unverified"
618
+ ]
619
+ },
620
+ reason_code: {
621
+ type: "string",
622
+ pattern: "^[a-z][a-z0-9_]{0,63}$"
623
+ },
624
+ repo_identity: {
625
+ type: "object",
626
+ additionalProperties: false,
627
+ required: [
628
+ "status",
629
+ "algorithm",
630
+ "digest",
631
+ "reason"
632
+ ],
633
+ properties: {
634
+ status: {
635
+ enum: [
636
+ "available",
637
+ "not_observed",
638
+ "unverified"
639
+ ]
640
+ },
641
+ algorithm: {
642
+ anyOf: [
643
+ {
644
+ const: "origin-descriptor-sha256-v1"
645
+ },
646
+ {
647
+ type: "null"
648
+ }
649
+ ]
650
+ },
651
+ digest: {
652
+ anyOf: [
653
+ {
654
+ type: "string",
655
+ pattern: "^[0-9a-f]{64}$"
656
+ },
657
+ {
658
+ type: "null"
659
+ }
660
+ ]
661
+ },
662
+ reason: {
663
+ enum: [
664
+ "origin_descriptor_observed",
665
+ "origin_not_reached",
666
+ "origin_capture_unverified",
667
+ "origin_syntax_unsupported",
668
+ "origin_semantics_ambiguous"
669
+ ]
670
+ }
671
+ },
672
+ allOf: [
673
+ {
674
+ if: {
675
+ properties: {
676
+ status: {
677
+ const: "available"
678
+ }
679
+ }
680
+ },
681
+ then: {
682
+ properties: {
683
+ algorithm: {
684
+ const: "origin-descriptor-sha256-v1"
685
+ },
686
+ digest: {
687
+ type: "string",
688
+ pattern: "^[0-9a-f]{64}$"
689
+ },
690
+ reason: {
691
+ const: "origin_descriptor_observed"
692
+ }
693
+ }
694
+ },
695
+ else: {
696
+ properties: {
697
+ algorithm: {
698
+ type: "null"
699
+ },
700
+ digest: {
701
+ type: "null"
702
+ }
703
+ }
704
+ }
705
+ },
706
+ {
707
+ if: {
708
+ properties: {
709
+ status: {
710
+ const: "not_observed"
711
+ }
712
+ }
713
+ },
714
+ then: {
715
+ properties: {
716
+ reason: {
717
+ const: "origin_not_reached"
718
+ }
719
+ }
720
+ }
721
+ },
722
+ {
723
+ if: {
724
+ properties: {
725
+ status: {
726
+ const: "unverified"
727
+ }
728
+ }
729
+ },
730
+ then: {
731
+ properties: {
732
+ reason: {
733
+ enum: [
734
+ "origin_capture_unverified",
735
+ "origin_syntax_unsupported",
736
+ "origin_semantics_ambiguous"
737
+ ]
738
+ }
739
+ }
740
+ }
741
+ }
742
+ ]
743
+ },
744
+ local_head: {
745
+ type: "object",
746
+ additionalProperties: false,
747
+ required: [
748
+ "status",
749
+ "value",
750
+ "reason"
751
+ ],
752
+ properties: {
753
+ status: {
754
+ enum: [
755
+ "observed",
756
+ "not_observed",
757
+ "unverified"
758
+ ]
759
+ },
760
+ value: {
761
+ anyOf: [
762
+ {
763
+ type: "string",
764
+ pattern: "^[0-9a-f]{40}$"
765
+ },
766
+ {
767
+ type: "null"
768
+ }
769
+ ]
770
+ },
771
+ reason: {
772
+ type: "string",
773
+ pattern: "^[a-z][a-z0-9_]{0,63}$"
774
+ }
775
+ },
776
+ allOf: [
777
+ {
778
+ if: {
779
+ properties: {
780
+ status: {
781
+ const: "observed"
782
+ }
783
+ }
784
+ },
785
+ then: {
786
+ properties: {
787
+ value: {
788
+ type: "string",
789
+ pattern: "^[0-9a-f]{40}$"
790
+ }
791
+ }
792
+ },
793
+ else: {
794
+ properties: {
795
+ value: {
796
+ type: "null"
797
+ }
798
+ }
799
+ }
800
+ }
801
+ ]
802
+ },
803
+ remote_head: {
804
+ type: "object",
805
+ additionalProperties: false,
806
+ required: [
807
+ "status",
808
+ "value",
809
+ "reason"
810
+ ],
811
+ properties: {
812
+ status: {
813
+ enum: [
814
+ "observed",
815
+ "not_observed",
816
+ "unverified"
817
+ ]
818
+ },
819
+ value: {
820
+ anyOf: [
821
+ {
822
+ type: "string",
823
+ pattern: "^[0-9a-f]{40}$"
824
+ },
825
+ {
826
+ type: "null"
827
+ }
828
+ ]
829
+ },
830
+ reason: {
831
+ type: "string",
832
+ pattern: "^[a-z][a-z0-9_]{0,63}$"
833
+ }
834
+ },
835
+ allOf: [
836
+ {
837
+ if: {
838
+ properties: {
839
+ status: {
840
+ const: "observed"
841
+ }
842
+ }
843
+ },
844
+ then: {
845
+ properties: {
846
+ value: {
847
+ type: "string",
848
+ pattern: "^[0-9a-f]{40}$"
849
+ }
850
+ }
851
+ },
852
+ else: {
853
+ properties: {
854
+ value: {
855
+ type: "null"
856
+ }
857
+ }
858
+ }
859
+ }
860
+ ]
861
+ },
862
+ comparison: {
863
+ enum: [
864
+ "equal",
865
+ "different",
866
+ "not_evaluated"
867
+ ]
868
+ },
869
+ relation_counts: {
870
+ type: "object",
871
+ additionalProperties: false,
872
+ required: [
873
+ "status",
874
+ "behind",
875
+ "ahead"
876
+ ],
877
+ properties: {
878
+ status: {
879
+ const: "not_supported"
880
+ },
881
+ behind: {
882
+ type: "null"
883
+ },
884
+ ahead: {
885
+ type: "null"
886
+ }
887
+ }
888
+ }
889
+ }
890
+ },
891
+ operation_receipt: {
892
+ type: "object",
893
+ additionalProperties: false,
894
+ required: [
895
+ "status",
896
+ "receipt"
897
+ ],
898
+ properties: {
899
+ status: {
900
+ const: "not_supported"
901
+ },
902
+ receipt: {
903
+ type: "null"
904
+ }
905
+ }
906
+ }
907
+ }
908
+ }
909
+ ]
910
+ };
911
+
912
+ // src/contracts/factory-private-evidence/windows-channel.v1.schema.json
913
+ var windows_channel_v1_schema_default = {
914
+ $schema: "https://json-schema.org/draft/2020-12/schema",
915
+ $id: "urn:caveat:factory-private-evidence-windows-channel:v1",
916
+ title: "Draft: local Windows private channel descriptor",
917
+ type: "object",
918
+ additionalProperties: false,
919
+ required: [
920
+ "transport",
921
+ "path",
922
+ "server_pid",
923
+ "server_start_identity",
924
+ "owner_sid"
925
+ ],
926
+ properties: {
927
+ transport: {
928
+ const: "windows-named-pipe-v1"
929
+ },
930
+ path: {
931
+ type: "string",
932
+ pattern: "^\\\\\\\\\\.\\\\pipe\\\\caveat-evidence-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
933
+ },
934
+ server_pid: {
935
+ type: "integer",
936
+ minimum: 1,
937
+ maximum: 9007199254740991
938
+ },
939
+ server_start_identity: {
940
+ type: "string",
941
+ minLength: 1,
942
+ maxLength: 256
943
+ },
944
+ owner_sid: {
945
+ type: "string",
946
+ pattern: "^S-1-[0-9]+(?:-[0-9]+)+$",
947
+ maxLength: 256
948
+ }
949
+ }
950
+ };
951
+
952
+ // src/privateEvidence/validation.ts
953
+ var ajv = new Ajv2020({ strict: true, strictRequired: false });
954
+ var validateCapability = ajv.compile(capability_v1_schema_default);
955
+ var validateFrame = ajv.compile(private_frame_v1_schema_default);
956
+ var validateWindowsDescriptor = ajv.compile(windows_channel_v1_schema_default);
957
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
958
+ var NONCE = /^[0-9a-f]{64}$/;
959
+ var MAX_CHANNEL_BYTES = 16384;
960
+ function strictJson(bytes, limit = MAX_CHANNEL_BYTES) {
961
+ if (bytes.byteLength === 0 || bytes.byteLength > limit) throw new Error("json_budget");
962
+ const text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
963
+ const objects = [];
964
+ let depth = 0, invalid = false;
965
+ visit(text, {
966
+ onObjectBegin() {
967
+ if (++depth > 32) throw new Error("json_depth");
968
+ objects.push(/* @__PURE__ */ new Set());
969
+ },
970
+ onObjectProperty(key) {
971
+ const keys = objects.at(-1);
972
+ if (keys.has(key)) invalid = true;
973
+ keys.add(key);
974
+ },
975
+ onObjectEnd() {
976
+ objects.pop();
977
+ depth--;
978
+ },
979
+ onArrayBegin() {
980
+ if (++depth > 32) throw new Error("json_depth");
981
+ },
982
+ onArrayEnd() {
983
+ depth--;
984
+ },
985
+ onError() {
986
+ invalid = true;
987
+ }
988
+ }, { disallowComments: true, allowTrailingComma: false, allowEmptyContent: false });
989
+ if (invalid || depth !== 0 || objects.length !== 0) throw new Error("json_invalid");
990
+ return JSON.parse(text);
991
+ }
992
+ function validateRequest(env) {
993
+ if (env.CAVEAT_FACTORY_PRIVATE_EVIDENCE !== "v1") return { status: "off" };
994
+ const collection = env.CAVEAT_FACTORY_PRIVATE_COLLECTION_ID;
995
+ const nonce = env.CAVEAT_FACTORY_PRIVATE_NONCE;
996
+ const channel = env.CAVEAT_FACTORY_PRIVATE_CHANNEL;
997
+ if (!collection || !UUID.test(collection) || !nonce || !NONCE.test(nonce) || !channel || channel.length > MAX_CHANNEL_BYTES)
998
+ return { status: "unverified", reason: "request_invalid" };
999
+ if (channel === "fd:3") return { status: "valid", collection_id: collection, nonce, transport: "posix-fd-v1" };
1000
+ try {
1001
+ const descriptor = strictJson(Buffer.from(channel));
1002
+ if (validateWindowsDescriptor(descriptor))
1003
+ return { status: "valid", collection_id: collection, nonce, transport: "windows-named-pipe-v1" };
1004
+ } catch {
1005
+ }
1006
+ return { status: "unverified", reason: "request_invalid" };
1007
+ }
1008
+ function selectCapability(request, capability, expectedVersion, platform, launchPath) {
1009
+ if (request.status === "off") return { status: "off" };
1010
+ if (request.status !== "valid") return { status: "unverified", reason: "request_invalid" };
1011
+ if (capability == null) return { status: "not_supported", reason: "capability_absent" };
1012
+ if (!validateCapability(capability) || capability.package_version !== expectedVersion)
1013
+ return { status: "unverified", reason: "capability_invalid" };
1014
+ const common = capability.transports.some((t) => t.id === request.transport && t.platforms.includes(platform) && t.launch_paths.includes(launchPath));
1015
+ return common ? { status: "candidate_requires_os_verification" } : { status: "not_supported", reason: "transport_unsupported" };
1016
+ }
1017
+ function validateExchange(input) {
1018
+ const bad = (reason) => ({ status: "unverified", reason });
1019
+ try {
1020
+ if (input.request.status !== "valid" || input.eof !== true || input.peerVerified !== true) return bad("channel_incomplete");
1021
+ if (!validateCapability(input.capability) || input.capability.package_version !== input.expectedVersion)
1022
+ return bad("capability_invalid");
1023
+ if (input.channelBytes.byteLength > MAX_CHANNEL_BYTES) return bad("channel_budget");
1024
+ const bytes = Buffer.from(input.channelBytes);
1025
+ if (bytes.at(-1) !== 10) return bad("frame_framing");
1026
+ const lines = bytes.toString("latin1").split("\n");
1027
+ if (lines.length !== 3 || lines[2] !== "") return bad("frame_framing");
1028
+ const frames = lines.slice(0, 2).map((line) => strictJson(Buffer.from(line, "latin1")));
1029
+ if (frames.some((frame) => !validateFrame(frame))) return bad("frame_schema");
1030
+ const [hello, result] = frames;
1031
+ if (hello.type !== "hello" || result.type !== "diagnostic_result") return bad("frame_order");
1032
+ if (!UUID.test(hello.execution_id)) return bad("frame_identity");
1033
+ for (const key of ["schema", "collection_id", "nonce", "execution_id"])
1034
+ if (hello[key] !== result[key]) return bad("frame_identity");
1035
+ if (hello.collection_id !== input.request.collection_id || hello.nonce !== input.request.nonce || hello.product_version !== input.expectedVersion || hello.process.package_version !== input.expectedVersion || hello.transport !== input.request.transport) return bad("frame_identity");
1036
+ if (selectCapability(input.request, input.capability, input.expectedVersion, input.platform, input.launchPath).status !== "candidate_requires_os_verification") return bad("transport_unsupported");
1037
+ const p = hello.process;
1038
+ if (!input.expectedProcess || !isDeepStrictEqual(p, input.expectedProcess)) return bad("peer_identity");
1039
+ const needed = [];
1040
+ for (const [key, reason] of [
1041
+ ["parent_pid", "parent_identity_unavailable"],
1042
+ ["exec_path", "exec_path_unavailable"],
1043
+ ["entry_realpath", "entry_path_unavailable"],
1044
+ ["build_id", "build_id_unavailable"]
1045
+ ])
1046
+ if (p[key] === null) needed.push(reason);
1047
+ if (p.start_identity.source === "unavailable") needed.push("start_identity_unavailable");
1048
+ if (p.identity.kind === "unknown") needed.push("actor_identity_unavailable");
1049
+ if (!isDeepStrictEqual([...needed].sort(), [...p.missing_reasons].sort())) return bad("process_missing_reason");
1050
+ if (input.publicBytes.at(-1) !== 10 || input.publicBytes.subarray(0, -1).includes(10)) return bad("public_framing");
1051
+ const pub = strictJson(input.publicBytes, 65536);
1052
+ if (pub.schema !== hello.public_diagnostic_schema || pub.product !== "caveat" || pub.version !== input.expectedVersion || pub.overall?.status !== result.public_result.overall_status || pub.sync?.status !== result.sync_observation.status || pub.sync?.reason_code !== result.sync_observation.reason_code) return bad("public_mismatch");
1053
+ if (result.public_output.bytes !== input.publicBytes.byteLength || result.public_output.sha256 !== createHash("sha256").update(input.publicBytes).digest("hex")) return bad("public_bytes_mismatch");
1054
+ const sync = result.sync_observation;
1055
+ const both = sync.local_head.status === "observed" && sync.remote_head.status === "observed";
1056
+ const comparison = both ? sync.local_head.value === sync.remote_head.value ? "equal" : "different" : "not_evaluated";
1057
+ if (sync.comparison !== comparison) return bad("head_comparison");
1058
+ const repo = sync.repo_identity;
1059
+ const allowed = repo.status === "available" ? ["origin_descriptor_observed"] : repo.status === "not_observed" ? ["origin_not_reached"] : ["origin_capture_unverified", "origin_syntax_unsupported", "origin_semantics_ambiguous"];
1060
+ if (!allowed.includes(repo.reason)) return bad("origin_reason");
1061
+ return { status: "valid", reason: "complete_synthetic_exchange" };
1062
+ } catch {
1063
+ return bad("exchange_invalid");
1064
+ }
1065
+ }
1066
+ export {
1067
+ MAX_CHANNEL_BYTES,
1068
+ UUID,
1069
+ selectCapability,
1070
+ strictJson,
1071
+ validateCapability,
1072
+ validateExchange,
1073
+ validateFrame,
1074
+ validateRequest,
1075
+ validateWindowsDescriptor
1076
+ };
1077
+ //# sourceMappingURL=validation.js.map