@synoi/sraid 0.2.0 → 0.4.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 (86) hide show
  1. package/README.md +156 -50
  2. package/SPEC.md +2 -2
  3. package/dist/attestation.d.ts +8 -49
  4. package/dist/attestation.d.ts.map +1 -1
  5. package/dist/attestation.js +15 -46
  6. package/dist/attestation.js.map +1 -1
  7. package/dist/capability.d.ts +59 -0
  8. package/dist/capability.d.ts.map +1 -0
  9. package/dist/capability.js +44 -0
  10. package/dist/capability.js.map +1 -0
  11. package/dist/index.d.ts +13 -13
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +26 -18
  14. package/dist/index.js.map +1 -1
  15. package/dist/internal/attestation-core.d.ts +85 -0
  16. package/dist/internal/attestation-core.d.ts.map +1 -0
  17. package/dist/internal/attestation-core.js +78 -0
  18. package/dist/internal/attestation-core.js.map +1 -0
  19. package/dist/internal/base64-browser.d.ts +31 -0
  20. package/dist/internal/base64-browser.d.ts.map +1 -0
  21. package/dist/internal/base64-browser.js +39 -0
  22. package/dist/internal/base64-browser.js.map +1 -0
  23. package/dist/internal/base64-validate.d.ts +19 -0
  24. package/dist/internal/base64-validate.d.ts.map +1 -0
  25. package/dist/internal/base64-validate.js +33 -0
  26. package/dist/internal/base64-validate.js.map +1 -0
  27. package/dist/internal/base64.d.ts +7 -5
  28. package/dist/internal/base64.d.ts.map +1 -1
  29. package/dist/internal/base64.js +7 -19
  30. package/dist/internal/base64.js.map +1 -1
  31. package/dist/internal/content-core.d.ts +68 -0
  32. package/dist/internal/content-core.d.ts.map +1 -0
  33. package/dist/internal/content-core.js +87 -0
  34. package/dist/internal/content-core.js.map +1 -0
  35. package/dist/internal/ed25519-browser.d.ts +33 -0
  36. package/dist/internal/ed25519-browser.d.ts.map +1 -0
  37. package/dist/internal/ed25519-browser.js +79 -0
  38. package/dist/internal/ed25519-browser.js.map +1 -0
  39. package/dist/internal/mldsa-browser.d.ts +27 -0
  40. package/dist/internal/mldsa-browser.d.ts.map +1 -0
  41. package/dist/internal/mldsa-browser.js +35 -0
  42. package/dist/internal/mldsa-browser.js.map +1 -0
  43. package/dist/internal/sha256-browser.d.ts +17 -0
  44. package/dist/internal/sha256-browser.d.ts.map +1 -0
  45. package/dist/internal/sha256-browser.js +27 -0
  46. package/dist/internal/sha256-browser.js.map +1 -0
  47. package/dist/lineage.js +0 -0
  48. package/dist/lineage.js.map +1 -1
  49. package/dist/oid.d.ts +2 -52
  50. package/dist/oid.d.ts.map +1 -1
  51. package/dist/oid.js +9 -71
  52. package/dist/oid.js.map +1 -1
  53. package/dist/types.d.ts +4 -30
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js +19 -0
  56. package/dist/types.js.map +1 -1
  57. package/dist/validate.d.ts +2 -17
  58. package/dist/validate.d.ts.map +1 -1
  59. package/dist/validate.js +0 -57
  60. package/dist/validate.js.map +1 -1
  61. package/dist/verify-browser.d.ts +80 -0
  62. package/dist/verify-browser.d.ts.map +1 -0
  63. package/dist/verify-browser.js +157 -0
  64. package/dist/verify-browser.js.map +1 -0
  65. package/package.json +22 -3
  66. package/src/attestation.ts +29 -88
  67. package/src/capability.ts +69 -0
  68. package/src/index.ts +27 -36
  69. package/src/internal/attestation-core.ts +122 -0
  70. package/src/internal/base64-browser.ts +39 -0
  71. package/src/internal/base64-validate.ts +31 -0
  72. package/src/internal/base64.ts +7 -16
  73. package/src/internal/content-core.ts +88 -0
  74. package/src/internal/ed25519-browser.ts +85 -0
  75. package/src/internal/mldsa-browser.ts +39 -0
  76. package/src/internal/sha256-browser.ts +28 -0
  77. package/src/lineage.ts +0 -0
  78. package/src/oid.ts +10 -73
  79. package/src/types.ts +23 -31
  80. package/src/validate.ts +1 -64
  81. package/src/verify-browser.ts +185 -0
  82. package/dist/authority.d.ts +0 -351
  83. package/dist/authority.d.ts.map +0 -1
  84. package/dist/authority.js +0 -563
  85. package/dist/authority.js.map +0 -1
  86. package/src/authority.ts +0 -849
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,IAAI,EACJ,WAAW,EACX,OAAO,EACP,GAAG,EACH,OAAO,EACP,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAGhG,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAA;AAKvB,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAMlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAK5D,OAAO,EACL,iBAAiB,EACjB,GAAG,EACH,WAAW,EACX,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,UAAU,EACV,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAA;AAIvB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,yBAAyB,EACzB,2BAA2B,EAC3B,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,IAAI,EACJ,WAAW,EACX,OAAO,EACP,eAAe,EACf,iBAAiB,GAClB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAGhG,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,gBAAgB,CAAA;AAKvB,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAMlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAK5D,OAAO,EACL,iBAAiB,EACjB,GAAG,EACH,WAAW,EACX,aAAa,EACb,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,UAAU,EACV,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGrE,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,2BAA2B,EAC3B,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * @synoi/sraid — public surface.
3
3
  *
