@synoi/sraid 0.2.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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/PROJECTION_SPEC.md +245 -0
  3. package/README.md +149 -0
  4. package/SPEC.md +216 -0
  5. package/dist/attestation.d.ts +92 -0
  6. package/dist/attestation.d.ts.map +1 -0
  7. package/dist/attestation.js +155 -0
  8. package/dist/attestation.js.map +1 -0
  9. package/dist/authority.d.ts +351 -0
  10. package/dist/authority.d.ts.map +1 -0
  11. package/dist/authority.js +563 -0
  12. package/dist/authority.js.map +1 -0
  13. package/dist/canonicalize.d.ts +70 -0
  14. package/dist/canonicalize.d.ts.map +1 -0
  15. package/dist/canonicalize.js +151 -0
  16. package/dist/canonicalize.js.map +1 -0
  17. package/dist/ed25519.d.ts +26 -0
  18. package/dist/ed25519.d.ts.map +1 -0
  19. package/dist/ed25519.js +53 -0
  20. package/dist/ed25519.js.map +1 -0
  21. package/dist/index.d.ts +28 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +46 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/internal/base64.d.ts +28 -0
  26. package/dist/internal/base64.d.ts.map +1 -0
  27. package/dist/internal/base64.js +45 -0
  28. package/dist/internal/base64.js.map +1 -0
  29. package/dist/internal/key-cache.d.ts +47 -0
  30. package/dist/internal/key-cache.d.ts.map +1 -0
  31. package/dist/internal/key-cache.js +77 -0
  32. package/dist/internal/key-cache.js.map +1 -0
  33. package/dist/lineage.d.ts +104 -0
  34. package/dist/lineage.d.ts.map +1 -0
  35. package/dist/lineage.js +0 -0
  36. package/dist/lineage.js.map +1 -0
  37. package/dist/mldsa.d.ts +41 -0
  38. package/dist/mldsa.d.ts.map +1 -0
  39. package/dist/mldsa.js +119 -0
  40. package/dist/mldsa.js.map +1 -0
  41. package/dist/oid.d.ts +109 -0
  42. package/dist/oid.d.ts.map +1 -0
  43. package/dist/oid.js +140 -0
  44. package/dist/oid.js.map +1 -0
  45. package/dist/sensitivity.d.ts +104 -0
  46. package/dist/sensitivity.d.ts.map +1 -0
  47. package/dist/sensitivity.js +117 -0
  48. package/dist/sensitivity.js.map +1 -0
  49. package/dist/signature.d.ts +46 -0
  50. package/dist/signature.d.ts.map +1 -0
  51. package/dist/signature.js +89 -0
  52. package/dist/signature.js.map +1 -0
  53. package/dist/types.d.ts +313 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +16 -0
  56. package/dist/types.js.map +1 -0
  57. package/dist/validate.d.ts +88 -0
  58. package/dist/validate.d.ts.map +1 -0
  59. package/dist/validate.js +339 -0
  60. package/dist/validate.js.map +1 -0
  61. package/package.json +69 -0
  62. package/src/attestation.ts +204 -0
  63. package/src/authority.ts +849 -0
  64. package/src/canonicalize.ts +167 -0
  65. package/src/ed25519.ts +60 -0
  66. package/src/index.ts +118 -0
  67. package/src/internal/base64.ts +44 -0
  68. package/src/internal/key-cache.ts +79 -0
  69. package/src/lineage.ts +0 -0
  70. package/src/mldsa.ts +131 -0
  71. package/src/oid.ts +146 -0
  72. package/src/sensitivity.ts +154 -0
  73. package/src/signature.ts +119 -0
  74. package/src/types.ts +351 -0
  75. package/src/validate.ts +402 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitivity.d.ts","sourceRoot":"","sources":["../src/sensitivity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAE9D;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAM7C,CAAA;AAEX,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,EAAE,eAAsB,CAAA;AAMxD,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,eAAe,CAElE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAM7D;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,eAAe,EAClB,CAAC,EAAE,eAAe,GACjB,eAAe,CAEjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,aAAa,CAAC,eAAe,GAAG,SAAS,GAAG,IAAI,CAAC,GACzD,eAAe,CAYjB;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,aAAa,CAAC,eAAe,GAAG,SAAS,GAAG,IAAI,CAAC,GACzD;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,CAOpE"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @synoi/sraid — sensitivity.ts
