@occ-core/stub 0.1.0 → 1.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
1
3
  /**
2
4
  * @occ/stub public API
3
5
  */
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,mCAAmC;AAEnC;;GAEG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,119 +1,27 @@
1
- /**
2
- * @occ/stub — StubHost
3
- *
4
- * An in-process implementation of HostCapabilities for development and
5
- * testing. All TEE-specific operations are performed in software using
6
- * Node.js built-ins and @noble/ed25519.
7
- *
8
- * SECURITY WARNING: This implementation provides NO security guarantees.
9
- * Keys are held in process memory (or a plaintext JSON file for persistence),
10
- * the counter is software-only, and there is no hardware-backed attestation.
11
- *
12
- * DO NOT use StubHost in production or in any security-sensitive context.
13
- * Its sole purpose is to allow developers to run, test, and explore
14
- * occ-core locally without a real TEE.
15
- */
16
- import type { HostCapabilities } from "@occ/core";
1
+ import type { HostCapabilities } from "occproof";
17
2
  export interface StubHostOptions {
18
- /**
19
- * Ed25519 private key (32 bytes).
20
- * If omitted, a fresh random key is generated.
21
- * Providing a fixed key is useful for deterministic tests.
22
- */
23
3
  privateKey?: Uint8Array;
24
- /**
25
- * Measurement string returned by getMeasurement().
26
- * Defaults to a fixed placeholder string.
27
- */
28
4
  measurement?: string;
29
- /**
30
- * Initial counter value. Defaults to 0.
31
- */
32
5
  initialCounter?: bigint;
33
- /**
34
- * If true, secureTime() is available and returns Date.now().
35
- * Defaults to true.
36
- */
37
6
  enableTime?: boolean;
38
- /**
39
- * If true, nextCounter() is available.
40
- * Defaults to true.
41
- */
42
7
  enableCounter?: boolean;
43
8
  }
44
9
  export interface PersistentStubHostOptions {
45
- /**
46
- * Path to a JSON file where identity and counter state is persisted.
47
- * If the file does not exist, it is created with a fresh keypair and
48
- * counter starting at 0. If it exists, the stored key and counter
49
- * are loaded and resumed.
50
- */
51
10
  statePath: string;
52
- /**
53
- * Measurement string returned by getMeasurement().
54
- * Defaults to "stub:measurement:not-a-real-tee".
55
- */
56
11
  measurement?: string;
57
- /**
58
- * If true, secureTime() is available and returns Date.now().
59
- * Defaults to true.
60
- */
61
12
  enableTime?: boolean;
62
- /**
63
- * If true, nextCounter() is available and persists across restarts.
64
- * Defaults to true.
65
- */
66
13
  enableCounter?: boolean;
67
14
  }
68
- /**
69
- * StubHost wraps a HostCapabilities object built from in-process crypto.
70
- *
71
- * Optional capabilities are conditionally attached to the plain object
72
- * returned by `.host` — this avoids TypeScript exactOptionalPropertyTypes
73
- * conflicts that arise when implementing optional interface methods as class
74
- * fields that could be undefined.
75
- */
76
15
  export declare class StubHost {
77
16
  #private;
78
17
  private constructor();
79
- /**
80
- * Record the hash of the last produced proof into persistent state.
81
- * Call this after each successful commit when using persistent mode to
82
- * enable automatic proof chaining across restarts.
83
- */
84
18
  setLastProofHash(hashB64: string): void;
85
- /**
86
- * Read the last proof hash from persistent state (for chaining).
87
- * Returns undefined if no proof has been committed yet.
88
- */
89
19
  getLastProofHash(): string | undefined;
90
- /**
91
- * Create a StubHost with ephemeral (in-memory) state.
92
- * Counter resets to 0 on every process restart.
93
- * Async because key derivation is async in @noble/ed25519.
94
- */
95
20
  static create(opts?: StubHostOptions): Promise<StubHost>;
96
- /**
97
- * Create a StubHost that persists identity and counter to a JSON file.
98
- *
99
- * On first call: generates a fresh keypair and writes it to `statePath`.
100
- * On subsequent calls: loads the existing keypair and counter and resumes.
101
- *
102
- * This lets a local demo service maintain a stable identity and
103
- * monotonically increasing counter across restarts.
104
- *
105
- * The state file is plaintext JSON — not for production use.
106
- */
107
21
  static createPersistent(opts: PersistentStubHostOptions): Promise<StubHost>;
108
- /**
109
- * Return the HostCapabilities object to pass to Constructor.initialize().
110
- */
111
22
  get host(): HostCapabilities;
112
- /** Return the raw private key bytes (test use only). */
113
23
  get privateKeyBytes(): Uint8Array;
114
- /** Return the raw public key bytes. */
115
24
  get publicKeyBytes(): Uint8Array;
116
- /** Return the current counter value without advancing it. */
117
25
  get currentCounter(): bigint;
118
26
  }