4
- * SRAID (Self-Routing Addressable Identity Data) is L0 of the SynOI SRAID Stack:
4
+ * SRAID is the object-identity layer: it defines what a signed object IS and
5
+ * how anyone re-derives and verifies its identity offline.
5
6
  *
6
- * L0 SRAID ← this package
7
- * L1 Vault / Resolver
8
- * L2 Inference Broker / Resonance
9
- * L3 GAP (Governed Action Protocol)
10
- * L4 Apps
7
+ * Scope, precisely:
8
+ * IN canonical serializer, OID computation, hybrid Ed25519 + ML-DSA-65
9
+ * attestation verification, lineage resolution, shape validators.
10
+ * OUT storage, transport, key resolution, revocation, policy, enforcement.
11
11
  *
12
- * This package is intentionally small: types, canonical serializer,
13
- * OID computation, hybrid signature verification, and shape validators.
14
- * No storage, no HTTP, no governance those are higher layers.
12
+ * It verifies SIGNATURES, not IDENTITIES: `signer_kid` is an opaque string
13
+ * this package never resolves, and nothing here checks revocation. Deciding
14
+ * whether a key was trusted at signing time is a caller/directory concern.
15
15
  */
16
16
  // Canonical serializer — byte-identical to synoi-gateway + @synoi/vault.
17
17
  export { canonicalize } from './canonicalize.js';
@@ -28,19 +28,27 @@ export { verifyMlDsa65, isNativeMlDsaAvailable } from './mldsa.js';
28
28
  // bytes; `evictKeyFromCaches(keyId)` drops that entry from every cache so a
29
29
  // rotated or compromised key cannot be served stale on a later verify.
30
30
  export { evictKeyFromCaches } from './internal/key-cache.js';
31
- // L2 DSSE attestation — PAE type-binding, hybrid Ed25519 + ML-DSA-65 both
31
+ // DSSE attestation — PAE type-binding, hybrid Ed25519 + ML-DSA-65 both
32
32
  // required. The preferred signing path (replaces the legacy bare-bytes
33
33
  // SignatureEnvelope; closes the cross-type confusion gap SRAID F7 / A4).
34
34
  export { verifyAttestation, pae, ALG_ED25519, ALG_ML_DSA_65, } from './attestation.js';
35
- // L3 lineage (Merkle-DAG) — unify supersedes/SRO/prev; latest-wins resolution.
35
+ // Lineage (Merkle-DAG) — unify the `supersedes` string with the identity-bound
36
+ // `prev`/`links` edges; latest-wins resolution over a version set.
36
37
  export { lineageLinks, supersededOids, latestWins, } from './lineage.js';
37
- // L4 propagating sensitivity — coarse, opaque tier + monotone max() carry-forward.
38
+ // Propagating sensitivity — coarse, opaque tier + monotone max() carry-forward.
38
39
  export { SENSITIVITY_TIERS, SENSITIVITY_DEFAULT, isSensitivityTier, sensitivityRank, sensitivityMax, sensitivityCarryForward, sensitivityMonotoneCheck, } from './sensitivity.js';
39
- // L4 authority verification (the authorized axis).
40
- export { verifyAuthority, capabilityCovers, } from './authority.js';
41
- // L4 delegation-chain verification (K2) — VERIFY-ONLY, offline, no enforcement.
42
- // Always reports revocation_checked/existence_checked false (no live claim).
43
- export { verifyDelegationChain, MAX_DELEGATION_DEPTH, } from './authority.js';
40
+ // Capability matching + the live-grant-status contract. The leaf primitive a
41
+ // grant store needs: pure string logic, no crypto, no I/O, no live claim.
42
+ export { capabilityCovers } from './capability.js';
44
43
  // Shape validators.