3
+ *
4
+ * L4 GOVERNANCE — the propagating sensitivity label (OBJECT_MODEL_CLEANSHEET
5
+ * §3.4, SRAID_FOUNDATION_PUNCHLIST A5). A single coarse, OPAQUE tier on the
6
+ * CDRO that retrieval, summarization, and consolidation MUST carry forward
7
+ * monotonically: a derived object inherits the HIGHEST tier among its sources,
8
+ * so a summary of high-sensitivity inputs cannot be downgraded.
9
+ *
10
+ * ── Why the tiers are OPAQUE ORDINALS, not literal categories ───────────────
11
+ *
12
+ * SPEC §7 is normative and explicit: the envelope is a NON-encrypted, signed,
13
+ * publicly visible surface. A literal classification label (e.g. `"phi"`,
14
+ * `"health"`, `"financial"`) on that surface would LEAK the nature of the
15
+ * encrypted `body` — an observer who cannot read the ciphertext could still
16
+ * read "this is health data" off the envelope. SPEC §7 therefore requires a
17
+ * "coarse, OPAQUE sensitivity classifier", and the §9 reserved note says the
18
+ * same.
19
+ *
20
+ * So the tier set here is a small, COARSE, ORDERED ladder of opaque levels
21
+ * (`s0` < `s1` < `s2` < `s3` < `s4`). It carries an ORDERING (needed for the
22
+ * monotone `max()` lattice — standard lattice-based information-flow labeling,
23
+ * Denning 1976) but NO semantic category. The mapping from a regulatory
24
+ * category (PHI, PII, secret, …) to a tier is a higher-layer POLICY concern
25
+ * kept OFF the public envelope: an operator's policy decides "PHI → s3"
26
+ * privately; the wire only ever shows `s3`. This is the "coarse, opaque tier
27
+ * (or opaque policy-scope handle)" required by the task and SPEC §7.
28
+ *
29
+ * The field is hashed into the OID (it is a content-core field; see
30
+ * `cdroContentCore` in oid.ts), so it cannot be silently stripped or
31
+ * downgraded without changing the OID and breaking the signature.
32
+ *
33
+ * NOTE on maturity (CLAIMS_DISCIPLINE): this module ships the FIELD, the
34
+ * lattice, the monotone `max()` carry-forward, and the validator, with
35
+ * vectors. The commitment-based selective-disclosure scheme that would
36
+ * CONCEAL the tier itself (SPEC §7 / §9) is reserved and NOT built here.
37
+ */
38
+ /**
39
+ * The ordered tier ladder, lowest-first. The index IS the rank used by the
40
+ * `max()` lattice. Frozen so the ordering is immutable at runtime.
41
+ */
42
+ export const SENSITIVITY_TIERS = Object.freeze([
43
+ 's0',
44
+ 's1',
45
+ 's2',
46
+ 's3',
47
+ 's4',
48
+ ]);
49
+ /** The default tier for an object that declares none — the lattice floor. */
50
+ export const SENSITIVITY_DEFAULT = 's0';
51
+ const RANK = new Map(SENSITIVITY_TIERS.map((t, i) => [t, i]));
52
+ /** True iff `x` is a defined `SensitivityTier`. */
53
+ export function isSensitivityTier(x) {
54
+ return typeof x === 'string' && RANK.has(x);
55
+ }
56
+ /**
57
+ * The ordinal rank of a tier (0 = lowest). Throws on an unknown tier so a
58
+ * typo can never silently rank as the floor (which would be a downgrade
59
+ * footgun in the lattice).
60
+ */
61
+ export function sensitivityRank(tier) {
62
+ const r = RANK.get(tier);
63
+ if (r === undefined) {
64
+ throw new RangeError(`sensitivityRank: "${String(tier)}" is not a known tier`);
65
+ }
66
+ return r;
67
+ }
68
+ /**
69
+ * The monotone lattice join: the HIGHER (more restricted) of two tiers.
70
+ * `max('s1','s3') === 's3'`. This is the per-pair operation behind
71
+ * carry-forward.
72
+ */
73
+ export function sensitivityMax(a, b) {
74
+ return sensitivityRank(a) >= sensitivityRank(b) ? a : b;
75
+ }
76
+ /**
77
+ * Carry-forward over a set of source tiers: the highest tier present.
78
+ *
79
+ * This is the rule that makes sensitivity MONOTONE under derivation
80
+ * (retrieval / summarization / consolidation): a derived object's tier =
81
+ * max(tiers of all its `consolidated_from` / `derived_from` sources). It can
82
+ * only ever go UP, never down — a summary of high-sensitivity inputs stays at
83
+ * the highest input tier.
84
+ *
85
+ * `undefined`/absent source tiers are treated as the floor (`s0`): a source
86
+ * that declared no tier cannot pull the result down, and an explicit higher
87
+ * source always wins. An empty input set returns the floor.
88
+ */
89
+ export function sensitivityCarryForward(sources) {
90
+ let acc = SENSITIVITY_DEFAULT;
91
+ for (const s of sources) {
92
+ if (s === undefined || s === null)
93
+ continue;
94
+ if (!isSensitivityTier(s)) {
95
+ throw new RangeError(`sensitivityCarryForward: "${String(s)}" is not a known tier`);
96
+ }
97
+ acc = sensitivityMax(acc, s);
98
+ }
99
+ return acc;
100
+ }
101
+ /**
102
+ * Guard a proposed sensitivity assignment against monotone violation: the
103
+ * `proposed` tier of a derived object MUST be at least as high as the
104
+ * carry-forward of its `sources`. Returns the floor the derived object is NOT
105
+ * allowed to fall below, plus whether `proposed` honors it.
106
+ *
107
+ * Use this to REJECT an attempt to label a summary of `s3` inputs as `s1`.
108
+ */
109
+ export function sensitivityMonotoneCheck(proposed, sources) {
110
+ const floor = sensitivityCarryForward(sources);
111
+ return {
112
+ ok: sensitivityRank(proposed) >= sensitivityRank(floor),
113
+ floor,
114
+ proposed,
115
+ };
116
+ }
117
+ //# sourceMappingURL=sensitivity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitivity.js","sourceRoot":"","sources":["../src/sensitivity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAqBH;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA+B,MAAM,CAAC,MAAM,CAAC;IACzE,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;CACI,CAAC,CAAA;AAEX,6EAA6E;AAC7E,MAAM,CAAC,MAAM,mBAAmB,GAAoB,IAAI,CAAA;AAExD,MAAM,IAAI,GAAgC,IAAI,GAAG,CAC/C,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CACxC,CAAA;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB,CAAC,CAAU;IAC1C,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAqB;IACnD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACxB,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACpB,MAAM,IAAI,UAAU,CAAC,qBAAqB,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAA;IAChF,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,CAAkB,EAClB,CAAkB;IAElB,OAAO,eAAe,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACzD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA0D;IAE1D,IAAI,GAAG,GAAoB,mBAAmB,CAAA;IAC9C,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;YAAE,SAAQ;QAC3C,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAClB,6BAA6B,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAC9D,CAAA;QACH,CAAC;QACD,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;IAC9B,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAyB,EACzB,OAA0D;IAE1D,MAAM,KAAK,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAA;IAC9C,OAAO;QACL,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC;QACvD,KAAK;QACL,QAAQ;KACT,CAAA;AACH,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @synoi/sraid — signature.ts
3
+ *
4
+ * Hybrid ed25519 + ml-dsa-65 signature verification for CDRO envelopes.
5
+ *
6
+ * SynOI signs every Decision Receipt and every governance object with
7
+ * BOTH a classical Ed25519 signature and a post-quantum ML-DSA-65
8
+ * signature. The verifier in this package requires BOTH to be valid
9
+ * before returning `valid: true` — even though either alone is
10
+ * cryptographically meaningful, signed objects exit the system only when
11
+ * both check out.
12
+ *
13
+ * The signature bytes are computed over the canonical form of the object
14
+ * minus the `signature` field itself. Callers are expected to produce
15
+ * that canonical form (typically via `canonicalize()` in this package)
16
+ * and pass it as `canonical` here — verifiers MUST use the same exact
17
+ * bytes that the signer used, so callers control that contract.
18
+ */
19
+ import type { SignatureEnvelope } from './types.js';
20
+ export interface VerifySignatureInput {
21
+ /** The canonical bytes that were signed (string is utf-8 encoded). */
22
+ canonical: string | Uint8Array;
23
+ /** Signature envelope to verify. */
24
+ envelope: SignatureEnvelope;
25
+ /** Raw 32-byte Ed25519 public key. */
26
+ ed25519_pub: Uint8Array;
27
+ /** Raw ML-DSA-65 public key bytes. */
28
+ ml_dsa_pub: Uint8Array;
29
+ }
30
+ export interface VerifySignatureResult {
31
+ /** True only when BOTH signatures verified successfully. */
32
+ valid: boolean;
33
+ /**
34
+ * Human-readable reasons for failure. Empty when valid. Possible
35
+ * values: 'ed25519-invalid', 'ml-dsa-invalid', 'ed25519-malformed',
36
+ * 'ml-dsa-malformed', 'envelope-malformed'.
37
+ */
38
+ reasons: string[];
39
+ }
40
+ /**
41
+ * Verify a hybrid CDRO signature envelope. Returns `valid: true` only
42
+ * when both the Ed25519 and the ML-DSA-65 signatures verify against the
43
+ * supplied public keys and canonical bytes.
44
+ */
45
+ export declare function verifySignature(input: VerifySignatureInput): VerifySignatureResult;
46
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,UAAU,CAAA;IAC9B,oCAAoC;IACpC,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,sCAAsC;IACtC,WAAW,EAAE,UAAU,CAAA;IACvB,sCAAsC;IACtC,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,KAAK,EAAE,OAAO,CAAA;IACd;;;;OAIG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAyDlF"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @synoi/sraid — signature.ts
3
+ *
4
+ * Hybrid ed25519 + ml-dsa-65 signature verification for CDRO envelopes.
5
+ *
6
+ * SynOI signs every Decision Receipt and every governance object with
7
+ * BOTH a classical Ed25519 signature and a post-quantum ML-DSA-65
8
+ * signature. The verifier in this package requires BOTH to be valid
9
+ * before returning `valid: true` — even though either alone is
10
+ * cryptographically meaningful, signed objects exit the system only when
11
+ * both check out.
12
+ *
13
+ * The signature bytes are computed over the canonical form of the object
14
+ * minus the `signature` field itself. Callers are expected to produce
15
+ * that canonical form (typically via `canonicalize()` in this package)
16
+ * and pass it as `canonical` here — verifiers MUST use the same exact
17
+ * bytes that the signer used, so callers control that contract.
18
+ */
19
+ import { verifyEd25519 } from './ed25519.js';
20
+ import { decodeBase64Strict } from './internal/base64.js';
21
+ import { verifyMlDsa65 } from './mldsa.js';
22
+ /**
23
+ * Verify a hybrid CDRO signature envelope. Returns `valid: true` only
24
+ * when both the Ed25519 and the ML-DSA-65 signatures verify against the
25
+ * supplied public keys and canonical bytes.
26
+ */
27
+ export function verifySignature(input) {
28
+ const reasons = [];
29
+ if (!input.envelope ||
30
+ typeof input.envelope.ed25519 !== 'string' ||
31
+ typeof input.envelope.ml_dsa_65 !== 'string' ||
32
+ typeof input.envelope.signer_kid !== 'string') {
33
+ return { valid: false, reasons: ['envelope-malformed'] };
34
+ }
35
+ const message = typeof input.canonical === 'string'
36
+ ? new TextEncoder().encode(input.canonical)
37
+ : input.canonical;
38
+ // Decode the two signatures from base64. If either fails to decode,
39
+ // the envelope is malformed — but we still want to verify the OTHER
40
+ // signature so we can report both reasons in one pass.
41
+ let edSig = null;
42
+ let mlSig = null;
43
+ try {
44
+ edSig = fromBase64(input.envelope.ed25519);
45
+ }
46
+ catch {
47
+ reasons.push('ed25519-malformed');
48
+ }
49
+ try {
50
+ mlSig = fromBase64(input.envelope.ml_dsa_65);
51
+ }
52
+ catch {
53
+ reasons.push('ml-dsa-malformed');
54
+ }
55
+ let edOk = false;
56
+ let mlOk = false;
57
+ if (edSig) {
58
+ try {
59
+ edOk = verifyEd25519(edSig, message, input.ed25519_pub);
60
+ }
61
+ catch {
62
+ // Treat invalid signature shape as a verification failure rather
63
+ // than a thrown exception, so callers can rely on a clean result.
64
+ edOk = false;
65
+ }
66
+ if (!edOk)
67
+ reasons.push('ed25519-invalid');
68
+ }
69
+ if (mlSig) {
70
+ try {
71
+ mlOk = verifyMlDsa65(mlSig, message, input.ml_dsa_pub);
72
+ }
73
+ catch {
74
+ mlOk = false;
75
+ }
76
+ if (!mlOk)
77
+ reasons.push('ml-dsa-invalid');
78
+ }
79
+ return { valid: edOk && mlOk, reasons };
80
+ }
81
+ // ── Base64 helpers (standard, with `=` padding) ──────────────────────────────
82
+ // Strict standard base64. Throws Error('base64-malformed') on any deviation
83
+ // rather than silently truncating at the first illegal byte. Both call sites
84
+ // wrap this in try/catch and map the throw to a *-malformed reason, so
85
+ // verifySignature never throws.
86
+ function fromBase64(s) {
87
+ return decodeBase64Strict(s);
88
+ }
89
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../src/signature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAyB1C;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,MAAM,OAAO,GAAa,EAAE,CAAA;IAE5B,IACE,CAAC,KAAK,CAAC,QAAQ;QACf,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,KAAK,QAAQ;QAC1C,OAAO,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ;QAC5C,OAAO,KAAK,CAAC,QAAQ,CAAC,UAAU,KAAK,QAAQ,EAC7C,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAA;IAC1D,CAAC;IAED,MAAM,OAAO,GACX,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;QACjC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;QAC3C,CAAC,CAAC,KAAK,CAAC,SAAS,CAAA;IAErB,oEAAoE;IACpE,oEAAoE;IACpE,uDAAuD;IACvD,IAAI,KAAK,GAAsB,IAAI,CAAA;IACnC,IAAI,KAAK,GAAsB,IAAI,CAAA;IACnC,IAAI,CAAC;QACH,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IACnC,CAAC;IACD,IAAI,CAAC;QACH,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,IAAI,GAAG,KAAK,CAAA;IAChB,IAAI,IAAI,GAAG,KAAK,CAAA;IAEhB,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,IAAI,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;YACjE,kEAAkE;YAClE,IAAI,GAAG,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC5C,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,IAAI,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC3C,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,IAAI,IAAI,EAAE,OAAO,EAAE,CAAA;AACzC,CAAC;AAED,gFAAgF;AAEhF,4EAA4E;AAC5E,6EAA6E;AAC7E,uEAAuE;AACvE,gCAAgC;AAChC,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,313 @@
1
+ /**
2
+ * @synoi/sraid — types.ts
3
+ *
4
+ * Type definitions for the SRAID (Self-Routing Addressable Identity Data) protocol — L0 of the
5
+ * SRAID Stack. Mirrors the shapes used by synoi-gateway and @synoi/vault so
6
+ * external implementations can interoperate without depending on the
7
+ * internal packages.
8
+ *
9
+ * CDRO objects are content-addressed: the OID is derived from the canonical
10
+ * form of the object (minus signature fields), so any byte-level change to
11
+ * the canonical content yields a different OID. Signatures are computed
12
+ * over the canonical bytes and attached after — they are NOT in the hash
13
+ * input, so signature rotation does not change the OID.
14
+ */
15
+ /**
16
+ * The six GAP decision verbs. Authority records carry the full verb set;
17
+ * they are NOT folded to allow/deny/defer before persistence (SRAID
18
+ * Foundation Punch List item A4). When an authority block describes a
19
+ * decision (e.g. a Decision Receipt), `decision` is one of these.
20
+ *
21
+ * allow — the action was permitted outright
22
+ * deny — the action was refused
23
+ * defer — the decision was postponed (queued / pending)
24
+ * step_up — additional authentication / HITL was required
25
+ * delegate — authority was passed to another actor
26
+ * revoke — a prior grant/decision was withdrawn
27
+ *
28
+ * The clean-sheet model (OBJECT_MODEL_CLEANSHEET §3.5) shows the core four
29
+ * (allow|deny|defer|step_up); delegate/revoke complete the AARM verb set
30
+ * so the enum does not have to widen later.
31
+ */
32
+ export type AuthorityDecision = 'allow' | 'deny' | 'defer' | 'step_up' | 'delegate' | 'revoke';
33
+ /**
34
+ * L4 GOVERNANCE — the authority block (the "authorized axis").
35
+ *
36
+ * This is the structural realization of the authorized axis
37
+ * (OBJECT_MODEL_CLEANSHEET §3.5, SRAID_FOUNDATION_PUNCHLIST A1): a state
38
+ * change or event is *normal* iff a governing authority record explains
39
+ * it. Every CDRO MAY carry an `authority` block referencing the GAP grant,
40
+ * the decision verb, and the session intent anchor that authorized it.
41
+ *
42
+ * IMPORTANT — identity-bound. The authority block lives physically INSIDE
43
+ * the hashed content core (it is one of the L4 fields hashed into the OID),
44
+ * so it cannot be silently stripped or swapped without changing the OID and
45
+ * therefore breaking the signature. Use `cdroOid` / `cdroContentCore` in
46
+ * `oid.ts` to compute identity over the content core (which includes
47
+ * `authority`), never `oidOf(body)` alone for a full CDRO.
48
+ *
49
+ * `decision` is `null`-able by design: a `state:change_event` carries
50
+ * `authority` with a null/absent decision until a correlation pass binds it
51
+ * to an authorizing receipt — a null authorized axis IS the orphan test
52
+ * (OBJECT_MODEL_CLEANSHEET R2.4). An absent `authority` field means the
53
+ * object asserts no authority; a present block with `grant_oid` asserts one.
54
+ */
55
+ export interface AuthorityBlock {
56
+ /**
57
+ * OID of the GAP capability grant (or decision/intent record) that
58
+ * permitted this object to exist. `sha256:<hex>` form. Optional only for
59
+ * an as-yet-uncorrelated state-change event; for any object that claims
60
+ * to be authorized, this MUST be present.
61
+ */
62
+ grant_oid?: string;
63
+ /**
64
+ * The decision verb, when this object IS (or records) a decision. One of
65
+ * the six GAP verbs. May be null/absent for objects that merely reference
66
+ * an authorizing grant without themselves being a decision, or for an
67
+ * uncorrelated state-change event.
68
+ */
69
+ decision?: AuthorityDecision | null;
70
+ /**
71
+ * OID of the session / task intent anchor under which the authority was
72
+ * exercised. `sha256:<hex>` form. Optional.
73
+ */
74
+ intent_oid?: string;
75
+ }
76
+ /**
77
+ * Typed lineage edge relations (OBJECT_MODEL_CLEANSHEET §3.3,
78
+ * SRAID_FOUNDATION_PUNCHLIST A2). A `links[]` edge names *why* one object
79
+ * points at another. The taxonomy is the union the four products need; it
80
+ * is OPEN (a verifier ignores rels it does not understand) but these are the
81
+ * named, reserved relations.
82
+ *
83
+ * supersedes — this object replaces the target (the unified, witnessed
84
+ * form of the legacy self-asserted `supersedes` string and
85
+ * the standalone SRO). Combined with `prev`, gives a
86
+ * verifier a latest-wins / monotone rule instead of an
87
+ * unwitnessed pointer (fixes SRAID F10 / Adversary A3).
88
+ * derived_from — this object was derived/transformed from the target.
89
+ * snapshot_of — this object is a checkpoint snapshot of the target chain.
90
+ * consolidated_from — Saga: a consolidated memory record built from raw chunks.
91
+ * predecessor — generic prior-version edge (when not a full supersession).
92
+ * encounter_of — Vitni: an encounter/disclosure references a prior one.
93
+ * subject_digest — Hlif: the content digest of the attested artifact.
94
+ * invocation_of — Althing: the GAP capability invocation this records.
95
+ * hitl_evidence — Althing: a HITL channel event backing a decision.
96
+ * entity_of — state-drift: the entity state-spine head this observes.
97
+ * prev_observation — state-drift: the prior observation of the same entity.
98
+ *
99
+ * Unknown rels are permitted (forward-compatible); validation only checks
100
+ * that each edge is well-formed (a non-empty `rel` + a `sha256:` `oid`).
101
+ */
102
+ export type LinkRel = 'supersedes' | 'derived_from' | 'snapshot_of' | 'consolidated_from' | 'predecessor' | 'encounter_of' | 'subject_digest' | 'invocation_of' | 'hitl_evidence' | 'entity_of' | 'prev_observation' | (string & {});
103
+ /**
104
+ * L3 LINEAGE — one typed Merkle-DAG edge.
105
+ *
106
+ * Both `prev` and every `links[]` edge are HASHED INTO THE OID (they live in
107
+ * the content core, see `cdroContentCore` in oid.ts), so lineage is
108
+ * identity-bound and tamper-evident: a node's OID transitively commits its
109
+ * entire reachable history (the Git/IPFS "head hash proves all history"
110
+ * property, OBJECT_MODEL_CLEANSHEET §3.3). An edge cannot be added, removed,
111
+ * or re-pointed without changing the OID and invalidating the signature.
112
+ */
113
+ export interface LineageLink {
114
+ /** Why this edge exists. One of the reserved `LinkRel`s, or any string. */
115
+ rel: LinkRel;
116
+ /** OID of the target object. `sha256:<hex>` form. */
117
+ oid: string;
118
+ }
119
+ export type { SensitivityTier } from './sensitivity.js';
120
+ import type { SensitivityTier } from './sensitivity.js';
121
+ /**
122
+ * Hybrid signature envelope — LEGACY. Carries an Ed25519 signature
123
+ * (classical) and an ML-DSA-65 signature (post-quantum), both computed over
124
+ * the bare canonical bytes with NO payload-type binding. `verifySignature`
125
+ * in this package requires BOTH to be valid before returning `valid: true`.
126
+ *
127
+ * DEPRECATED in favour of the DSSE `AttestationEnvelope` (the L2 attestation
128
+ * layer). The bare-bytes form has no `payloadType` binding, which allows a
129
+ * signature minted for one object type to be replayed against a different
130
+ * type whose canonical bytes match (SRAID F7 / Adversary A4). New objects
131
+ * SHOULD carry an `attestation` (DSSE) envelope; `SignatureEnvelope` is
132
+ * retained only so existing callers and stored objects keep verifying during
133
+ * the migration.
134
+ *
135
+ * Encoded as base64 (standard, with `=` padding). `signer_kid` is a
136
+ * stable string that identifies which keypair produced the signatures.
137
+ */
138
+ export interface SignatureEnvelope {
139
+ /** Base64-encoded 64-byte Ed25519 signature. */
140
+ ed25519: string;
141
+ /** Base64-encoded ML-DSA-65 signature. */
142
+ ml_dsa_65: string;
143
+ /** Key ID — opaque string identifying which keypair signed. */
144
+ signer_kid: string;
145
+ }
146
+ /**
147
+ * One signature entry inside a DSSE `AttestationEnvelope`. The signature is
148
+ * computed over the envelope's PAE (Pre-Authentication Encoding) — see
149
+ * `pae()` / `verifyAttestation()` in attestation.ts — so the `payloadType`
150
+ * is structurally bound into what each signature covers.
151
+ */
152
+ export interface AttestationSignature {
153
+ /**
154
+ * Algorithm identifier. SynOI requires both `'ed25519'` and `'ml-dsa-65'`
155
+ * to be present (the hybrid AND policy). Other algs are ignored by the
156
+ * SynOI verifier but permitted in the array (DSSE is forward-compatible).
157
+ */
158
+ alg: 'ed25519' | 'ml-dsa-65' | (string & {});
159
+ /** Base64-encoded signature bytes over the PAE. */
160
+ sig: string;
161
+ /** Optional key ID — opaque string identifying which keypair signed. */
162
+ keyid?: string;
163
+ }
164
+ /**
165
+ * L2 ATTESTATION — a DSSE (Dead Simple Signing Envelope), JSON profile.
166
+ *
167
+ * Replaces the legacy `SignatureEnvelope`. Each signature in `signatures[]`
168
+ * covers `PAE(payloadType, payload)` rather than the bare payload bytes, so
169
+ * the payload TYPE is bound into the signed bytes — closing the cross-type
170
+ * confusion gap (SRAID F7 / Adversary A4). The hybrid both-required rule is
171
+ * preserved: a conformant SRAID attestation MUST carry both an `ed25519` and
172
+ * an `ml-dsa-65` entry over the same PAE, and `verifyAttestation` requires
173
+ * both to verify.
174
+ *
175
+ * `payload` is the canonical UTF-8 string of the content core (the same
176
+ * bytes `canonicalize()` produces and `oidOf` hashes). Because the envelope
177
+ * is detached (it is the CDRO's `attestation` field, excluded from the OID
178
+ * hash), adding/rotating a signature never changes the OID.
179
+ *
180
+ * A future CBOR profile would use COSE (RFC 9052); it is reserved, not
181
+ * implemented in this package.
182
+ */
183
+ export interface AttestationEnvelope {
184
+ /**
185
+ * The payload media type, bound into the PAE. SynOI objects use
186
+ * `application/vnd.synoi.sraid+json`; Hlif supply-chain attestations use
187
+ * `application/vnd.in-toto+json` for in-toto/SLSA/Sigstore interop.
188
+ */
189
+ payloadType: string;
190
+ /** Canonical UTF-8 payload string (the signed content core). */
191
+ payload: string;
192
+ /** Detached signatures, each over `PAE(payloadType, payload)`. */
193
+ signatures: AttestationSignature[];
194
+ }
195
+ /**
196
+ * CDRO — Canonical Data Record Object.
197
+ *
198
+ * The base shape every signed CDRO object takes. The `oid` field is
199
+ * `sha256:` + hex(sha256(canonicalize(body))) where the body is the CDRO
200
+ * minus the `oid` and `signature` fields.
201
+ *
202
+ * Mirrors `GapCdroEnvelope` in synoi-gateway so a GAP object IS a CDRO.
203
+ * Higher-layer packages narrow `body` with their own type.
204
+ */
205
+ export interface CDRO<TBody = unknown> {
206
+ /** "sha256:" + hex(sha256(canonicalize(cdro_minus_oid_and_signature))). */
207
+ oid: string;
208
+ /** Object type discriminator (e.g. "gap:capability_grant"). */
209
+ type: string;
210
+ /** SRAID protocol version. v2 is the only defined version today. */
211
+ sraid_version: '2.0';
212
+ /** Tenant that owns this object. */
213
+ tenant_id: string;
214
+ /** Unix ms timestamp of creation. */
215
+ created_at_ms: number;
216
+ /** OID of the actor (skill, user, device, …) that created the object. */
217
+ created_by: string;
218
+ /** Body — type-specific payload. Higher layers narrow this. */
219
+ body: TBody;
220
+ /**
221
+ * Optional L4 authority block — the authorized axis (§3.5). When present
222
+ * it is HASHED INTO THE OID (it is part of the content core), so it cannot
223
+ * be stripped without changing identity. See `AuthorityBlock` and the
224
+ * `cdroOid` helper in oid.ts.
225
+ */
226
+ authority?: AuthorityBlock;
227
+ /**
228
+ * Optional L4 propagating sensitivity tier — a COARSE, OPAQUE level
229
+ * (`s0`..`s4`, lowest-to-highest), NOT a literal content category (§3.4,
230
+ * SRAID_FOUNDATION_PUNCHLIST A5). It is OPAQUE on purpose: SPEC §7 forbids
231
+ * leaking the nature of an encrypted `body` via the public, signed
232
+ * envelope, so a literal label like `"phi"`/`"health"` is NOT allowed here;
233
+ * the regulatory-category → tier mapping is private higher-layer policy.
234
+ *
235
+ * HASHED INTO THE OID (it is a content-core field, see `cdroContentCore` in
236
+ * oid.ts), so the tier cannot be silently stripped or downgraded without
237
+ * changing identity and invalidating the signature. Carry-forward is
238
+ * monotone (`max`): a consolidated/summarized object inherits the HIGHEST
239
+ * tier among its sources — see `sensitivityCarryForward` in sensitivity.ts
240
+ * and the Vault consolidation path. Absent means "unclassified" (the floor,
241
+ * `s0`); it does not assert low sensitivity, only that none was declared.
242
+ */
243
+ sensitivity?: SensitivityTier;
244
+ /**
245
+ * Optional L3 lineage — the Merkle edge to the immediately superseded
246
+ * version (null/absent at a root object). HASHED INTO THE OID (it is part
247
+ * of the content core), so the predecessor link is identity-bound: a node's
248
+ * OID transitively commits its predecessor's OID and therefore its whole
249
+ * reachable history. This is the unified, witnessed replacement for the
250
+ * legacy self-asserted `supersedes` string — see `lineageLinks` /
251
+ * `latestWins` in lineage.ts for the latest-wins / monotone rule.
252
+ */
253
+ prev?: string;
254
+ /**
255
+ * Optional L3 lineage — typed Merkle-DAG edges (§3.3). HASHED INTO THE OID
256
+ * (content core), so every edge is identity-bound and tamper-evident. The
257
+ * standalone SRO and the self-asserted `supersedes` pointer both become
258
+ * expressible here as `{ rel: 'supersedes', oid }` edges, unifying the
259
+ * three legacy supersession mechanisms onto one model.
260
+ */
261
+ links?: LineageLink[];
262
+ /**
263
+ * Legacy supersession pointer — OID of the previous version. RETAINED for
264
+ * back-compat. It is now routed through the unified lineage model: treat it
265
+ * as equivalent to `prev` (and to a `{ rel: 'supersedes' }` link). New
266
+ * objects SHOULD set `prev`/`links` instead; `lineageLinks` in lineage.ts
267
+ * coalesces all three so a verifier sees one set of typed edges. Still
268
+ * hashed into the OID (it is a content-core field).
269
+ */
270
+ supersedes?: string;
271
+ /**
272
+ * Optional L2 attestation — the DSSE envelope (the preferred signing path).
273
+ * Carries `payloadType` + `signatures[]`, each over `PAE(payloadType,
274
+ * payload)`. Detached: NOT part of the OID hash (see `cdroContentCore` in
275
+ * oid.ts), so adding/rotating a signature never changes identity.
276
+ */
277
+ attestation?: AttestationEnvelope;
278
+ /**
279
+ * Optional LEGACY signature envelope (bare-bytes, no payload-type binding).
280
+ * Retained for back-compat with objects/callers minted before the DSSE
281
+ * `attestation` envelope. New objects SHOULD use `attestation`. May be
282
+ * absent on draft / unsigned objects.
283
+ */
284
+ signature?: SignatureEnvelope;
285
+ }
286
+ /**
287
+ * SRO — Mutation / Supersession Record.
288
+ *
289
+ * Links a successor CDRO to its predecessor and the actor that authorized
290
+ * the supersession. SROs are themselves CDRO objects (so they're CDROs with
291
+ * an `oid` and `signature`), but they have a specific body shape.
292
+ *
293
+ * Where CDROs are the "what" of the system, SROs are the "what changed."
294
+ * They form an append-only chain: every supersedes pointer in a CDRO is
295
+ * accompanied by an SRO that explains and witnesses the change.
296
+ */
297
+ export interface SROBody {
298
+ /** OID of the predecessor object being superseded. */
299
+ predecessor_oid: string;
300
+ /** OID of the successor object that supersedes it. */
301
+ successor_oid: string;
302
+ /** Why the predecessor was superseded. Free-form short string. */
303
+ reason: string;
304
+ /** OID of the actor that authorized this mutation. */
305
+ authorized_by: string;
306
+ /** Optional list of supporting evidence OIDs (audit trail). */
307
+ evidence_oids?: string[];
308
+ }
309
+ /** SRO is just a CDRO with a fixed body type. */
310
+ export type SRO = CDRO<SROBody> & {
311
+ type: 'sraid:sro';
312
+ };
313
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @synoi/sraid — types.ts
3
+ *
4
+ * Type definitions for the SRAID (Self-Routing Addressable Identity Data) protocol — L0 of the
5
+ * SRAID Stack. Mirrors the shapes used by synoi-gateway and @synoi/vault so
6
+ * external implementations can interoperate without depending on the
7
+ * internal packages.
8
+ *
9
+ * CDRO objects are content-addressed: the OID is derived from the canonical
10
+ * form of the object (minus signature fields), so any byte-level change to
11
+ * the canonical content yields a different OID. Signatures are computed
12
+ * over the canonical bytes and attached after — they are NOT in the hash
13
+ * input, so signature rotation does not change the OID.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}