@sanning/proof 0.12.0 → 0.13.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.
Files changed (48) hide show
  1. package/README.md +25 -12
  2. package/dist/agent-proof.d.ts +2 -2
  3. package/dist/agent-proof.js +4 -4
  4. package/dist/case-file.d.ts +126 -0
  5. package/dist/case-file.js +349 -0
  6. package/dist/case.d.ts +173 -26
  7. package/dist/case.js +469 -123
  8. package/dist/cli.d.ts +38 -5
  9. package/dist/cli.js +557 -208
  10. package/dist/crypto.d.ts +1 -1
  11. package/dist/crypto.js +5 -1
  12. package/dist/declaration.d.ts +58 -52
  13. package/dist/declaration.js +256 -33
  14. package/dist/evidence.d.ts +2 -0
  15. package/dist/evidence.js +134 -19
  16. package/dist/exit-codes.d.ts +17 -0
  17. package/dist/exit-codes.js +50 -0
  18. package/dist/grading.d.ts +28 -13
  19. package/dist/grading.js +90 -31
  20. package/dist/index.d.ts +10 -7
  21. package/dist/index.js +13 -6
  22. package/dist/message-parts.d.ts +11 -9
  23. package/dist/message-parts.js +11 -9
  24. package/dist/types.d.ts +1 -0
  25. package/dist/verifier.d.ts +9 -2
  26. package/dist/verifier.js +28 -12
  27. package/dist/zip-reader.d.ts +50 -0
  28. package/dist/zip-reader.js +220 -0
  29. package/package.json +2 -2
  30. package/src/agent-proof.ts +4 -4
  31. package/src/case-file.ts +419 -0
  32. package/src/case.ts +586 -132
  33. package/src/cli.ts +651 -206
  34. package/src/crypto.ts +5 -1
  35. package/src/declaration.ts +248 -52
  36. package/src/evidence.ts +142 -21
  37. package/src/exit-codes.ts +54 -0
  38. package/src/grading.ts +109 -52
  39. package/src/index.ts +58 -2
  40. package/src/message-parts.ts +11 -9
  41. package/src/types.ts +5 -0
  42. package/src/verifier.ts +35 -13
  43. package/src/zip-reader.ts +229 -0
  44. package/vectors/README.md +23 -5
  45. package/vectors/case-file-index.json +668 -0
  46. package/vectors/case-split.json +218 -9
  47. package/vectors/pack-grading.json +68 -4
  48. package/vectors/stamp-on-chain.json +3 -3