45
- export { validateCdro, validateSro, validateSignatureEnvelope, validateAttestationEnvelope, validateAuthorityBlock, validateLineageLink, } from './validate.js';
44
+ export { validateCdro, validateSignatureEnvelope, validateAttestationEnvelope, validateAuthorityBlock, validateLineageLink, } from './validate.js';
45
+ // MOVED IN 0.4.0 — the grant and delegation-chain VERIFIERS (`verifyAuthority`,
46
+ // `verifyDelegationChain`, `MAX_DELEGATION_DEPTH`) are authorization policy,
47
+ // not object identity, and are no longer exported from this entry. They live
48
+ // at the `@synoi/sraid/authority` subpath, unchanged and still verify-only.
49
+ //
50
+ // `capabilityCovers`, `AuthorityResolver` and `GrantStatus` did NOT move: they
51
+ // are the leaf primitive and the contract, and are exported above.
52
+ //
53
+ // REMOVED IN 0.4.0 — `validateSro`, `SRO`, `SROBody`. See CHANGELOG 0.4.0.
46
54
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,yEAAyE;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,oEAAoE;AACpE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAEhG,8EAA8E;AAC9E,OAAO,EACL,eAAe,GAGhB,MAAM,gBAAgB,CAAA;AAEvB,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAElE,wEAAwE;AACxE,yEAAyE;AACzE,4EAA4E;AAC5E,uEAAuE;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,0EAA0E;AAC1E,uEAAuE;AACvE,yEAAyE;AACzE,OAAO,EACL,iBAAiB,EACjB,GAAG,EACH,WAAW,EACX,aAAa,GAGd,MAAM,kBAAkB,CAAA;AAEzB,+EAA+E;AAC/E,OAAO,EACL,YAAY,EACZ,cAAc,EACd,UAAU,GAEX,MAAM,cAAc,CAAA;AAErB,mFAAmF;AACnF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AAEzB,mDAAmD;AACnD,OAAO,EACL,eAAe,EACf,gBAAgB,GAMjB,MAAM,gBAAgB,CAAA;AAEvB,gFAAgF;AAChF,6EAA6E;AAC7E,OAAO,EACL,qBAAqB,EACrB,oBAAoB,GAKrB,MAAM,gBAAgB,CAAA;AAEvB,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,WAAW,EACX,yBAAyB,EACzB,2BAA2B,EAC3B,sBAAsB,EACtB,mBAAmB,GAEpB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAeH,yEAAyE;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,oEAAoE;AACpE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAEhG,8EAA8E;AAC9E,OAAO,EACL,eAAe,GAGhB,MAAM,gBAAgB,CAAA;AAEvB,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAElE,wEAAwE;AACxE,yEAAyE;AACzE,4EAA4E;AAC5E,uEAAuE;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAE5D,uEAAuE;AACvE,uEAAuE;AACvE,yEAAyE;AACzE,OAAO,EACL,iBAAiB,EACjB,GAAG,EACH,WAAW,EACX,aAAa,GAGd,MAAM,kBAAkB,CAAA;AAEzB,+EAA+E;AAC/E,mEAAmE;AACnE,OAAO,EACL,YAAY,EACZ,cAAc,EACd,UAAU,GAEX,MAAM,cAAc,CAAA;AAErB,gFAAgF;AAChF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AAEzB,6EAA6E;AAC7E,0EAA0E;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAGlD,oBAAoB;AACpB,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,2BAA2B,EAC3B,sBAAsB,EACtB,mBAAmB,GAEpB,MAAM,eAAe,CAAA;AAEtB,gFAAgF;AAChF,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,EAAE;AACF,+EAA+E;AAC/E,mEAAmE;AACnE,EAAE;AACF,2EAA2E"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @synoi/sraid — internal/attestation-core.ts
3
+ *
4
+ * The crypto-agnostic core of the L2 DSSE attestation profile: the PAE
5
+ * encoding, the algorithm identifiers, the public verify input/result types,
6
+ * the both-required signature lookup, and the envelope-shape predicate.
7
+ *
8
+ * This is a PURE module — no crypto, no node:crypto, no Buffer — so the same
9
+ * PAE bytes, AND-policy shape, and type contract are shared byte-for-byte by
10
+ * BOTH the node default entry (attestation.ts, node:crypto verifiers) and the
11
+ * browser verify surface (verify-browser.ts, WebCrypto + @noble verifiers).
12
+ * Divergent PAE or shape logic between the two would be a signature-validity
13
+ * hazard; keeping it in one place removes that risk.
14
+ *
15
+ * The verify ORCHESTRATION (decode each sig, run both verifiers, gate on the
16
+ * AND policy) is intentionally NOT here: the node path is synchronous
17
+ * (node:crypto verify) and the browser path is asynchronous (WebCrypto verify),
18
+ * so a single shared body cannot serve both. Each entry keeps its own thin
19
+ * orchestration and reuses these leaf helpers.
20
+ */
21
+ import type { AttestationEnvelope, AttestationSignature } from '../types.js';
22
+ /** The single supported algorithm identifiers for the JSON profile. */
23
+ export declare const ALG_ED25519 = "ed25519";
24
+ export declare const ALG_ML_DSA_65 = "ml-dsa-65";
25
+ /**
26
+ * The DSSE Pre-Authentication Encoding (PAE).
27
+ *
28
+ * Per the DSSE spec:
29
+ *
30
+ * PAE(type, body) = "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body
31
+ *
32
+ * where:
33
+ * - SP is a single ASCII space (0x20),
34
+ * - LEN(x) is the ASCII-decimal byte length of x's UTF-8 encoding,
35
+ * - type and body are the raw UTF-8 bytes (NOT base64).
36
+ *
37
+ * Binding the payloadType (and both lengths) into the signed bytes is what
38
+ * makes a signature non-transferable across object types. Returns the raw
39
+ * bytes to be signed/verified.
40
+ */
41
+ export declare function pae(payloadType: string, payload: string | Uint8Array): Uint8Array;
42
+ export interface VerifyAttestationInput {
43
+ /**
44
+ * The DSSE attestation envelope to verify. Its `payloadType` is bound into
45
+ * the PAE; its `payload` is the canonical UTF-8 string that was signed.
46
+ */
47
+ envelope: AttestationEnvelope;
48
+ /** Raw 32-byte Ed25519 public key. */
49
+ ed25519_pub: Uint8Array;
50
+ /** Raw ML-DSA-65 public key bytes. */
51
+ ml_dsa_pub: Uint8Array;
52
+ /**
53
+ * Optional. If supplied, the verifier asserts the envelope's `payloadType`
54
+ * equals this value before verifying signatures — an explicit type-pinning
55
+ * check on top of the structural PAE binding. A mismatch fails with
56
+ * `payload-type-mismatch`.
57
+ */
58
+ expectedPayloadType?: string;
59
+ }
60
+ export interface VerifyAttestationResult {
61
+ /** True only when BOTH required signatures verified over the same PAE. */
62
+ valid: boolean;
63
+ /**
64
+ * Human-readable failure reasons. Empty when valid. Possible values:
65
+ * 'envelope-malformed', 'payload-type-mismatch', 'missing-ed25519',
66
+ * 'missing-ml-dsa-65', 'ed25519-malformed', 'ml-dsa-malformed',
67
+ * 'ed25519-invalid', 'ml-dsa-invalid'.
68
+ */
69
+ reasons: string[];
70
+ }
71
+ /**
72
+ * Structural well-formedness of an attestation envelope: a non-null object with
73
+ * a non-empty string `payloadType`, a string `payload`, and an array
74
+ * `signatures`. A false result maps to the `envelope-malformed` reason. This is
75
+ * the SINGLE definition of envelope shape, shared by the node and browser
76
+ * verifiers so they reject the same inputs.
77
+ */
78
+ export declare function isWellFormedEnvelope(env: unknown): env is AttestationEnvelope;
79
+ /**
80
+ * Find the first well-formed signature entry for `alg` (a `{ alg, sig }` object
81
+ * whose `sig` is a string). Returns undefined when absent; the AND policy in
82
+ * each verifier turns a missing pair member into a `missing-*` reason.
83
+ */
84
+ export declare function findSig(sigs: readonly AttestationSignature[], alg: string): AttestationSignature | undefined;
85
+ //# sourceMappingURL=attestation-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation-core.d.ts","sourceRoot":"","sources":["../../src/internal/attestation-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAE5E,uEAAuE;AACvE,eAAO,MAAM,WAAW,YAAY,CAAA;AACpC,eAAO,MAAM,aAAa,cAAc,CAAA;AAExC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAYjF;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,sCAAsC;IACtC,WAAW,EAAE,UAAU,CAAA;IACvB,sCAAsC;IACtC,UAAU,EAAE,UAAU,CAAA;IACtB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAA;IACd;;;;;OAKG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,mBAAmB,CAS7E;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,SAAS,oBAAoB,EAAE,EACrC,GAAG,EAAE,MAAM,GACV,oBAAoB,GAAG,SAAS,CAOlC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @synoi/sraid — internal/attestation-core.ts
3
+ *
4
+ * The crypto-agnostic core of the L2 DSSE attestation profile: the PAE
5
+ * encoding, the algorithm identifiers, the public verify input/result types,
6
+ * the both-required signature lookup, and the envelope-shape predicate.
7
+ *
8
+ * This is a PURE module — no crypto, no node:crypto, no Buffer — so the same
9
+ * PAE bytes, AND-policy shape, and type contract are shared byte-for-byte by
10
+ * BOTH the node default entry (attestation.ts, node:crypto verifiers) and the
11
+ * browser verify surface (verify-browser.ts, WebCrypto + @noble verifiers).
12
+ * Divergent PAE or shape logic between the two would be a signature-validity
13
+ * hazard; keeping it in one place removes that risk.
14
+ *
15
+ * The verify ORCHESTRATION (decode each sig, run both verifiers, gate on the
16
+ * AND policy) is intentionally NOT here: the node path is synchronous
17
+ * (node:crypto verify) and the browser path is asynchronous (WebCrypto verify),
18
+ * so a single shared body cannot serve both. Each entry keeps its own thin
19
+ * orchestration and reuses these leaf helpers.
20
+ */
21
+ /** The single supported algorithm identifiers for the JSON profile. */
22
+ export const ALG_ED25519 = 'ed25519';
23
+ export const ALG_ML_DSA_65 = 'ml-dsa-65';
24
+ /**
25
+ * The DSSE Pre-Authentication Encoding (PAE).
26
+ *
27
+ * Per the DSSE spec:
28
+ *
29
+ * PAE(type, body) = "DSSEv1" SP LEN(type) SP type SP LEN(body) SP body
30
+ *
31
+ * where:
32
+ * - SP is a single ASCII space (0x20),
33
+ * - LEN(x) is the ASCII-decimal byte length of x's UTF-8 encoding,
34
+ * - type and body are the raw UTF-8 bytes (NOT base64).
35
+ *
36
+ * Binding the payloadType (and both lengths) into the signed bytes is what
37
+ * makes a signature non-transferable across object types. Returns the raw
38
+ * bytes to be signed/verified.
39
+ */
40
+ export function pae(payloadType, payload) {
41
+ const enc = new TextEncoder();
42
+ const typeBytes = enc.encode(payloadType);
43
+ const bodyBytes = typeof payload === 'string' ? enc.encode(payload) : payload;
44
+ const prefix = enc.encode(`DSSEv1 ${typeBytes.length} ${payloadType} ${bodyBytes.length} `);
45
+ const out = new Uint8Array(prefix.length + bodyBytes.length);
46
+ out.set(prefix, 0);
47
+ out.set(bodyBytes, prefix.length);
48
+ return out;
49
+ }
50
+ /**
51
+ * Structural well-formedness of an attestation envelope: a non-null object with
52
+ * a non-empty string `payloadType`, a string `payload`, and an array
53
+ * `signatures`. A false result maps to the `envelope-malformed` reason. This is
54
+ * the SINGLE definition of envelope shape, shared by the node and browser
55
+ * verifiers so they reject the same inputs.
56
+ */
57
+ export function isWellFormedEnvelope(env) {
58
+ return (env !== null &&
59
+ typeof env === 'object' &&
60
+ typeof env.payloadType === 'string' &&
61
+ env.payloadType.length > 0 &&
62
+ typeof env.payload === 'string' &&
63
+ Array.isArray(env.signatures));
64
+ }
65
+ /**
66
+ * Find the first well-formed signature entry for `alg` (a `{ alg, sig }` object
67
+ * whose `sig` is a string). Returns undefined when absent; the AND policy in
68
+ * each verifier turns a missing pair member into a `missing-*` reason.
69
+ */
70
+ export function findSig(sigs, alg) {
71
+ for (const s of sigs) {
72
+ if (s && typeof s === 'object' && s.alg === alg && typeof s.sig === 'string') {
73
+ return s;
74
+ }
75
+ }
76
+ return undefined;
77
+ }
78
+ //# sourceMappingURL=attestation-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation-core.js","sourceRoot":"","sources":["../../src/internal/attestation-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAA;AACpC,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAA;AAExC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,GAAG,CAAC,WAAmB,EAAE,OAA4B;IACnE,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAA;IAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IACzC,MAAM,SAAS,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IAE7E,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CACvB,UAAU,SAAS,CAAC,MAAM,IAAI,WAAW,IAAI,SAAS,CAAC,MAAM,GAAG,CACjE,CAAA;IACD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5D,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAClB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACjC,OAAO,GAAG,CAAA;AACZ,CAAC;AAiCD;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,OAAO,CACL,GAAG,KAAK,IAAI;QACZ,OAAO,GAAG,KAAK,QAAQ;QACvB,OAAQ,GAA2B,CAAC,WAAW,KAAK,QAAQ;QAC3D,GAA2B,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QACnD,OAAQ,GAA2B,CAAC,OAAO,KAAK,QAAQ;QACxD,KAAK,CAAC,OAAO,CAAE,GAA2B,CAAC,UAAU,CAAC,CACvD,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,OAAO,CACrB,IAAqC,EACrC,GAAW;IAEX,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC7E,OAAO,CAAC,CAAA;QACV,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @synoi/sraid — internal/base64-browser.ts
3
+ *
4
+ * Strict standard-base64 (RFC 4648 §4, with `=` padding) decode for the
5
+ * BROWSER verify surface.
6
+ *
7
+ * INTERNAL: not exported from any public entry.
8
+ *
9
+ * Why a separate decoder: the node decoder (./base64.ts `decodeBase64Strict`)
10
+ * finishes with `Buffer.from(s, 'base64')`. `Buffer` is a NODE global that does
11
+ * not exist in a browser / service-worker / Chrome-extension context — and,
12
+ * crucially, it is NOT a `node:` specifier, so an esbuild `node:`-reference scan
13
+ * would NOT catch it. A `Buffer`-based decode would bundle clean yet throw
14
+ * `ReferenceError: Buffer is not defined` at runtime. This decoder is
15
+ * Buffer-free: it reuses the pure `assertBase64` validation (regex/length/
16
+ * padding only, from ./base64-validate.js — NOT ./base64.js, whose graph pulls
17
+ * in the `Buffer` decode) and decodes via the standard `atob` global, which IS
18
+ * available in browsers, dedicated/shared workers, and MV3 extension service
19
+ * workers.
20
+ *
21
+ * Same strict contract as the node path: throws Error('base64-malformed') on
22
+ * any deviation (illegal char, bad length, bad padding) rather than silently
23
+ * truncating, so a malformed signature is rejected loudly, never decoded to a
24
+ * short prefix that then "verifies" against something unintended.
25
+ */
26
+ /**
27
+ * Strictly decode standard base64 to raw bytes using only browser-safe globals.
28
+ * Throws Error('base64-malformed') on any non-conforming input.
29
+ */
30
+ export declare function decodeBase64StrictBrowser(s: string): Uint8Array;
31
+ //# sourceMappingURL=base64-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64-browser.d.ts","sourceRoot":"","sources":["../../src/internal/base64-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAM/D"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @synoi/sraid — internal/base64-browser.ts
3
+ *
4
+ * Strict standard-base64 (RFC 4648 §4, with `=` padding) decode for the
5
+ * BROWSER verify surface.
6
+ *
7
+ * INTERNAL: not exported from any public entry.
8
+ *
9
+ * Why a separate decoder: the node decoder (./base64.ts `decodeBase64Strict`)
10
+ * finishes with `Buffer.from(s, 'base64')`. `Buffer` is a NODE global that does
11
+ * not exist in a browser / service-worker / Chrome-extension context — and,
12
+ * crucially, it is NOT a `node:` specifier, so an esbuild `node:`-reference scan
13
+ * would NOT catch it. A `Buffer`-based decode would bundle clean yet throw
14
+ * `ReferenceError: Buffer is not defined` at runtime. This decoder is
15
+ * Buffer-free: it reuses the pure `assertBase64` validation (regex/length/
16
+ * padding only, from ./base64-validate.js — NOT ./base64.js, whose graph pulls
17
+ * in the `Buffer` decode) and decodes via the standard `atob` global, which IS
18
+ * available in browsers, dedicated/shared workers, and MV3 extension service
19
+ * workers.
20
+ *
21
+ * Same strict contract as the node path: throws Error('base64-malformed') on
22
+ * any deviation (illegal char, bad length, bad padding) rather than silently
23
+ * truncating, so a malformed signature is rejected loudly, never decoded to a
24
+ * short prefix that then "verifies" against something unintended.
25
+ */
26
+ import { assertBase64 } from './base64-validate.js';
27
+ /**
28
+ * Strictly decode standard base64 to raw bytes using only browser-safe globals.
29
+ * Throws Error('base64-malformed') on any non-conforming input.
30
+ */
31
+ export function decodeBase64StrictBrowser(s) {
32
+ assertBase64(s);
33
+ const bin = atob(s);
34
+ const out = new Uint8Array(bin.length);
35
+ for (let i = 0; i < bin.length; i++)
36
+ out[i] = bin.charCodeAt(i);
37
+ return out;
38
+ }
39
+ //# sourceMappingURL=base64-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64-browser.js","sourceRoot":"","sources":["../../src/internal/base64-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,CAAS;IACjD,YAAY,CAAC,CAAC,CAAC,CAAA;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACtC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAC/D,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @synoi/sraid — internal/base64-validate.ts
3
+ *
4
+ * Pure strict standard-base64 (RFC 4648 §4, with `=` padding) VALIDATION.
5
+ *
6
+ * INTERNAL: not exported from any public entry.
7
+ *
8
+ * This is the Buffer-free, node:crypto-free half of base64 handling, split out
9
+ * so the browser decoder (./base64-browser.ts) can validate without importing
10
+ * ./base64.ts (whose `decodeBase64Strict` uses the node `Buffer` global — safe
11
+ * in node, a runtime `ReferenceError` in a browser). The node decoder re-uses
12
+ * this same validator, so both paths reject exactly the same inputs.
13
+ */
14
+ /**
15
+ * Validate strict standard base64. Throws Error('base64-malformed') on any
16
+ * non-conforming input.
17
+ */
18
+ export declare function assertBase64(s: string): void;
19
+ //# sourceMappingURL=base64-validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64-validate.d.ts","sourceRoot":"","sources":["../../src/internal/base64-validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ5C"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @synoi/sraid — internal/base64-validate.ts
3
+ *
4
+ * Pure strict standard-base64 (RFC 4648 §4, with `=` padding) VALIDATION.
5
+ *
6
+ * INTERNAL: not exported from any public entry.
7
+ *
8
+ * This is the Buffer-free, node:crypto-free half of base64 handling, split out
9
+ * so the browser decoder (./base64-browser.ts) can validate without importing
10
+ * ./base64.ts (whose `decodeBase64Strict` uses the node `Buffer` global — safe
11
+ * in node, a runtime `ReferenceError` in a browser). The node decoder re-uses
12
+ * this same validator, so both paths reject exactly the same inputs.
13
+ */
14
+ // Standard base64 alphabet; `=` only as 1-2 trailing pad chars. Total length
15
+ // must be a multiple of 4.
16
+ const STD_B64 = /^[A-Za-z0-9+/]*={0,2}$/;
17
+ /**
18
+ * Validate strict standard base64. Throws Error('base64-malformed') on any
19
+ * non-conforming input.
20
+ */
21
+ export function assertBase64(s) {
22
+ if (typeof s !== 'string')
23
+ throw new Error('base64-malformed');
24
+ if (s.length % 4 !== 0)
25
+ throw new Error('base64-malformed');
26
+ if (!STD_B64.test(s))
27
+ throw new Error('base64-malformed');
28
+ // `=` may appear only in the final 1-2 positions. The regex `={0,2}` anchored
29
+ // at end already guarantees pad chars are contiguous and trailing, but a pad
30
+ // char earlier in the body would have been rejected by the alphabet class —
31
+ // so an in-body `=` cannot pass STD_B64. No extra check needed.
32
+ }
33
+ //# sourceMappingURL=base64-validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64-validate.js","sourceRoot":"","sources":["../../src/internal/base64-validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,6EAA6E;AAC7E,2BAA2B;AAC3B,MAAM,OAAO,GAAG,wBAAwB,CAAA;AAExC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAC9D,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAC3D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACzD,8EAA8E;IAC9E,6EAA6E;IAC7E,4EAA4E;IAC5E,gEAAgE;AAClE,CAAC"}
@@ -14,12 +14,14 @@
14
14
  *
