@mikeargento/bitgraph 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +9 -0
  2. package/NOTICE +14 -0
  3. package/README.md +175 -0
  4. package/dist/__tests__/canonical.test.d.ts +2 -0
  5. package/dist/__tests__/canonical.test.d.ts.map +1 -0
  6. package/dist/__tests__/canonical.test.js +162 -0
  7. package/dist/__tests__/canonical.test.js.map +1 -0
  8. package/dist/__tests__/commit-service.integration.test.d.ts +2 -0
  9. package/dist/__tests__/commit-service.integration.test.d.ts.map +1 -0
  10. package/dist/__tests__/commit-service.integration.test.js +95 -0
  11. package/dist/__tests__/commit-service.integration.test.js.map +1 -0
  12. package/dist/__tests__/constructor.test.d.ts +2 -0
  13. package/dist/__tests__/constructor.test.d.ts.map +1 -0
  14. package/dist/__tests__/constructor.test.js +267 -0
  15. package/dist/__tests__/constructor.test.js.map +1 -0
  16. package/dist/__tests__/hello-world.test.d.ts +2 -0
  17. package/dist/__tests__/hello-world.test.d.ts.map +1 -0
  18. package/dist/__tests__/hello-world.test.js +9 -0
  19. package/dist/__tests__/hello-world.test.js.map +1 -0
  20. package/dist/__tests__/policy-enforcement.test.d.ts +2 -0
  21. package/dist/__tests__/policy-enforcement.test.d.ts.map +1 -0
  22. package/dist/__tests__/policy-enforcement.test.js +188 -0
  23. package/dist/__tests__/policy-enforcement.test.js.map +1 -0
  24. package/dist/__tests__/proof-hash-regression.test.d.ts +2 -0
  25. package/dist/__tests__/proof-hash-regression.test.d.ts.map +1 -0
  26. package/dist/__tests__/proof-hash-regression.test.js +134 -0
  27. package/dist/__tests__/proof-hash-regression.test.js.map +1 -0
  28. package/dist/__tests__/proof-hash.test.d.ts +2 -0
  29. package/dist/__tests__/proof-hash.test.d.ts.map +1 -0
  30. package/dist/__tests__/proof-hash.test.js +134 -0
  31. package/dist/__tests__/proof-hash.test.js.map +1 -0
  32. package/dist/__tests__/verifier.test.d.ts +2 -0
  33. package/dist/__tests__/verifier.test.d.ts.map +1 -0
  34. package/dist/__tests__/verifier.test.js +457 -0
  35. package/dist/__tests__/verifier.test.js.map +1 -0
  36. package/dist/canonical.d.ts +54 -0
  37. package/dist/canonical.d.ts.map +1 -0
  38. package/dist/canonical.js +119 -0
  39. package/dist/canonical.js.map +1 -0
  40. package/dist/constructor.d.ts +66 -0
  41. package/dist/constructor.d.ts.map +1 -0
  42. package/dist/constructor.js +339 -0
  43. package/dist/constructor.js.map +1 -0
  44. package/dist/host.d.ts +138 -0
  45. package/dist/host.d.ts.map +1 -0
  46. package/dist/host.js +3 -0
  47. package/dist/host.js.map +1 -0
  48. package/dist/index.d.ts +20 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +9 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/policy.d.ts +68 -0
  53. package/dist/policy.d.ts.map +1 -0
  54. package/dist/policy.js +176 -0
  55. package/dist/policy.js.map +1 -0
  56. package/dist/proof-hash.d.ts +9 -0
  57. package/dist/proof-hash.d.ts.map +1 -0
  58. package/dist/proof-hash.js +75 -0
  59. package/dist/proof-hash.js.map +1 -0
  60. package/dist/types.d.ts +705 -0
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/types.js +3 -0
  63. package/dist/types.js.map +1 -0
  64. package/dist/verifier.d.ts +27 -0
  65. package/dist/verifier.d.ts.map +1 -0
  66. package/dist/verifier.js +844 -0
  67. package/dist/verifier.js.map +1 -0
  68. package/package.json +40 -0
  69. package/src/__tests__/canonical.test.ts +253 -0
  70. package/src/__tests__/commit-service.integration.test.ts +117 -0
  71. package/src/__tests__/constructor.test.ts +340 -0
  72. package/src/__tests__/hello-world.test.ts +10 -0
  73. package/src/__tests__/policy-enforcement.test.ts +226 -0
  74. package/src/__tests__/proof-hash-regression.test.ts +147 -0
  75. package/src/__tests__/proof-hash.test.ts +148 -0
  76. package/src/__tests__/verifier.test.ts +541 -0
  77. package/src/constructor.ts +435 -0
  78. package/src/host.ts +153 -0
  79. package/src/index.ts +51 -0
  80. package/src/policy.ts +239 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,6CAA6C;QAC7C,oDAAoD;QACpD,IAAI,OAAO,KAAK,KAAK,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,SAAS,CACjB,kFAAkF,CACnF,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,UAAU,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC7D,MAAM,IAAI,SAAS,CACjB,4BAA4B,OAAO,KAAK,gDAAgD,CACzF,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,SAAS,CACjB,iFAAiF;gBAC/E,mDAAmD,CACtD,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,yCAAyC;QACzC,OAAO,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnC,CAAC;IAED,6DAA6D;IAC7D,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACvE,MAAM,KAAK,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAC;QACtD,gEAAgE;QAChE,kEAAkE;QAClE,IAAI,OAAO,KAAK,KAAK,WAAW,EAAE,CAAC;YACjC,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,CAAa,EAAE,CAAa;IAC5D,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,kEAAkE;QAClE,IAAI,IAAK,CAAC,CAAC,CAAC,CAAY,GAAI,CAAC,CAAC,CAAC,CAAY,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { HostCapabilities } from "./host.js";