119
27
  //# sourceMappingURL=stub-host.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stub-host.d.ts","sourceRoot":"","sources":["../src/stub-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAMlD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IAExB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAMD,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAmBD;;;;;;;GAOG;AACH,qBAAa,QAAQ;;IAQnB,OAAO;IAoDP;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAevC;;;OAGG;IACH,gBAAgB,IAAI,MAAM,GAAG,SAAS;IActC;;;;OAIG;WACU,MAAM,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAkBlE;;;;;;;;;;OAUG;WACU,gBAAgB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAmDjF;;OAEG;IACH,IAAI,IAAI,IAAI,gBAAgB,CAE3B;IAED,wDAAwD;IACxD,IAAI,eAAe,IAAI,UAAU,CAEhC;IAED,uCAAuC;IACvC,IAAI,cAAc,IAAI,UAAU,CAE/B;IAED,6DAA6D;IAC7D,IAAI,cAAc,IAAI,MAAM,CAE3B;CACF"}
1
+ {"version":3,"file":"stub-host.d.ts","sourceRoot":"","sources":["../src/stub-host.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAMjD,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAgBD,qBAAa,QAAQ;;IAQnB,OAAO;IA8CP,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAevC,gBAAgB,IAAI,MAAM,GAAG,SAAS;WAUzB,MAAM,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC;WAkBrD,gBAAgB,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,QAAQ,CAAC;IA4CjF,IAAI,IAAI,IAAI,gBAAgB,CAE3B;IAED,IAAI,eAAe,IAAI,UAAU,CAEhC;IAED,IAAI,cAAc,IAAI,UAAU,CAE/B;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;CACF"}
package/dist/stub-host.js CHANGED
@@ -1,3 +1,5 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
1
3
  /**
2
4
  * @occ/stub — StubHost
3
5
  *
@@ -6,12 +8,7 @@
6
8
  * Node.js built-ins and @noble/ed25519.
7
9
  *
8
10
  * SECURITY WARNING: This implementation provides NO security guarantees.
9
- * Keys are held in process memory (or a plaintext JSON file for persistence),
10
- * the counter is software-only, and there is no hardware-backed attestation.
11
- *
12
11
  * DO NOT use StubHost in production or in any security-sensitive context.
13
- * Its sole purpose is to allow developers to run, test, and explore
14
- * occ-core locally without a real TEE.
15
12
  */
16
13
  import { getPublicKeyAsync, signAsync, utils } from "@noble/ed25519";
17
14
  import { randomBytes } from "crypto";
@@ -20,14 +17,6 @@ import { dirname } from "path";
20
17
  // ---------------------------------------------------------------------------
21
18
  // StubHost
22
19
  // ---------------------------------------------------------------------------
23
- /**
24
- * StubHost wraps a HostCapabilities object built from in-process crypto.
25
- *
26
- * Optional capabilities are conditionally attached to the plain object
27
- * returned by `.host` — this avoids TypeScript exactOptionalPropertyTypes
28
- * conflicts that arise when implementing optional interface methods as class
29
- * fields that could be undefined.
30
- */
31
20
  export class StubHost {
32
21
  #host;
33
22
  #privateKey;
@@ -41,7 +30,6 @@ export class StubHost {
41
30
  this.#measurement = opts.measurement;
42
31
  this.#counter = opts.initialCounter;
43
32
  this.#statePath = statePath;
44
- // Build the base host with required capabilities
45
33
  const base = {
46
34
  enforcementTier: "stub",
47
35
  getMeasurement: async () => this.#measurement,
@@ -49,7 +37,6 @@ export class StubHost {
49
37
  sign: async (data) => signAsync(data, this.#privateKey),
50
38
  getPublicKey: async () => this.#publicKey,
51
39
  };
52
- // Conditionally attach optional capabilities
53
40
  if (opts.enableCounter) {
54
41
  base.nextCounter = async () => {
55
42
  this.#counter += 1n;
@@ -64,9 +51,6 @@ export class StubHost {
64
51
  }
65
52
  this.#host = base;
66
53
  }
67
- // ---------------------------------------------------------------------------
68
- // Persistence helpers
69
- // ---------------------------------------------------------------------------
70
54
  #persistState() {
71
55
  if (this.#statePath === undefined)
72
56
  return;
@@ -76,11 +60,6 @@ export class StubHost {
76
60
  };
77
61
  writeFileSync(this.#statePath, JSON.stringify(state, null, 2), "utf8");
78
62
  }
79
- /**
80
- * Record the hash of the last produced proof into persistent state.
81
- * Call this after each successful commit when using persistent mode to
82
- * enable automatic proof chaining across restarts.
83
- */
84
63
  setLastProofHash(hashB64) {
85
64
  if (this.#statePath === undefined)
86
65
  return;
@@ -97,10 +76,6 @@ export class StubHost {
97
76
  existing.lastProofHashB64 = hashB64;
98
77
  writeFileSync(this.#statePath, JSON.stringify(existing, null, 2), "utf8");
99
78
  }
100
- /**
101
- * Read the last proof hash from persistent state (for chaining).
102
- * Returns undefined if no proof has been committed yet.
103
- */
104
79
  getLastProofHash() {
105
80
  if (this.#statePath === undefined)
106
81
  return undefined;
@@ -112,14 +87,6 @@ export class StubHost {
112
87
  return undefined;
113
88
  }
114
89
  }
115
- // ---------------------------------------------------------------------------
116
- // Factory methods
117
- // ---------------------------------------------------------------------------
118
- /**
119
- * Create a StubHost with ephemeral (in-memory) state.
120
- * Counter resets to 0 on every process restart.
121
- * Async because key derivation is async in @noble/ed25519.
122
- */
123
90
  static async create(opts = {}) {
124
91
  const privateKey = opts.privateKey ?? utils.randomPrivateKey();
125
92
  if (privateKey.length !== 32) {
@@ -135,22 +102,10 @@ export class StubHost {
135
102
  };
136
103
  return new StubHost(privateKey, publicKey, resolved);
137
104
  }
138
- /**
139
- * Create a StubHost that persists identity and counter to a JSON file.
140
- *
141
- * On first call: generates a fresh keypair and writes it to `statePath`.
142
- * On subsequent calls: loads the existing keypair and counter and resumes.
143
- *
144
- * This lets a local demo service maintain a stable identity and
145
- * monotonically increasing counter across restarts.
146
- *
147
- * The state file is plaintext JSON — not for production use.
148
- */
149
105
  static async createPersistent(opts) {
150
106
  const { statePath, measurement, enableTime, enableCounter } = opts;
151
107
  let privateKey;
152
108
  let initialCounter;
153
- // Try to load existing state
154
109
  let existingState;
155
110
  try {
156
111
  existingState = JSON.parse(readFileSync(statePath, "utf8"));
@@ -163,10 +118,8 @@ export class StubHost {
163
118
  initialCounter = BigInt(existingState.counter);
164
119
  }
165
120
  else {
166
- // First run — generate a fresh key
167
121
  privateKey = utils.randomPrivateKey();
168
122
  initialCounter = 0n;
169
- // Ensure the directory exists
170
123
  mkdirSync(dirname(statePath), { recursive: true });
171
124
  const initialState = {
172
125
  privateKeyB64: Buffer.from(privateKey).toString("base64"),
@@ -187,24 +140,15 @@ export class StubHost {
187
140
  };
188
141
  return new StubHost(privateKey, publicKey, resolved, statePath);
189
142
  }
190
- // ---------------------------------------------------------------------------
191
- // Accessors
192
- // ---------------------------------------------------------------------------
193
- /**
194
- * Return the HostCapabilities object to pass to Constructor.initialize().
195
- */
196
143
  get host() {
197
144
  return this.#host;
198
145
  }
199
- /** Return the raw private key bytes (test use only). */
200
146
  get privateKeyBytes() {
201
147
  return this.#privateKey;
202
148
  }
203
- /** Return the raw public key bytes. */
204
149
  get publicKeyBytes() {
205
150
  return this.#publicKey;
206
151
  }
207
- /** Return the current counter value without advancing it. */
208
152
  get currentCounter() {
209
153
  return this.#counter;
210
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stub-host.js","sourceRoot":"","sources":["../src/stub-host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stub-host.js","sourceRoot":"","sources":["../src/stub-host.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,58 +1,31 @@
1
1
  {
2
2
  "name": "@occ-core/stub",
3
- "version": "0.1.0",
4
- "description": "In-process HostCapabilities stub for occ-core development and testing only",
5
- "keywords": [
6
- "occ",
7
- "origin-controlled-computing",
8
- "tee",
9
- "stub",
10
- "dev",
11
- "ed25519",
12
- "tamper-evident"
13
- ],
3
+ "version": "1.0.0",
4
+ "description": "In-process stub adapter for OCC development and testing",
14
5
  "author": "Mike Argento",
15
6
  "license": "Apache-2.0",
16
- "repository": {
17
- "type": "git",
18
- "url": "https://github.com/mikeargento/occ-core.git",
19
- "directory": "packages/occ-core-stub"
20
- },
21
- "homepage": "https://github.com/mikeargento/occ-core#readme",
22
- "bugs": {
23
- "url": "https://github.com/mikeargento/occ-core/issues"
24
- },
25
7
  "type": "module",
26
8
  "main": "./dist/index.js",
27
9
  "types": "./dist/index.d.ts",
28
- "sideEffects": false,
29
10
  "exports": {
30
11
  ".": {
31
12
  "import": "./dist/index.js",
32
13
  "types": "./dist/index.d.ts"
33
14
  }
34
15
  },
35
- "files": [
36
- "dist",
37
- "!dist/__tests__",
38
- "src",
39
- "!src/__tests__"
40
- ],
41
16
  "scripts": {
42
17
  "build": "tsc",
43
- "typecheck": "tsc --noEmit",
44
- "test": "npm run build && node --test dist/__tests__/*.test.js",
45
- "prepublishOnly": "npm run build && npm test"
18
+ "typecheck": "tsc --noEmit"
46
19
  },
47
20
  "dependencies": {
48
21
  "@noble/ed25519": "^2.1.0",
49
- "@occ-core/core": "*"
22
+ "occproof": "^1.0.2"
50
23
  },
51
24
  "devDependencies": {
52
25
  "@types/node": "^20.0.0",
53
26
  "typescript": "^5.4.0"
54
27
  },
55
28
  "engines": {
56
- "node": ">=18.0.0"
29
+ "node": ">=20.0.0"
57
30
  }
58
31
  }
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+
1
4
  /**
2
5
  * @occ/stub public API
3
6
  */
package/src/stub-host.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2024-2026 Mike Argento
3
+
1
4
  /**
2
5
  * @occ/stub — StubHost
3
6
  *
@@ -6,98 +9,41 @@
6
9
  * Node.js built-ins and @noble/ed25519.
7
10
  *
8
11
  * SECURITY WARNING: This implementation provides NO security guarantees.
9
- * Keys are held in process memory (or a plaintext JSON file for persistence),
10
- * the counter is software-only, and there is no hardware-backed attestation.
11
- *
12
12
  * DO NOT use StubHost in production or in any security-sensitive context.
13
- * Its sole purpose is to allow developers to run, test, and explore
14
- * occ-core locally without a real TEE.
15
13
  */
16
14
 
17
15
  import { getPublicKeyAsync, signAsync, utils } from "@noble/ed25519";
18
16
  import { randomBytes } from "crypto";
19
17
  import { readFileSync, writeFileSync, mkdirSync } from "fs";
20
18
  import { dirname } from "path";
21
- import type { HostCapabilities } from "@occ/core";
19
+ import type { HostCapabilities } from "occproof";
22
20
 
23
21
  // ---------------------------------------------------------------------------
24
22
  // StubHost options
25
23
  // ---------------------------------------------------------------------------
26
24
 
27
25
  export interface StubHostOptions {
28
- /**
29
- * Ed25519 private key (32 bytes).
30
- * If omitted, a fresh random key is generated.
31
- * Providing a fixed key is useful for deterministic tests.
32
- */
33
26
  privateKey?: Uint8Array;
34
-
35
- /**
36
- * Measurement string returned by getMeasurement().
37
- * Defaults to a fixed placeholder string.
38
- */
39
27
  measurement?: string;
40
-
41
- /**
42
- * Initial counter value. Defaults to 0.
43
- */
44
28
  initialCounter?: bigint;
45
-
46
- /**
47
- * If true, secureTime() is available and returns Date.now().
48
- * Defaults to true.
49
- */
50
29
  enableTime?: boolean;
51
-
52
- /**
53
- * If true, nextCounter() is available.
54
- * Defaults to true.
55
- */
56
30
  enableCounter?: boolean;
57
31
  }
58
32
 
59
- // ---------------------------------------------------------------------------
60
- // Persistent StubHost options
61
- // ---------------------------------------------------------------------------
62
-
63
33
  export interface PersistentStubHostOptions {
64
- /**
65
- * Path to a JSON file where identity and counter state is persisted.
66
- * If the file does not exist, it is created with a fresh keypair and
67
- * counter starting at 0. If it exists, the stored key and counter
68
- * are loaded and resumed.
69
- */
70
34
  statePath: string;
71
-
72
- /**
73
- * Measurement string returned by getMeasurement().
74
- * Defaults to "stub:measurement:not-a-real-tee".
75
- */
76
35
  measurement?: string;
77
-
78
- /**
79
- * If true, secureTime() is available and returns Date.now().
80
- * Defaults to true.
81
- */
82
36
  enableTime?: boolean;
83
-
84
- /**
85
- * If true, nextCounter() is available and persists across restarts.
86
- * Defaults to true.
87
- */
88
37
  enableCounter?: boolean;
89
38
  }
90
39
 
91
40
  // ---------------------------------------------------------------------------
92
- // Persisted state shape (written as JSON)
41
+ // Persisted state shape
93
42
  // ---------------------------------------------------------------------------
94
43
 
95
44
  interface PersistedState {
96
- /** Base64-encoded Ed25519 private key (32 bytes). */
97
45
  privateKeyB64: string;
98
- /** Current counter value as a decimal string (survives BigInt round-trip). */
99
46
  counter: string;
100
- /** Base64 of the last proof's canonical hash — populated by the service layer. */
101
47
  lastProofHashB64?: string;
102
48
  }
103
49
 
@@ -105,14 +51,6 @@ interface PersistedState {
105
51
  // StubHost
106
52
  // ---------------------------------------------------------------------------
107
53
 
108
- /**
109
- * StubHost wraps a HostCapabilities object built from in-process crypto.
110
- *
111
- * Optional capabilities are conditionally attached to the plain object
112
- * returned by `.host` — this avoids TypeScript exactOptionalPropertyTypes
113
- * conflicts that arise when implementing optional interface methods as class
114
- * fields that could be undefined.
115
- */
116
54
  export class StubHost {
117
55
  readonly #host: HostCapabilities;
118
56
  readonly #privateKey: Uint8Array;
@@ -133,7 +71,6 @@ export class StubHost {
133
71
  this.#counter = opts.initialCounter;
134
72
  this.#statePath = statePath;
135
73
 
136
- // Build the base host with required capabilities
137
74
  const base: HostCapabilities = {
138
75
  enforcementTier: "stub",
139
76
  getMeasurement: async () => this.#measurement,
@@ -142,7 +79,6 @@ export class StubHost {
142
79
  getPublicKey: async () => this.#publicKey,
143
80
  };
144
81
 
145
- // Conditionally attach optional capabilities
146
82
  if (opts.enableCounter) {
147
83
  base.nextCounter = async (): Promise<string> => {
148
84
  this.#counter += 1n;
@@ -160,10 +96,6 @@ export class StubHost {
160
96
  this.#host = base;
161
97
  }
162
98
 
163
- // ---------------------------------------------------------------------------
164
- // Persistence helpers
165
- // ---------------------------------------------------------------------------
166
-
167
99
  #persistState(): void {
168
100
  if (this.#statePath === undefined) return;
169
101
  const state: PersistedState = {
@@ -173,11 +105,6 @@ export class StubHost {
173
105
  writeFileSync(this.#statePath, JSON.stringify(state, null, 2), "utf8");
174
106
  }
175
107
 
176
- /**
177
- * Record the hash of the last produced proof into persistent state.
178
- * Call this after each successful commit when using persistent mode to
179
- * enable automatic proof chaining across restarts.
180
- */
181
108
  setLastProofHash(hashB64: string): void {
182
109
  if (this.#statePath === undefined) return;
183
110
  let existing: PersistedState;
@@ -193,10 +120,6 @@ export class StubHost {
193
120
  writeFileSync(this.#statePath, JSON.stringify(existing, null, 2), "utf8");
194
121
  }
195
122
 
196
- /**
197
- * Read the last proof hash from persistent state (for chaining).
198
- * Returns undefined if no proof has been committed yet.
199
- */
200
123
  getLastProofHash(): string | undefined {
201
124
  if (this.#statePath === undefined) return undefined;
202
125
  try {
@@ -207,15 +130,6 @@ export class StubHost {
207
130
  }
208
131
  }
209
132
 
210
- // ---------------------------------------------------------------------------
211
- // Factory methods
212
- // ---------------------------------------------------------------------------
213
-
214
- /**
215
- * Create a StubHost with ephemeral (in-memory) state.
216
- * Counter resets to 0 on every process restart.
217
- * Async because key derivation is async in @noble/ed25519.
218
- */
219
133
  static async create(opts: StubHostOptions = {}): Promise<StubHost> {
220
134
  const privateKey = opts.privateKey ?? utils.randomPrivateKey();
221
135
  if (privateKey.length !== 32) {
@@ -234,24 +148,12 @@ export class StubHost {
234
148
  return new StubHost(privateKey, publicKey, resolved);
235
149
  }
236
150
 
237
- /**
238
- * Create a StubHost that persists identity and counter to a JSON file.
239
- *
240
- * On first call: generates a fresh keypair and writes it to `statePath`.
241
- * On subsequent calls: loads the existing keypair and counter and resumes.
242
- *
243
- * This lets a local demo service maintain a stable identity and
244
- * monotonically increasing counter across restarts.
245
- *
246
- * The state file is plaintext JSON — not for production use.
247
- */
248
151
  static async createPersistent(opts: PersistentStubHostOptions): Promise<StubHost> {
249
152
  const { statePath, measurement, enableTime, enableCounter } = opts;
250
153
 
251
154
  let privateKey: Uint8Array;
252
155
  let initialCounter: bigint;
253
156
 
254
- // Try to load existing state
255
157
  let existingState: PersistedState | undefined;
256
158
  try {
257
159
  existingState = JSON.parse(readFileSync(statePath, "utf8")) as PersistedState;
@@ -263,10 +165,8 @@ export class StubHost {
263
165
  privateKey = new Uint8Array(Buffer.from(existingState.privateKeyB64, "base64"));
264
166
  initialCounter = BigInt(existingState.counter);
265
167
  } else {
266
- // First run — generate a fresh key
267
168
  privateKey = utils.randomPrivateKey();
268
169
  initialCounter = 0n;
269
- // Ensure the directory exists
270
170
  mkdirSync(dirname(statePath), { recursive: true });
271
171
  const initialState: PersistedState = {
272
172
  privateKeyB64: Buffer.from(privateKey).toString("base64"),
@@ -292,28 +192,18 @@ export class StubHost {
292
192
  return new StubHost(privateKey, publicKey, resolved, statePath);
293
193
  }
294
194
 
295
- // ---------------------------------------------------------------------------
296
- // Accessors
297
- // ---------------------------------------------------------------------------
298
-
299
- /**
300
- * Return the HostCapabilities object to pass to Constructor.initialize().
301
- */
302
195
  get host(): HostCapabilities {
303
196
  return this.#host;
304
197
  }
305
198
 
306
- /** Return the raw private key bytes (test use only). */
307
199
  get privateKeyBytes(): Uint8Array {
308
200
  return this.#privateKey;
309
201
  }
310
202
 
311
- /** Return the raw public key bytes. */
312
203
  get publicKeyBytes(): Uint8Array {
313
204
  return this.#publicKey;
314
205
  }
315
206
 
316
- /** Return the current counter value without advancing it. */
317
207
  get currentCounter(): bigint {
318
208
  return this.#counter;
319
209
  }
package/tsconfig.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "sourceMap": true,
12
+ "strict": true,
13
+ "noUncheckedIndexedAccess": true,
14
+ "exactOptionalPropertyTypes": true,
15
+ "noImplicitReturns": true,
16
+ "noFallthroughCasesInSwitch": true,
17
+ "forceConsistentCasingInFileNames": true,
18
+ "esModuleInterop": false,
19
+ "skipLibCheck": true
20
+ },
21
+ "include": ["src/**/*.ts"],
22
+ "exclude": ["node_modules", "dist"]
23
+ }