15
15
  * Canonical inputs carry no surrounding whitespace, so no trim is applied;
16
16
  * leading/trailing whitespace is itself a rejection.
17
+ *
18
+ * The strict VALIDATION (alphabet/length/padding) lives in the pure, Buffer-
19
+ * free ./base64-validate.ts so the browser decoder can share it; this module
20
+ * adds the node `Buffer`-based decode on top and re-exports `assertBase64` so
21
+ * existing importers of `./base64.js` are unchanged.
17
22
  */
18
- /**
19
- * Validate strict standard base64. Throws Error('base64-malformed') on any
20
- * non-conforming input.
21
- */
22
- export declare function assertBase64(s: string): void;
23
+ import { assertBase64 } from './base64-validate.js';
24
+ export { assertBase64 };
23
25
  /**
24
26
  * Strictly decode standard base64 to raw bytes. Throws
25
27
  * Error('base64-malformed') on any non-conforming input.
@@ -1 +1 @@
1
- {"version":3,"file":"base64.d.ts","sourceRoot":"","sources":["../../src/internal/base64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAQ5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAGxD"}
1
+ {"version":3,"file":"base64.d.ts","sourceRoot":"","sources":["../../src/internal/base64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAGxD"}
@@ -14,26 +14,14 @@
14
14
  *
15
15
  * Canonical inputs carry no surrounding whitespace, so no trim is applied;
16
16
  * leading/trailing whitespace is itself a rejection.
17
+ *
18
+ * The strict VALIDATION (alphabet/length/padding) lives in the pure, Buffer-
19
+ * free ./base64-validate.ts so the browser decoder can share it; this module
20
+ * adds the node `Buffer`-based decode on top and re-exports `assertBase64` so
21
+ * existing importers of `./base64.js` are unchanged.
17
22
  */