2
+ import type { BitGraphPolicy, BitGraphProof, AgencyEnvelope, Attribution, PolicyBinding } from "@mikeargento/bitgraph-verify";
3
+ export declare class Constructor {
4
+ #private;
5
+ private constructor();
6
+ /**
7
+ * Initialize a Constructor bound to a host adapter.
8
+ *
9
+ * Performs a preflight check to confirm the host can produce a measurement
10
+ * and a public key. If either fails the returned promise rejects and no
11
+ * Constructor is created.
12
+ *
13
+ * @param opts.host - Host capabilities implementation (TEE adapter)
14
+ * @param opts.policy - Optional policy constraints
15
+ * @param opts.epochId - Optional epoch identifier (generated at enclave boot).
16
+ * When provided, included in every proof's commit.epochId field
17
+ * (signed, tamper-evident). Verifiers use epochId to detect
18
+ * enclave lifecycle boundaries.
19
+ */
20
+ static initialize(opts: {
21
+ host: HostCapabilities;
22
+ policy?: BitGraphPolicy;
23
+ epochId?: string;
24
+ }): Promise<Constructor>;
25
+ /**
26
+ * Produce a tamper-evident, signed commit proof for a pre-computed digest.
27
+ *
28
+ * Same atomic guarantees as `commit()`, but accepts a Base64-encoded
29
+ * SHA-256 digest instead of raw bytes. This enables digest-only mode
30
+ * where the raw data never leaves the caller (e.g. an iPhone sending
31
+ * only the SHA-256 of a photo to the enclave).
32
+ *
33
+ * @param input.digestB64 - Base64-standard SHA-256 digest of the data
34
+ * @param input.metadata - Advisory metadata (NOT signed)
35
+ * @param input.prevProofHashB64 - Optional base64 hash of a prior proof for chaining
36
+ * @param input.agency - Optional agency envelope (actor + authorization)
37
+ */
38
+ commitDigest(input: {
39
+ digestB64: string;
40
+ metadata?: Record<string, unknown>;
41
+ prevProofHashB64?: string;
42
+ agency?: AgencyEnvelope;
43
+ attribution?: Attribution;
44
+ policy?: PolicyBinding;
45
+ }): Promise<BitGraphProof>;
46
+ /**
47
+ * Produce a tamper-evident, signed commit proof for `input.bytes`.
48
+ *
49
+ * The call is atomic: it either returns a complete BitGraphProof or throws.
50
+ * No partial proof is ever returned.
51
+ *
52
+ * @param input.bytes - The raw bytes to commit
53
+ * @param input.metadata - Advisory metadata (NOT signed)
54
+ * @param input.prevProofHashB64 - Optional base64 hash of a prior proof for chaining
55
+ * @param input.agency - Optional agency envelope (actor + authorization)
56
+ */
57
+ commit(input: {
58
+ bytes: Uint8Array;
59
+ metadata?: Record<string, unknown>;
60
+ prevProofHashB64?: string;
61
+ agency?: AgencyEnvelope;
62
+ attribution?: Attribution;
63
+ policy?: PolicyBinding;
64
+ }): Promise<BitGraphProof>;
65
+ }
66
+ //# sourceMappingURL=constructor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constructor.d.ts","sourceRoot":"","sources":["../src/constructor.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAc,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAM1I,qBAAa,WAAW;;IAKtB,OAAO;IAUP;;;;;;;;;;;;;OAaG;WACU,UAAU,CAAC,IAAI,EAAE;QAC5B,IAAI,EAAE,gBAAgB,CAAC;QACvB,MAAM,CAAC,EAAE,cAAc,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,WAAW,CAAC;IAkCxB;;;;;;;;;;;;OAYG;IACG,YAAY,CAAC,KAAK,EAAE;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,MAAM,CAAC,EAAE,cAAc,CAAC;QACxB,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GAAG,OAAO,CAAC,aAAa,CAAC;IAe1B;;;;;;;;;;OAUG;IACG,MAAM,CAAC,KAAK,EAAE;QAClB,KAAK,EAAE,UAAU,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,MAAM,CAAC,EAAE,cAAc,CAAC;QACxB,WAAW,CAAC,EAAE,WAAW,CAAC;QAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GAAG,OAAO,CAAC,aAAa,CAAC;CAwN3B"}
@@ -0,0 +1,339 @@
1
+ // Copyright (c) Mike Argento. All rights reserved. See LICENSE.
2
+ /**
3
+ * bitgraph-core Constructor
4
+ *
5
+ * The Constructor is the sole write path in bitgraph-core. It enforces a strict
6
+ * atomic commit invariant:
7
+ *
8
+ * authorize → bind → sign → (authorization consumed)
9
+ *
10
+ * No partial outputs are produced. If any step fails the entire commit
11
+ * is aborted and an error is thrown without returning any proof fragment.
12
+ *
13
+ * Commit steps (in order):
14
+ * 1. Obtain monotonic counter (if host supports it)
15
+ * 2. Obtain fresh boundary nonce from host
16
+ * 3. Obtain secure time (if host supports it)
17
+ * 4. Compute SHA-256 of input bytes
18
+ * 5. Retrieve enclave measurement and public key
19
+ * 6. Build canonical signed body (includes enforcement + measurement +
20
+ * attestationFormat when present)
21
+ * 7. Canonicalize signed body to UTF-8 bytes
22
+ * 8. Sign canonical bytes via host
23
+ * 9. Optionally obtain attestation report bound to this commit
24
+ * 10. Assemble and return the complete BitGraphProof
25
+ *
26
+ * Steps 1-9 are performed inside a single async critical section; any
27
+ * rejection causes the function to throw with no returned value.
28
+ */
29
+ import { sha256 } from "@noble/hashes/sha256";
30
+ import { canonicalize } from "@mikeargento/bitgraph-verify";
31
+ // ---------------------------------------------------------------------------
32
+ // Constructor class
33
+ // ---------------------------------------------------------------------------
34
+ export class Constructor {
35
+ #host;
36
+ #policy;
37
+ #epochId;
38
+ constructor(host, policy, epochId) {
39
+ this.#host = host;
40
+ this.#policy = policy;
41
+ this.#epochId = epochId;
42
+ }
43
+ /**
44
+ * Initialize a Constructor bound to a host adapter.
45
+ *
46
+ * Performs a preflight check to confirm the host can produce a measurement
47
+ * and a public key. If either fails the returned promise rejects and no
48
+ * Constructor is created.
49
+ *
50
+ * @param opts.host - Host capabilities implementation (TEE adapter)
51
+ * @param opts.policy - Optional policy constraints
52
+ * @param opts.epochId - Optional epoch identifier (generated at enclave boot).
53
+ * When provided, included in every proof's commit.epochId field
54
+ * (signed, tamper-evident). Verifiers use epochId to detect
55
+ * enclave lifecycle boundaries.
56
+ */
57
+ static async initialize(opts) {
58
+ const { host, policy = {}, epochId } = opts;
59
+ const resolvedPolicy = {
60
+ requireCounter: policy.requireCounter ?? false,
61
+ requireTime: policy.requireTime ?? false,
62
+ };
63
+ // Preflight: confirm the host can serve a measurement and a public key.
64
+ await Promise.all([host.getMeasurement(), host.getPublicKey()]).catch((cause) => {
65
+ throw new Error("bitgraph-core: host preflight failed — getMeasurement() or getPublicKey() rejected", { cause });
66
+ });
67
+ // Policy validation: if counter is required, confirm the host has it.
68
+ if (resolvedPolicy.requireCounter && typeof host.nextCounter !== "function") {
69
+ throw new Error("bitgraph-core: policy requires a monotonic counter but host does not implement nextCounter()");
70
+ }
71
+ if (resolvedPolicy.requireTime && typeof host.secureTime !== "function") {
72
+ throw new Error("bitgraph-core: policy requires secure time but host does not implement secureTime()");
73
+ }
74
+ return new Constructor(host, resolvedPolicy, epochId);
75
+ }
76
+ /**
77
+ * Produce a tamper-evident, signed commit proof for a pre-computed digest.
78
+ *
79
+ * Same atomic guarantees as `commit()`, but accepts a Base64-encoded
80
+ * SHA-256 digest instead of raw bytes. This enables digest-only mode
81
+ * where the raw data never leaves the caller (e.g. an iPhone sending
82
+ * only the SHA-256 of a photo to the enclave).
83
+ *
84
+ * @param input.digestB64 - Base64-standard SHA-256 digest of the data
85
+ * @param input.metadata - Advisory metadata (NOT signed)
86
+ * @param input.prevProofHashB64 - Optional base64 hash of a prior proof for chaining
87
+ * @param input.agency - Optional agency envelope (actor + authorization)
88
+ */
89
+ async commitDigest(input) {
90
+ const { digestB64, metadata, prevProofHashB64 } = input;
91
+ // Validate the provided digest
92
+ const digestBytes = fromBase64Digest(digestB64);
93
+ if (digestBytes.length !== 32) {
94
+ throw new RangeError(`bitgraph-core: digestB64 decodes to ${digestBytes.length} bytes; expected 32 (SHA-256)`);
95
+ }
96
+ // Delegate to the internal commit flow, skipping step 4 (hashing)
97
+ return this.#commitInternal({ digestB64, metadata, prevProofHashB64, agency: input.agency, attribution: input.attribution, policy: input.policy });
98
+ }
99
+ /**
100
+ * Produce a tamper-evident, signed commit proof for `input.bytes`.
101
+ *
102
+ * The call is atomic: it either returns a complete BitGraphProof or throws.
103
+ * No partial proof is ever returned.
104
+ *
105
+ * @param input.bytes - The raw bytes to commit
106
+ * @param input.metadata - Advisory metadata (NOT signed)
107
+ * @param input.prevProofHashB64 - Optional base64 hash of a prior proof for chaining
108
+ * @param input.agency - Optional agency envelope (actor + authorization)
109
+ */
110
+ async commit(input) {
111
+ const { bytes, metadata, prevProofHashB64 } = input;
112
+ // Step 4: SHA-256 digest of input bytes
113
+ const digest = sha256(bytes);
114
+ const digestB64 = toBase64(digest);
115
+ // Delegate to shared internal flow (steps 1-3, 5-10)
116
+ return this.#commitInternal({ digestB64, metadata, prevProofHashB64, agency: input.agency, attribution: input.attribution, policy: input.policy });
117
+ }
118
+ // ------------------------------------------------------------------
119
+ // Internal shared commit flow (steps 1-3, 5-10)
120
+ // ------------------------------------------------------------------
121
+ async #commitInternal(input) {
122
+ const { digestB64, metadata, prevProofHashB64, agency, attribution, policy } = input;
123
+ // ------------------------------------------------------------------
124
+ // Step 1: Monotonic counter (optional, policy-gated)
125
+ // ------------------------------------------------------------------
126
+ let counter;
127
+ if (typeof this.#host.nextCounter === "function") {
128
+ counter = await this.#host.nextCounter().catch((cause) => {
129
+ throw new Error("bitgraph-core: host.nextCounter() rejected", { cause });
130
+ });
131
+ assertNonEmptyString(counter, "counter");
132
+ }
133
+ // ------------------------------------------------------------------
134
+ // Step 2: Fresh boundary nonce
135
+ // ------------------------------------------------------------------
136
+ const nonceBytes = await this.#host.getFreshNonce().catch((cause) => {
137
+ throw new Error("bitgraph-core: host.getFreshNonce() rejected", { cause });
138
+ });
139
+ assertUint8Array(nonceBytes, "nonce", 16); // minimum 128-bit entropy
140
+ // ------------------------------------------------------------------
141
+ // Step 3: Secure time (optional, policy-gated)
142
+ // ------------------------------------------------------------------
143
+ let time;
144
+ if (typeof this.#host.secureTime === "function") {
145
+ time = await this.#host.secureTime().catch((cause) => {
146
+ throw new Error("bitgraph-core: host.secureTime() rejected", { cause });
147
+ });
148
+ if (typeof time !== "number" || !Number.isFinite(time) || time < 0) {
149
+ throw new TypeError("bitgraph-core: host.secureTime() returned an invalid value; expected a non-negative finite number");
150
+ }
151
+ }
152
+ // ------------------------------------------------------------------
153
+ // Step 5: Enclave identity (measurement + public key)
154
+ // ------------------------------------------------------------------
155
+ const [measurement, publicKeyBytes] = await Promise.all([
156
+ this.#host.getMeasurement().catch((cause) => {
157
+ throw new Error("bitgraph-core: host.getMeasurement() rejected", { cause });
158
+ }),
159
+ this.#host.getPublicKey().catch((cause) => {
160
+ throw new Error("bitgraph-core: host.getPublicKey() rejected", { cause });
161
+ }),
162
+ ]);
163
+ assertNonEmptyString(measurement, "measurement");
164
+ assertUint8Array(publicKeyBytes, "publicKey", 32); // Ed25519 public key
165
+ // ------------------------------------------------------------------
166
+ // Step 6: Build canonical signed body
167
+ // ------------------------------------------------------------------
168
+ const commitFields = {
169
+ nonceB64: toBase64(nonceBytes),
170
+ };
171
+ if (counter !== undefined)
172
+ commitFields.counter = counter;
173
+ if (time !== undefined)
174
+ commitFields.time = time;
175
+ if (prevProofHashB64 !== undefined)
176
+ commitFields.prevB64 = prevProofHashB64;
177
+ if (this.#epochId !== undefined)
178
+ commitFields.epochId = this.#epochId;
179
+ const signedBody = {
180
+ version: "bitgraph/1",
181
+ artifact: {
182
+ hashAlg: "sha256",
183
+ digestB64,
184
+ },
185
+ commit: commitFields,
186
+ publicKeyB64: toBase64(publicKeyBytes),
187
+ enforcement: this.#host.enforcementTier,
188
+ measurement,
189
+ };
190
+ // Include actor identity in signed body when agency is present
191
+ if (agency !== undefined) {
192
+ signedBody.actor = agency.actor;
193
+ }
194
+ // Include policy binding in signed body when present (cryptographically sealed)
195
+ if (policy !== undefined) {
196
+ signedBody.policy = policy;
197
+ }
198
+ // Include attribution in signed body when present (cryptographically sealed)
199
+ if (attribution !== undefined) {
200
+ signedBody.attribution = attribution;
201
+ }
202
+ // ------------------------------------------------------------------
203
+ // Step 7: Canonicalize
204
+ // ------------------------------------------------------------------
205
+ const canonicalBytes = canonicalize(signedBody);
206
+ // ------------------------------------------------------------------
207
+ // Step 8: Sign
208
+ // ------------------------------------------------------------------
209
+ const signatureBytes = await this.#host.sign(canonicalBytes).catch((cause) => {
210
+ throw new Error("bitgraph-core: host.sign() rejected", { cause });
211
+ });
212
+ assertUint8Array(signatureBytes, "signature", 64); // Ed25519 signature
213
+ // ------------------------------------------------------------------
214
+ // Step 9: Optional attestation report bound to this commit
215
+ // ------------------------------------------------------------------
216
+ let attestation;
217
+ if (typeof this.#host.getAttestation === "function") {
218
+ // Bind the attestation to the canonical body hash so that a verifier
219
+ // can confirm the report covers this specific commit.
220
+ const bodyHash = sha256(canonicalBytes);
221
+ const result = await this.#host.getAttestation(bodyHash).catch((cause) => {
222
+ throw new Error("bitgraph-core: host.getAttestation() rejected", { cause });
223
+ });
224
+ if (typeof result !== "object" ||
225
+ result === null ||
226
+ typeof result.format !== "string" ||
227
+ result.format.length === 0 ||
228
+ !(result.report instanceof Uint8Array) ||
229
+ result.report.length === 0) {
230
+ throw new TypeError("bitgraph-core: host.getAttestation() must return { format: string, report: Uint8Array }");
231
+ }
232
+ attestation = {
233
+ format: result.format,
234
+ reportB64: toBase64(result.report),
235
+ };
236
+ // Also add attestationFormat to the signed body (already canonicalized
237
+ // above without it — we must add it BEFORE signing. Re-do steps 6-8
238
+ // with attestationFormat included so the format is covered by the sig.
239
+ signedBody.attestationFormat = result.format;
240
+ const canonicalBytesWithAttestation = canonicalize(signedBody);
241
+ const signatureBytesWithAttestation = await this.#host.sign(canonicalBytesWithAttestation).catch((cause) => {
242
+ throw new Error("bitgraph-core: host.sign() rejected (attestation body)", { cause });
243
+ });
244
+ assertUint8Array(signatureBytesWithAttestation, "signature", 64);
245
+ // ------------------------------------------------------------------
246
+ // Step 10: Assemble proof (with attestation)
247
+ // ------------------------------------------------------------------
248
+ const proof = {
249
+ version: "bitgraph/1",
250
+ artifact: signedBody.artifact,
251
+ commit: signedBody.commit,
252
+ signer: {
253
+ publicKeyB64: signedBody.publicKeyB64,
254
+ signatureB64: toBase64(signatureBytesWithAttestation),
255
+ },
256
+ environment: {
257
+ enforcement: this.#host.enforcementTier,
258
+ measurement: signedBody.measurement,
259
+ attestation,
260
+ },
261
+ };
262
+ if (agency !== undefined)
263
+ proof.agency = agency;
264
+ if (policy !== undefined)
265
+ proof.policy = policy;
266
+ if (attribution !== undefined)
267
+ proof.attribution = attribution;
268
+ if (metadata !== undefined)
269
+ proof.metadata = metadata;
270
+ return proof;
271
+ }
272
+ // ------------------------------------------------------------------
273
+ // Step 10: Assemble proof (without attestation)
274
+ // ------------------------------------------------------------------
275
+ const proof = {
276
+ version: "bitgraph/1",
277
+ artifact: signedBody.artifact,
278
+ commit: signedBody.commit,
279
+ signer: {
280
+ publicKeyB64: signedBody.publicKeyB64,
281
+ signatureB64: toBase64(signatureBytes),
282
+ },
283
+ environment: {
284
+ enforcement: this.#host.enforcementTier,
285
+ measurement: signedBody.measurement,
286
+ },
287
+ };
288
+ if (agency !== undefined)
289
+ proof.agency = agency;
290
+ if (policy !== undefined)
291
+ proof.policy = policy;
292
+ if (attribution !== undefined)
293
+ proof.attribution = attribution;
294
+ if (metadata !== undefined)
295
+ proof.metadata = metadata;
296
+ return proof;
297
+ }
298
+ }
299
+ // ---------------------------------------------------------------------------
300
+ // Internal guards
301
+ // ---------------------------------------------------------------------------
302
+ function assertUint8Array(value, name, minLength) {
303
+ if (!(value instanceof Uint8Array)) {
304
+ throw new TypeError(`bitgraph-core: host returned non-Uint8Array for ${name}`);
305
+ }
306
+ if (value.length < minLength) {
307
+ throw new RangeError(`bitgraph-core: host returned ${name} with insufficient length ` +
308
+ `(got ${value.length}, expected >= ${minLength})`);
309
+ }
310
+ }
311
+ function assertNonEmptyString(value, name) {
312
+ if (typeof value !== "string" || value.length === 0) {
313
+ throw new TypeError(`bitgraph-core: host returned invalid ${name}: expected a non-empty string`);
314
+ }
315
+ }
316
+ // ---------------------------------------------------------------------------
317
+ // Encoding utility
318
+ // ---------------------------------------------------------------------------
319
+ /**
320
+ * Encode a Uint8Array as standard Base64 (RFC 4648 §4, with padding).
321
+ */
322
+ function toBase64(bytes) {
323
+ return Buffer.from(bytes).toString("base64");
324
+ }
325
+ /**
326
+ * Decode a Base64 string to Uint8Array, validating round-trip fidelity.
327
+ * Used by commitDigest() to validate the caller-provided digest.
328
+ */
329
+ function fromBase64Digest(b64) {
330
+ if (typeof b64 !== "string" || b64.length === 0) {
331
+ throw new TypeError("bitgraph-core: digestB64 must be a non-empty string");
332
+ }
333
+ const buf = Buffer.from(b64, "base64");
334
+ if (buf.toString("base64") !== b64) {
335
+ throw new TypeError(`bitgraph-core: digestB64 is not valid base64: "${b64}"`);
336
+ }
337
+ return new Uint8Array(buf);
338
+ }
339
+ //# sourceMappingURL=constructor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constructor.js","sourceRoot":"","sources":["../src/constructor.ts"],"names":[],"mappings":"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"}
package/dist/host.d.ts ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * bitgraph-core host abstraction
3
+ *
4
+ * `HostCapabilities` is the sole interface between this library and any
5
+ * Trusted Execution Environment. All TEE-specific behavior (attestation,
6
+ * key management, monotonic counters, secure clocks) is supplied by a
7
+ * caller-provided implementation of this interface.
8
+ *
9
+ * Design goals:
10
+ * - TEE-agnostic: no vendor types leak into this file
11
+ * - Fail-closed: every capability is async and may reject
12
+ * - Extensible: optional capabilities use the ? modifier so that
13
+ * adapters can be progressively enhanced without breaking the core
14
+ * - Self-describing: enforcementTier declares the adapter's trust class
15
+ *
16
+ * Adapters (e.g. aws-nitro, sgx-dcap, sev-snp) live in separate packages
17
+ * and implement this interface. A minimal in-process stub for testing is
18
+ * provided in @bitgraph/stub.
19
+ *
20
+ * IMPORTANT — adapter authors:
21
+ * enforcementTier is self-reported and signed into every proof.
22
+ * Claiming "measured-tee" requires that ALL of the following execute
23
+ * inside the attested enclave boundary:
24
+ * - key generation and sealing
25
+ * - nonce generation (getFreshNonce)
26
+ * - monotonic counter (nextCounter)
27
+ * - commit gate logic
28
+ * - signing (sign)
29
+ * If any of these run outside the boundary, the correct tier is "hw-key"
30
+ * or "stub". Misrepresenting the tier is an architectural violation of
31
+ * BitGraph's atomic causality invariant.
32
+ */
33
+ import type { EnforcementTier } from "@mikeargento/bitgraph-verify";
34
+ export interface HostCapabilities {
35
+ /**
36
+ * Declares the enforcement tier of this adapter.
37
+ *
38
+ * This value is written into every proof's environment.enforcement field
39
+ * and is included in the signed body — making it tamper-evident in transit.
40
+ *
41
+ * Must be one of: "stub" | "hw-key" | "measured-tee"
42
+ * See EnforcementTier in types.ts for full semantics.
43
+ *
44
+ * This is a plain property (not async) because it is a static adapter
45
+ * declaration, not a runtime capability.
46
+ */
47
+ readonly enforcementTier: EnforcementTier;
48
+ /**
49
+ * Return the current enclave measurement as an opaque string.
50
+ *
51
+ * The format is adapter-defined (e.g. hex-encoded PCR0 for Nitro,
52
+ * MRENCLAVE for SGX). The verifier stores and compares this value
53
+ * verbatim; it does not parse or interpret it.
54
+ *
55
+ * Must not return a cached value from outside the TEE boundary.
56
+ *
57
+ * Tier expectations:
58
+ * stub: MAY return a synthetic sentinel
59
+ * hw-key: SHOULD return a string identifying the key environment
60
+ * measured-tee: MUST return the attested enclave image identifier
61
+ */
62
+ getMeasurement(): Promise<string>;
63
+ /**
64
+ * Generate a fresh, boundary-local nonce.
65
+ *
66
+ * The nonce MUST be:
67
+ * - generated inside the TEE boundary (not passed in from the host OS)
68
+ * - at least 128 bits of entropy
69
+ * - never reused across calls
70
+ *
71
+ * Returns raw bytes; the library base64-encodes them for the proof.
72
+ */
73
+ getFreshNonce(): Promise<Uint8Array>;
74
+ /**
75
+ * Sign `data` with the enclave's private signing key.
76
+ *
77
+ * The key MUST be:
78
+ * - generated or provisioned inside the TEE boundary
79
+ * - an Ed25519 key pair
80
+ * - not exportable from the TEE
81
+ *
82
+ * Adapter note: when using @noble/ed25519, prefer signAsync() over sign()
83
+ * to avoid requiring a synchronous SHA-512 shim in Node.js environments.
84
+ *
85
+ * Returns the raw 64-byte Ed25519 signature.
86
+ */
87
+ sign(data: Uint8Array): Promise<Uint8Array>;
88
+ /**
89
+ * Return the Ed25519 public key corresponding to the signing key.
90
+ *
91
+ * Returns raw 32-byte compressed public key bytes.
92
+ * Must be stable across calls within a single enclave lifecycle.
93
+ */
94
+ getPublicKey(): Promise<Uint8Array>;
95
+ /**
96
+ * Atomically advance and return a monotonic counter.
97
+ *
98
+ * The counter MUST be:
99
+ * - monotonically increasing across restarts (hardware-backed preferred)
100
+ * - returned as a decimal string (no leading zeros unless "0", ASCII digits only)
101
+ * - never the same value twice (even after a crash/restart)
102
+ *
103
+ * Compared as BigInt by the verifier to avoid IEEE-754 precision loss.
104
+ * Absence of this capability degrades ordering guarantees to nonce-only.
105
+ */
106
+ nextCounter?(): Promise<string>;
107
+ /**
108
+ * Return a TEE-local attestation report that binds the current enclave
109
+ * state to an optional nonce or arbitrary user data.
110
+ *
111
+ * `userData` is adapter-defined; typically a hash of the canonical proof
112
+ * body so the report is bound to this specific commit.
113
+ *
114
+ * The returned object includes:
115
+ * - format — adapter-defined format identifier (e.g. "aws-nitro", "sgx-dcap")
116
+ * - report — raw attestation report bytes; the library does not parse them
117
+ *
118
+ * format is stored in environment.attestation.format and IS signed.
119
+ * report is stored in environment.attestation.reportB64 and is NOT signed
120
+ * (it is vendor-signed and self-authenticating).
121
+ */
122
+ getAttestation?(userData?: Uint8Array): Promise<{
123
+ format: string;
124
+ report: Uint8Array;
125
+ }>;
126
+ /**
127
+ * Return the current time as Unix epoch milliseconds from a TEE-trusted
128
+ * source.
129
+ *
130
+ * Software clocks inside TEEs can be skewed or forged by a malicious host.
131
+ * This capability is marked optional because not all TEE platforms provide
132
+ * a trusted clock. When absent, commit.time is omitted from the proof.
133
+ *
134
+ * Callers must not use time as the sole ordering mechanism.
135
+ */
136
+ secureTime?(): Promise<number>;
137
+ }
138
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMpE,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C;;;;;;;;;;;;;OAaG;IACH,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAElC;;;;;;;;;OASG;IACH,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAErC;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE5C;;;;;OAKG;IACH,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAMpC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEhC;;;;;;;;;;;;;;OAcG;IACH,cAAc,CAAC,CAAC,QAAQ,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IAExF;;;;;;;;;OASG;IACH,UAAU,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAChC"}
package/dist/host.js ADDED
@@ -0,0 +1,3 @@
1
+ // Copyright (c) Mike Argento. All rights reserved. See LICENSE.
2
+ export {};
3
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,gEAAgE"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * bitgraph-core — BitGraph
3
+ *
4
+ * Portable cryptographic proof at finalization.
5
+ * Hardware TEE enforcement via AWS Nitro Enclaves.
6
+ *
7
+ * The verification side (verify, proof schema, canonicalization, proofHash)
8
+ * lives in @mikeargento/bitgraph-verify (MIT) and is re-exported here for
9
+ * compatibility. Verification of BitGraph proofs is permissionless.
10
+ */
11
+ export type { BitGraphProof, BitGraphPolicy, VerificationPolicy, SignedBody, EnforcementTier, Attribution, PolicyBinding, SlotAllocation, ActorIdentity, AuthorizationPayload, WebAuthnAuthorization, AgencyEnvelope, } from "@mikeargento/bitgraph-verify";
12
+ export { verify, resetEpochLinkState } from "@mikeargento/bitgraph-verify";
13
+ export type { VerifyResult } from "@mikeargento/bitgraph-verify";
14
+ export { computeProofHash } from "@mikeargento/bitgraph-verify";
15
+ export { canonicalize, canonicalizeToString, constantTimeEqual } from "@mikeargento/bitgraph-verify";
16
+ export type { HostCapabilities } from "./host.js";
17
+ export { Constructor } from "./constructor.js";
18
+ export { parsePolicy, hashPolicy, createPolicyBinding, validateAction, } from "./policy.js";
19
+ export type { PolicyDocument, PolicyRules, ActionValidationResult, } from "./policy.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAGH,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGrG,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EACL,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,WAAW,EACX,sBAAsB,GACvB,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // Copyright (c) Mike Argento. All rights reserved. See LICENSE.
2
+ export { verify, resetEpochLinkState } from "@mikeargento/bitgraph-verify";
3
+ export { computeProofHash } from "@mikeargento/bitgraph-verify";
4
+ export { canonicalize, canonicalizeToString, constantTimeEqual } from "@mikeargento/bitgraph-verify";
5
+ // Constructor (write path)
6
+ export { Constructor } from "./constructor.js";
7
+ // Policy parsing, hashing, and validation
8
+ export { parsePolicy, hashPolicy, createPolicyBinding, validateAction, } from "./policy.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gEAAgE;AA4BhE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKrG,2BAA2B;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,0CAA0C;AAC1C,OAAO,EACL,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,cAAc,GACf,MAAM,aAAa,CAAC"}