package/dist/crypto.d.ts CHANGED
@@ -4,7 +4,7 @@ export declare function isHexField(value: unknown, nibbles: number, lower?: bool
4
4
  export declare function utf8(s: string): Uint8Array;
5
5
  export declare function sha256Bytes(bytes: Uint8Array): Promise<Uint8Array>;
6
6
  export declare function sha256Hex(bytes: Uint8Array): Promise<string>;
7
- export declare function ed25519Verify(signatureHex: string, message: Uint8Array, publicKeyHex: string): Promise<boolean>;
7
+ export declare function ed25519Verify(message: Uint8Array, signatureHex: string, publicKeyHex: string): Promise<boolean>;
8
8
  export declare function ed25519Sign(message: Uint8Array, privateKeyHex: string): Promise<string>;
9
9
  export declare function ed25519PublicKey(privateKeyHex: string): Promise<string>;
10
10
  export declare function verifyRsaPssSha256(payloadBytes: Uint8Array, signatureHex: string, publicKey: {
package/dist/crypto.js CHANGED
@@ -74,7 +74,11 @@ export async function sha256Hex(bytes) {
74
74
  // appear in the envelope; message is raw bytes. Never throws — a malformed
75
75
  // signature or key is "not verified," not an exception, so a hostile envelope
76
76
  // can't crash the checker.
77
- export async function ed25519Verify(signatureHex, message, publicKeyHex) {
77
+ // Arguments in the Python twin's order, `ed25519_verify(message,
78
+ // signature_hex, public_key_hex)` (P-03, 0.13.0). The message came second
79
+ // until 0.13.0; a caller that still passes the signature first gets a compile
80
+ // error, because a string is not a Uint8Array.
81
+ export async function ed25519Verify(message, signatureHex, publicKeyHex) {
78
82
  try {
79
83
  // zip215:false → strict RFC-8032 verification, matching the Go agent's
80
84
  // crypto/ed25519 exactly (noble defaults to the more lenient zip215:true).
@@ -1,30 +1,27 @@
1
1
  import { type HandoffRecord } from "./handoff.js";
2
2
  import { type SideContentMap } from "./side-content.js";
3
- /** The declaration schema this reader knows. */
3
+ /** The first declaration schema, which every earlier reader knows. */
4
4
  export declare const DECLARATION_VERSION = "sanning.declaration/v1";
5
- /** The three states a declaration check can reach, from the §3 vocabulary. */
6
- export type DeclarationVerdict = "verified" | "failed" | "partial";
7
- export type DeclarationDeviationKind =
8
- /** The declaration is written to this version and is not readable as one. */
9
- "declaration-malformed"
10
- /** A record the declaration expects is not in the pack. */
11
- | "declared-absent"
12
- /** A record in the pack the declaration never expected. */
13
- | "undeclared-present"
14
5
  /**
15
- * A record declared `content_withheld` whose bytes the pack supplies INSIDE
16
- * its own signed body, in `events[].content`.
6
+ * v1 plus a signed `records[].role` on every record (evidence-bundle.md
7
+ * 5.4.1 v1.20, A21). A reader that knows only v1 reads a v2 declaration as one
8
+ * it cannot read, which is the safe direction.
17
9
  */
18
- | "withheld-but-disclosed"
19
- /** The pack carries one `event_id` on two or more records. */
20
- | "duplicate-event-id"
21
- /** A claimed hand-off names a record the declaration does not declare. */
22
- | "pair-record-undeclared"
10
+ export declare const DECLARATION_VERSION_V2 = "sanning.declaration/v2";
11
+ /** Every declaration schema this reader knows, in the order they were added. */
12
+ export declare const DECLARATION_VERSIONS: readonly ["sanning.declaration/v1", "sanning.declaration/v2"];
23
13
  /**
24
- * A claimed hand-off names a record that is not a conformant hand-off
25
- * record of the side it is claimed on (envelope-spec.md 4.1).
14
+ * What a v2 declaration may sign a record IS, compared exactly: `handoff`, a
15
+ * record 4.1 governs that the pack claims as a side in `handoffs[]`, or
16
+ * `step`, any other record.
26
17
  */
27
- | "pair-record-not-a-handoff";
18
+ export declare const DECLARATION_ROLES: readonly ["handoff", "step"];
19
+ export type DeclarationRole = (typeof DECLARATION_ROLES)[number];
20
+ /** The three states a declaration check can reach, from the §3 vocabulary. */
21
+ export declare const DECLARATION_VERDICTS: readonly ["verified", "failed", "partial"];
22
+ export type DeclarationVerdict = (typeof DECLARATION_VERDICTS)[number];
23
+ export declare const DECLARATION_DEVIATION_KINDS: readonly ["declaration_malformed", "declared_absent", "undeclared_present", "withheld_but_disclosed", "duplicate_event_id", "pair_record_undeclared", "pair_record_not_a_handoff", "role_handoff_unclaimed", "role_step_claimed", "role_step_governed", "role_step_unreadable"];
24
+ export type DeclarationDeviationKind = (typeof DECLARATION_DEVIATION_KINDS)[number];
28
25
  /**
29
26
  * Every way a pack and the UNSIGNED content handed in beside it fail to line
30
27
  * up, as a closed set. Neither of these is a deviation, and neither of them
@@ -51,22 +48,8 @@ export type DeclarationDeviationKind =
51
48
  * legal and grades `verified`, which is strictly better than the `incomplete`
52
49
  * these carry.
53
50
  */
54
- export type DeclarationContentKind =
55
- /**
56
- * A record declared `disclosed` whose bytes reached this reader from
57
- * neither channel. ALWAYS content-dependent: 5.4.1 lets those bytes travel
58
- * beside the pack as `logs/<event_id>.json`, so "no bytes arrived" is a
59
- * fact about what the READER was handed and never a fact about what the
60
- * holder supplied. No signature covers the absence of a file nobody signed.
61
- */
62
- "content-dependent-withholding"
63
- /**
64
- * A record declared `content_withheld` whose bytes reached this reader ONLY
65
- * from the unsigned side-content map. The pack's own body supplies none, so
66
- * the holder committed to no such disclosure. The in-body half of the same
67
- * rule is the `withheld-but-disclosed` DEVIATION and still fails.
68
- */
69
- | "content-dependent-disclosure";
51
+ export declare const DECLARATION_CONTENT_KINDS: readonly ["content_dependent_withholding", "content_dependent_disclosure"];
52
+ export type DeclarationContentKind = (typeof DECLARATION_CONTENT_KINDS)[number];
70
53
  /**
71
54
  * One way the pack and the unsigned content beside it do not line up. Named
72
55
  * like a deviation and weighed like an absence.
@@ -77,18 +60,8 @@ export interface DeclarationContentFinding {
77
60
  eventId?: string;
78
61
  }
79
62
  /** Everything this check reports that is NOT a deviation, as a closed set. */
80
- export type DeclarationNoteKind =
81
- /**
82
- * Every record declared `disclosed` supplied no bytes, so nothing was
83
- * selected: the bytes did not travel with the pack.
84
- */
85
- "disclosure-did-not-travel"
86
- /**
87
- * A claimed hand-off side whose `event_bytes` the pack withholds. The reader
88
- * cannot see what the record is either way, so it is neither a conformant
89
- * hand-off record nor a non-conformant one.
90
- */
91
- | "pair-record-withheld";
63
+ export declare const DECLARATION_NOTE_KINDS: readonly ["disclosure_did_not_travel", "pair_record_withheld", "role_step_withheld"];
64
+ export type DeclarationNoteKind = (typeof DECLARATION_NOTE_KINDS)[number];
92
65
  /**
93
66
  * One named non-deviation finding, as data.
94
67
  *
@@ -102,9 +75,9 @@ export interface DeclarationNote {
102
75
  count?: number;
103
76
  /** The record this is about, where it is about one. */
104
77
  eventId?: string;
105
- /** Which side of a claimed hand-off named it, for `pair-record-withheld`. */
78
+ /** Which side of a claimed hand-off named it, for `pair_record_withheld`. */
106
79
  side?: "sent" | "received";
107
- /** Which claimed hand-off, by position, for `pair-record-withheld`. */
80
+ /** Which claimed hand-off, by position, for `pair_record_withheld`. */
108
81
  pairIndex?: number;
109
82
  }
110
83
  /** One deviation, as data. A surface renders its own prose or calls `renderDeviation`. */
@@ -116,8 +89,14 @@ export interface DeclarationDeviation {
116
89
  side?: "sent" | "received";
117
90
  /** Which claimed hand-off, by position, for the two `pair-record-` deviations. */
118
91
  pairIndex?: number;
119
- /** What is wrong with the declaration itself, for `declaration-malformed`. */
92
+ /** What is wrong with the declaration itself, for `declaration_malformed`. */
120
93
  reason?: string;
94
+ /**
95
+ * The `declaration_version` the object claimed, for `declaration_malformed`,
96
+ * so the rendered sentence names the version the holder wrote to rather than
97
+ * the first one this reader learned.
98
+ */
99
+ version?: string;
121
100
  }
122
101
  export interface DeclarationCheck {
123
102
  verdict: DeclarationVerdict;
@@ -142,6 +121,22 @@ export interface DeclarationCheck {
142
121
  declared: string[];
143
122
  /** Of those, the ones declared withheld on purpose. */
144
123
  declaredWithheld: string[];
124
+ /**
125
+ * The `declaration_version` this reader read the object as, one of
126
+ * `DECLARATION_VERSIONS`, or `null` where the body carries no declaration or
127
+ * one whose version this reader does not know. Set for a malformed object
128
+ * too: the version was read, the rest was not. Optional so a check a caller
129
+ * builds by hand, as rule version 5 adapters do, still type-checks.
130
+ */
131
+ version?: string | null;
132
+ /**
133
+ * Every record a v2 declaration signs a role for, in declaration order.
134
+ * Empty for v1, and for anything this reader could not read.
135
+ */
136
+ roles?: {
137
+ eventId: string;
138
+ role: DeclarationRole;
139
+ }[];
145
140
  }
146
141
  /**
147
142
  * One of the pack's own records: the id, and whether the pack supplied its
@@ -242,7 +237,7 @@ export interface DeclarationClaims {
242
237
  */
243
238
  present: boolean;
244
239
  /**
245
- * Whether this reader could read the claim as `DECLARATION_VERSION` AND the
240
+ * Whether this reader could read the claim as one of `DECLARATION_VERSIONS` AND the
246
241
  * object satisfies 5.4.1. `false` covers an absent declaration, an unknown
247
242
  * version and a malformed object, and a case reader must not read any of the
248
243
  * three as "the holder claimed nothing to check".
@@ -256,6 +251,17 @@ export interface DeclarationClaims {
256
251
  * is legal and is exactly the shape a case reader has to name.
257
252
  */
258
253
  claimedSides: string[];
254
+ /**
255
+ * The version the claim was read as, where `readable`; else `null`. The case
256
+ * reader's claim check is v1's alone (5.5.1 v1.20): a v2 pack's claim check
257
+ * is rule 9, which the declaration check already ran.
258
+ */
259
+ version: string | null;
260
+ /** Every record a READABLE v2 declaration signs a role for. Empty for v1. */
261
+ roles: {
262
+ eventId: string;
263
+ role: DeclarationRole;
264
+ }[];
259
265
  }
260
266
  /**
261
267
  * Read the claim a pack's declaration makes, without grading the pack.