18
- // Standard base64 alphabet; `=` only as 1-2 trailing pad chars. Total length
19
- // must be a multiple of 4.
20
- const STD_B64 = /^[A-Za-z0-9+/]*={0,2}$/;
21
- /**
22
- * Validate strict standard base64. Throws Error('base64-malformed') on any
23
- * non-conforming input.
24
- */
25
- export function assertBase64(s) {
26
- if (typeof s !== 'string')
27
- throw new Error('base64-malformed');
28
- if (s.length % 4 !== 0)
29
- throw new Error('base64-malformed');
30
- if (!STD_B64.test(s))
31
- throw new Error('base64-malformed');
32
- // `=` may appear only in the final 1-2 positions. The regex `={0,2}` anchored
33
- // at end already guarantees pad chars are contiguous and trailing, but a pad
34
- // char earlier in the body would have been rejected by the alphabet class —
35
- // so an in-body `=` cannot pass STD_B64. No extra check needed.
36
- }
23
+ import { assertBase64 } from './base64-validate.js';
24
+ export { assertBase64 };
37
25
  /**
38
26
  * Strictly decode standard base64 to raw bytes. Throws
39
27
  * Error('base64-malformed') on any non-conforming input.
@@ -1 +1 @@
1
- {"version":3,"file":"base64.js","sourceRoot":"","sources":["../../src/internal/base64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,6EAA6E;AAC7E,2BAA2B;AAC3B,MAAM,OAAO,GAAG,wBAAwB,CAAA;AAExC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAC9D,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAC3D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACzD,8EAA8E;IAC9E,6EAA6E;IAC7E,4EAA4E;IAC5E,gEAAgE;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,YAAY,CAAC,CAAC,CAAC,CAAA;IACf,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;AACjD,CAAC"}
1
+ {"version":3,"file":"base64.js","sourceRoot":"","sources":["../../src/internal/base64.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,OAAO,EAAE,YAAY,EAAE,CAAA;AAEvB;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAS;IAC1C,YAAY,CAAC,CAAC,CAAC,CAAA;IACf,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAA;AACjD,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @synoi/sraid — internal/content-core.ts
3
+ *
4
+ * The CDRO OID content-core projection: the normative strip-set and the
5
+ * field-removal function that together define WHAT bytes an OID is computed
6
+ * over. This is a PURE module — no hashing, no node:crypto, no Buffer — so it
7
+ * is safe to import from both the node default entry (via oid.ts) and the
8
+ * browser verify surface (via verify-browser.ts) without dragging node
9
+ * builtins into a browser bundle.
10
+ *
11
+ * This is the SINGLE NORMATIVE SOURCE of the CDRO OID projection (ADR_019).
12
+ * oid.ts re-exports these symbols and layers the SHA-256 hashing on top; every
13
+ * other surface (GAP SDKs, the gateway signer, IMPLEMENTING.md) derives from
14
+ * THIS set, never re-lists it.
15
+ */
16
+ /**
17
+ * The detached-signature / envelope fields removed by `cdroContentCore`
18
+ * before hashing. This is the SINGLE NORMATIVE strip-set for the CDRO OID
19
+ * projection (ADR_019 decision 1); every other surface (GAP SDKs, the
20
+ * gateway signer, IMPLEMENTING.md) derives from THIS set, never re-lists it.
21
+ *
22
+ * The set is defined SEMANTICALLY: it is "every field produced BY the signer
23
+ * after canonicalization, plus the OID output itself." Concretely:
24
+ *
25
+ * oid — the projection OUTPUT (cannot be an input to itself).
26
+ * signature — legacy hybrid SignatureEnvelope (attaches after hash).
27
+ * ml_dsa_signature — detached PQ signature (attaches after hash).
28
+ * signature_key_id — signer-stamped key id (produced by the signer).
29
+ * signature_algorithm — signer-stamped alg id (produced by the signer).
30
+ * attestation — DSSE AttestationEnvelope (attaches after hash).
31
+ *
32
+ * EVERYTHING ELSE IS KEPT and hashed into the OID, including in particular:
33
+ * - `gap_version` — IN identity so a protocol downgrade is OID-detectable.
34
+ * - `supersedes` — IN identity because the SRAID Merkle-DAG head-proves-
35
+ * history property requires every lineage edge inside the
36
+ * hash. Superseding mints a NEW object; it never mutates
37
+ * the old one's bytes, so keeping it here is safe and
38
+ * makes the lineage edge tamper-evident.
39
+ * - `type`, `sraid_version`, `tenant_id`, `created_at_ms`, `created_by`,
40
+ * `body`, `authority`, `sensitivity`, `prev`, `links`, and any other
41
+ * content field.
42
+ *
43
+ * This is the ONE projection that yields the SAME OID whether the object is
44
+ * pre- or post-attestation: attaching an `attestation` (or `signature`,
45
+ * `ml_dsa_signature`, `signature_key_id`, `signature_algorithm`) after hashing
46
+ * is stripped back out here, so `cdroOid(obj)` is invariant across signing.
47
+ *
48
+ * It is FROZEN so no caller can mutate the normative set at runtime.
49
+ */
50
+ export declare const CDRO_ENVELOPE_FIELDS: readonly string[];
51
+ /**
52
+ * Build the OID content core of a full CDRO: the object with EXACTLY the six
53
+ * detached-signature / envelope fields in `CDRO_ENVELOPE_FIELDS` removed at
54
+ * the top level, and everything else kept.
55
+ *
56
+ * This is the mechanism that makes the L4 `authority` block, the L3 lineage
57
+ * edges (`prev`, `links`, `supersedes`), the propagating `sensitivity` tier,
58
+ * and `gap_version` tamper-evident: they are hashed into identity by
59
+ * construction, so a field cannot be added, stripped, re-pointed, or
60
+ * downgraded without producing a different OID (and invalidating the
61
+ * signature, which is computed over these same bytes). Because `prev`/`links`/
62
+ * `supersedes` OIDs are inside the hash, a node's OID transitively commits its
63
+ * whole reachable history (the Merkle-DAG "head proves history" property).
64
+ *
65
+ * Returns a plain object suitable for `canonicalize` / `oidOf`.
66
+ */
67
+ export declare function cdroContentCore(cdro: unknown): Record<string, unknown>;
68
+ //# sourceMappingURL=content-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-core.d.ts","sourceRoot":"","sources":["../../src/internal/content-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAOhD,CAAA;AAIF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUtE"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @synoi/sraid — internal/content-core.ts
3
+ *
4
+ * The CDRO OID content-core projection: the normative strip-set and the
5
+ * field-removal function that together define WHAT bytes an OID is computed
6
+ * over. This is a PURE module — no hashing, no node:crypto, no Buffer — so it
7
+ * is safe to import from both the node default entry (via oid.ts) and the
8
+ * browser verify surface (via verify-browser.ts) without dragging node
9
+ * builtins into a browser bundle.
10
+ *
11
+ * This is the SINGLE NORMATIVE SOURCE of the CDRO OID projection (ADR_019).
12
+ * oid.ts re-exports these symbols and layers the SHA-256 hashing on top; every
13
+ * other surface (GAP SDKs, the gateway signer, IMPLEMENTING.md) derives from
14
+ * THIS set, never re-lists it.
15
+ */
16
+ /**
17
+ * The detached-signature / envelope fields removed by `cdroContentCore`
18
+ * before hashing. This is the SINGLE NORMATIVE strip-set for the CDRO OID
19
+ * projection (ADR_019 decision 1); every other surface (GAP SDKs, the
20
+ * gateway signer, IMPLEMENTING.md) derives from THIS set, never re-lists it.
21
+ *
22
+ * The set is defined SEMANTICALLY: it is "every field produced BY the signer
23
+ * after canonicalization, plus the OID output itself." Concretely:
24
+ *
25
+ * oid — the projection OUTPUT (cannot be an input to itself).
26
+ * signature — legacy hybrid SignatureEnvelope (attaches after hash).
27
+ * ml_dsa_signature — detached PQ signature (attaches after hash).
28
+ * signature_key_id — signer-stamped key id (produced by the signer).
29
+ * signature_algorithm — signer-stamped alg id (produced by the signer).
30
+ * attestation — DSSE AttestationEnvelope (attaches after hash).
31
+ *
32
+ * EVERYTHING ELSE IS KEPT and hashed into the OID, including in particular:
33
+ * - `gap_version` — IN identity so a protocol downgrade is OID-detectable.
34
+ * - `supersedes` — IN identity because the SRAID Merkle-DAG head-proves-
35
+ * history property requires every lineage edge inside the
36
+ * hash. Superseding mints a NEW object; it never mutates
37
+ * the old one's bytes, so keeping it here is safe and
38
+ * makes the lineage edge tamper-evident.
39
+ * - `type`, `sraid_version`, `tenant_id`, `created_at_ms`, `created_by`,
40
+ * `body`, `authority`, `sensitivity`, `prev`, `links`, and any other
41
+ * content field.
42
+ *
43
+ * This is the ONE projection that yields the SAME OID whether the object is
44
+ * pre- or post-attestation: attaching an `attestation` (or `signature`,
45
+ * `ml_dsa_signature`, `signature_key_id`, `signature_algorithm`) after hashing
46
+ * is stripped back out here, so `cdroOid(obj)` is invariant across signing.
47
+ *
48
+ * It is FROZEN so no caller can mutate the normative set at runtime.
49
+ */
50
+ export const CDRO_ENVELOPE_FIELDS = Object.freeze([
51
+ 'oid',
52
+ 'signature',
53
+ 'ml_dsa_signature',
54
+ 'signature_key_id',
55
+ 'signature_algorithm',
56
+ 'attestation',
57
+ ]);
58
+ const CDRO_ENVELOPE_FIELD_SET = new Set(CDRO_ENVELOPE_FIELDS);
59
+ /**
60
+ * Build the OID content core of a full CDRO: the object with EXACTLY the six
61
+ * detached-signature / envelope fields in `CDRO_ENVELOPE_FIELDS` removed at
62
+ * the top level, and everything else kept.
63
+ *
64
+ * This is the mechanism that makes the L4 `authority` block, the L3 lineage
65
+ * edges (`prev`, `links`, `supersedes`), the propagating `sensitivity` tier,
66
+ * and `gap_version` tamper-evident: they are hashed into identity by
67
+ * construction, so a field cannot be added, stripped, re-pointed, or
68
+ * downgraded without producing a different OID (and invalidating the
69
+ * signature, which is computed over these same bytes). Because `prev`/`links`/
70
+ * `supersedes` OIDs are inside the hash, a node's OID transitively commits its
71
+ * whole reachable history (the Merkle-DAG "head proves history" property).
72
+ *
73
+ * Returns a plain object suitable for `canonicalize` / `oidOf`.
74
+ */
75
+ export function cdroContentCore(cdro) {
76
+ if (cdro === null || typeof cdro !== 'object' || Array.isArray(cdro)) {
77
+ throw new TypeError('cdroContentCore: argument must be a CDRO object');
78
+ }
79
+ const core = {};
80
+ for (const [k, v] of Object.entries(cdro)) {
81
+ if (CDRO_ENVELOPE_FIELD_SET.has(k))
82
+ continue;
83
+ core[k] = v;
84
+ }
85
+ return core;
86
+ }
87
+ //# sourceMappingURL=content-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-core.js","sourceRoot":"","sources":["../../src/internal/content-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAsB,MAAM,CAAC,MAAM,CAAC;IACnE,KAAK;IACL,WAAW;IACX,kBAAkB;IAClB,kBAAkB;IAClB,qBAAqB;IACrB,aAAa;CACd,CAAC,CAAA;AAEF,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAA;AAElF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAAC,IAAa;IAC3C,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAA;IACxE,CAAC;IACD,MAAM,IAAI,GAA4B,EAAE,CAAA;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAA+B,CAAC,EAAE,CAAC;QACrE,IAAI,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,SAAQ;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACb,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}