@vorionsys/runtime 0.1.0 → 0.1.2

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.
package/README.md ADDED
@@ -0,0 +1,576 @@
1
+ # @vorionsys/runtime
2
+
3
+ Orchestration layer for AI agent governance, built on the [Vorion](https://github.com/vorionsys/vorion) trust framework and aligned with the BASIS (Baseline Authority for Safe & Interoperable Systems) specification.
4
+
5
+ Combines **Gate Trust** (one-time admission control) and **Dynamic Trust** (per-action real-time scoring) into a unified, fast decision system with cryptographic proof of every governance decision.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @vorionsys/runtime
11
+ ```
12
+
13
+ **Peer dependencies** (optional, enhance functionality):
14
+
15
+ ```bash
16
+ npm install @vorionsys/atsf-core @vorionsys/contracts
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import {
23
+ createTrustFacade,
24
+ createProofCommitter,
25
+ createIntentPipeline,
26
+ } from '@vorionsys/runtime';
27
+
28
+ // 1. Create the trust facade (Gate Trust + Dynamic Trust)
29
+ const facade = createTrustFacade();
30
+
31
+ // 2. Create the proof committer (cryptographic audit trail)
32
+ const committer = createProofCommitter();
33
+
34
+ // 3. Wire them together with the intent pipeline
35
+ const pipeline = createIntentPipeline(facade, committer);
36
+
37
+ // 4. Admit an agent (Gate Trust - "the door")
38
+ const admission = await facade.admit({
39
+ agentId: 'agent-123',
40
+ name: 'DataProcessor',
41
+ capabilities: ['read:data', 'write:reports'],
42
+ observationTier: 'GRAY_BOX',
43
+ });
44
+
45
+ console.log(admission.admitted); // true
46
+ console.log(admission.initialScore); // 200 (GRAY_BOX initial)
47
+ console.log(admission.observationCeiling); // 800
48
+
49
+ // 5. Authorize an action (Dynamic Trust - "the handshake")
50
+ const auth = await facade.authorize('agent-123', {
51
+ type: 'read',
52
+ resource: 'data/users',
53
+ });
54
+
55
+ if (auth.allowed) {
56
+ console.log('Decision tier:', auth.tier); // 'GREEN'
57
+ console.log('Constraints:', auth.constraints); // { timeoutMs, maxOperations, ... }
58
+ }
59
+ ```
60
+
61
+ ## What It Provides
62
+
63
+ | Component | Purpose |
64
+ |---|---|
65
+ | **TrustFacade** | Unified API combining gate trust (admission) and dynamic trust (per-action authorization) with an 8-tier trust model (T0-T7) |
66
+ | **ProofCommitter** | Zero-latency synchronous hash commitment (<1ms) with async Merkle-tree batching and optional Ed25519 signing |
67
+ | **IntentPipeline** | End-to-end orchestration: Intent -> Gate Check -> Authorization -> Execution -> Proof |
68
+ | **SQLiteProofStore** | Persistent proof storage backed by better-sqlite3 with WAL mode |
69
+ | **SQLiteTrustStore** | Persistent agent trust records and signal history backed by better-sqlite3 |
70
+ | **InMemoryProofStore** | In-memory proof store for testing and development |
71
+
72
+ ## Core Concepts
73
+
74
+ ### Trust Tiers (T0-T7)
75
+
76
+ Agents are assigned a numeric trust score (0-1000) that maps to one of eight tiers:
77
+
78
+ | Tier | Name | Score Range |
79
+ |------|------|-------------|
80
+ | T0 | Untrusted | 0-99 |
81
+ | T1 | Provisional | 100-199 |
82
+ | T2 | Basic | 200-349 |
83
+ | T3 | Monitored | 350-499 |
84
+ | T4 | Standard | 500-649 |
85
+ | T5 | Trusted | 650-799 |
86
+ | T6 | Elevated | 800-899 |
87
+ | T7 | Autonomous | 900-1000 |
88
+
89
+ ### Observation Tiers
90
+
91
+ Agent visibility determines the maximum trust score (ceiling) an agent can achieve:
92
+
93
+ - **BLACK_BOX** -- Opaque internals, ceiling at 500 (max T3)
94
+ - **GRAY_BOX** -- Partial visibility, ceiling at 800 (max T5)
95
+ - **WHITE_BOX** -- Full visibility, ceiling at 1000 (max T7)
96
+
97
+ ### Decision Tiers
98
+
99
+ Every authorization returns one of three decision tiers:
100
+
101
+ - **GREEN** -- Allowed with standard constraints
102
+ - **YELLOW** -- Allowed with additional constraints and refinement options
103
+ - **RED** -- Denied
104
+
105
+ ### Asymmetric Trust Dynamics
106
+
107
+ Trust is hard to earn and easy to lose. Decay and recovery dynamics are policy-configurable, preventing rapid trust escalation while enforcing accountability.
108
+
109
+ ## Subpath Imports
110
+
111
+ Each major component is available as a subpath import:
112
+
113
+ ```typescript
114
+ // Root -- all exports
115
+ import { createTrustFacade, createProofCommitter, createIntentPipeline } from '@vorionsys/runtime';
116
+
117
+ // Trust facade only
118
+ import { createTrustFacade, TrustFacade } from '@vorionsys/runtime/trust-facade';
119
+
120
+ // Proof committer only
121
+ import { createProofCommitter, ProofCommitter } from '@vorionsys/runtime/proof-committer';
122
+
123
+ // Intent pipeline only
124
+ import { createIntentPipeline, IntentPipeline } from '@vorionsys/runtime/intent-pipeline';
125
+
126
+ // Persistent stores
127
+ import { createSQLiteProofStore, createSQLiteTrustStore } from '@vorionsys/runtime/stores';
128
+ ```
129
+
130
+ ## API Reference
131
+
132
+ ### TrustFacade
133
+
134
+ The primary API for agent governance. Implements the `TrustGate` interface.
135
+
136
+ ```typescript
137
+ import { createTrustFacade, type TrustFacadeConfig } from '@vorionsys/runtime';
138
+
139
+ const facade = createTrustFacade({
140
+ // All fields are optional with sensible defaults
141
+ gateTrustCacheTtlMs: 3600000, // Cache gate trust results for 1 hour
142
+ maxAuthorizationLatencyMs: 50, // Target latency for authorize()
143
+ useAtsfForPersistence: true, // Use ATSF-core for persistence
144
+ useA3iForDynamics: true, // Use A3I for trust dynamics
145
+ primaryScoreSource: 'atsf', // Primary source for trust scores
146
+ });
147
+ ```
148
+
149
+ #### `facade.admit(agent: AgentCredentials): Promise<AdmissionResult>`
150
+
151
+ Gate trust check -- called once at agent registration. Result is cached.
152
+
153
+ ```typescript
154
+ const result = await facade.admit({
155
+ agentId: 'agent-123',
156
+ name: 'My Agent',
157
+ capabilities: ['read:data', 'write:reports'],
158
+ observationTier: 'WHITE_BOX', // 'BLACK_BOX' | 'GRAY_BOX' | 'WHITE_BOX'
159
+ metadata: { version: '1.0' }, // optional
160
+ });
161
+
162
+ // AdmissionResult:
163
+ // {
164
+ // admitted: boolean,
165
+ // initialTier: TrustTier, // 0-7
166
+ // initialScore: number, // e.g. 300 for WHITE_BOX
167
+ // observationCeiling: number, // e.g. 1000 for WHITE_BOX
168
+ // capabilities: string[],
169
+ // expiresAt: Date,
170
+ // reason?: string, // set when admitted === false
171
+ // }
172
+ ```
173
+
174
+ #### `facade.authorize(agentId: string, action: Action): Promise<AuthorizationResult>`
175
+
176
+ Dynamic trust check -- called on every action. Must be fast (<50ms target).
177
+
178
+ ```typescript
179
+ const auth = await facade.authorize('agent-123', {
180
+ type: 'read', // 'read' | 'write' | 'delete' | 'execute' | ...
181
+ resource: 'data/users',
182
+ context: { limit: 100 }, // optional
183
+ });
184
+
185
+ // AuthorizationResult:
186
+ // {
187
+ // allowed: boolean,
188
+ // tier: DecisionTier, // 'GREEN' | 'YELLOW' | 'RED'
189
+ // currentScore: number,
190
+ // currentTier: TrustTier,
191
+ // constraints?: Constraints, // timeoutMs, maxOperations, resourceLimits
192
+ // refinements?: Refinement[], // YELLOW decisions include refinement options
193
+ // reason: string,
194
+ // latencyMs: number,
195
+ // }
196
+ ```
197
+
198
+ #### `facade.fullCheck(agent: AgentCredentials, action: Action): Promise<FullCheckResult>`
199
+
200
+ Combined admission + authorization in a single call. Useful for first-time agent interactions.
201
+
202
+ ```typescript
203
+ const result = await facade.fullCheck(agentCredentials, action);
204
+
205
+ // FullCheckResult:
206
+ // {
207
+ // admission: AdmissionResult,
208
+ // authorization?: AuthorizationResult, // only present if admission.admitted === true
209
+ // }
210
+ ```
211
+
212
+ #### `facade.recordSignal(signal: TrustSignal): Promise<void>`
213
+
214
+ Record a trust signal that updates the agent's dynamic trust score.
215
+
216
+ ```typescript
217
+ await facade.recordSignal({
218
+ agentId: 'agent-123',
219
+ type: 'success', // 'success' | 'failure' | 'violation' | 'neutral'
220
+ weight: 0.5, // 0-1
221
+ source: 'execution-engine',
222
+ context: { intentId: '...' }, // optional
223
+ });
224
+ ```
225
+
226
+ #### `facade.getScore(agentId: string): Promise<number | null>`
227
+
228
+ Returns the current trust score, or `null` if the agent is unknown.
229
+
230
+ #### `facade.getTier(agentId: string): Promise<TrustTier | null>`
231
+
232
+ Returns the current trust tier (0-7), or `null` if the agent is unknown.
233
+
234
+ #### `facade.revoke(agentId: string, reason: string): Promise<void>`
235
+
236
+ Revoke an agent's admission. Clears cached trust data and prevents future authorizations until re-admitted.
237
+
238
+ ---
239
+
240
+ ### ProofCommitter
241
+
242
+ Zero-latency cryptographic proof system. Synchronous hash commitment on the hot path (<1ms), with asynchronous Merkle-tree batching on the cold path.
243
+
244
+ ```typescript
245
+ import { createProofCommitter, type ProofCommitterConfig } from '@vorionsys/runtime';
246
+
247
+ const committer = createProofCommitter({
248
+ maxBufferSize: 100, // Auto-flush when buffer reaches this size
249
+ flushIntervalMs: 100, // Periodic flush interval
250
+ enableSigning: false, // Enable Ed25519 signing
251
+ privateKey: undefined, // Base64-encoded Ed25519 private key (required if signing enabled)
252
+ });
253
+ ```
254
+
255
+ #### `committer.commit(event: ProofEvent): string`
256
+
257
+ Synchronous hot-path commitment. Returns a commitment ID. Target: <1ms.
258
+
259
+ ```typescript
260
+ const commitmentId = committer.commit({
261
+ type: 'intent_submitted', // ProofEventType
262
+ entityId: 'agent-123',
263
+ payload: { action: 'read', resource: 'data/users' },
264
+ timestamp: Date.now(),
265
+ correlationId: 'corr-456', // optional, for linking related events
266
+ });
267
+ ```
268
+
269
+ **ProofEventType values:** `'intent_submitted'` | `'decision_made'` | `'execution_started'` | `'execution_completed'` | `'trust_signal'` | `'agent_admitted'` | `'agent_revoked'` | `'parity_violation'`
270
+
271
+ #### `committer.flush(): Promise<void>`
272
+
273
+ Force-flush the buffer. Builds a Merkle tree, optionally signs, and persists to the proof store.
274
+
275
+ #### `committer.stop(): Promise<void>`
276
+
277
+ Flush remaining events and stop the periodic flush timer. Call this on shutdown.
278
+
279
+ #### `committer.getCommitment(commitmentId: string): Promise<ProofCommitment | null>`
280
+
281
+ Retrieve a commitment from the store by ID.
282
+
283
+ #### `committer.getCommitmentsForEntity(entityId: string): Promise<ProofCommitment[]>`
284
+
285
+ Retrieve all commitments for a given entity (agent, intent, etc.).
286
+
287
+ #### `committer.verifyCommitment(commitment: ProofCommitment): boolean`
288
+
289
+ Verify a commitment's SHA-256 hash matches the original event.
290
+
291
+ #### `committer.getMetrics()`
292
+
293
+ Returns `{ totalCommitments, totalBatches, avgFlushTimeMs, bufferSize }`.
294
+
295
+ #### `committer.getBufferSize(): number`
296
+
297
+ Returns the number of uncommitted events in the buffer.
298
+
299
+ ---
300
+
301
+ ### IntentPipeline
302
+
303
+ Orchestrates the full agent intent lifecycle: **Intent -> Gate Check -> Authorization -> Execution -> Proof**.
304
+
305
+ ```typescript
306
+ import { createIntentPipeline, type IntentPipelineConfig } from '@vorionsys/runtime';
307
+
308
+ const pipeline = createIntentPipeline(trustFacade, proofCommitter, {
309
+ verboseLogging: false, // Enable detailed logging
310
+ timeoutMs: 5000, // Maximum processing time
311
+ autoRecordSignals: true, // Auto-record trust signals on execution
312
+ });
313
+ ```
314
+
315
+ #### `pipeline.registerHandler(actionType: string, handler: ExecutionHandler): void`
316
+
317
+ Register an execution handler for an action type.
318
+
319
+ ```typescript
320
+ pipeline.registerHandler('read', async (intent, context) => {
321
+ // Execute the intent
322
+ const data = await myDatabase.query(intent.action.resource);
323
+ return { success: true, result: data };
324
+ });
325
+
326
+ pipeline.registerHandler('write', async (intent, context) => {
327
+ try {
328
+ await myDatabase.write(intent.action.resource, intent.metadata);
329
+ return { success: true };
330
+ } catch (err) {
331
+ return { success: false, error: err.message };
332
+ }
333
+ });
334
+ ```
335
+
336
+ #### `pipeline.submit(credentials: AgentCredentials, action: Action, metadata?: Record<string, unknown>): Promise<IntentResult>`
337
+
338
+ Submit an intent for full processing (gate check, authorization, execution, proof).
339
+
340
+ ```typescript
341
+ const result = await pipeline.submit(
342
+ {
343
+ agentId: 'agent-123',
344
+ name: 'DataProcessor',
345
+ capabilities: ['read:data'],
346
+ observationTier: 'GRAY_BOX',
347
+ },
348
+ { type: 'read', resource: 'data/users' },
349
+ { limit: 50 }, // optional metadata
350
+ );
351
+
352
+ // IntentResult:
353
+ // {
354
+ // intentId: string,
355
+ // allowed: boolean,
356
+ // tier: DecisionTier, // 'GREEN' | 'YELLOW' | 'RED'
357
+ // reason: string,
358
+ // commitmentId: string, // proof commitment ID
359
+ // constraints?: string[],
360
+ // processingTimeMs: number,
361
+ // }
362
+ ```
363
+
364
+ #### `pipeline.check(credentials: AgentCredentials, action: Action): Promise<{ allowed, tier, reason }>`
365
+
366
+ Quick authorization check without execution.
367
+
368
+ #### `pipeline.getMetrics()`
369
+
370
+ Returns `{ totalIntents, allowedIntents, deniedIntents, avgProcessingTimeMs, allowRate }`.
371
+
372
+ #### `pipeline.flushProofs(): Promise<void>`
373
+
374
+ Flush all pending proof commitments.
375
+
376
+ #### `pipeline.stop(): Promise<void>`
377
+
378
+ Stop the pipeline and flush remaining proofs.
379
+
380
+ ---
381
+
382
+ ### Persistent Stores
383
+
384
+ SQLite-backed stores for production use. Both use WAL mode by default for better write concurrency.
385
+
386
+ #### SQLiteProofStore
387
+
388
+ ```typescript
389
+ import { createSQLiteProofStore } from '@vorionsys/runtime/stores';
390
+
391
+ const proofStore = createSQLiteProofStore({
392
+ dbPath: './data/proofs.db', // Use ':memory:' for in-memory
393
+ walMode: true, // default: true
394
+ });
395
+
396
+ // Pass to ProofCommitter
397
+ const committer = createProofCommitter({ maxBufferSize: 100 }, proofStore);
398
+
399
+ // Query proofs
400
+ const commitment = await proofStore.getCommitment('commitment-id');
401
+ const batch = await proofStore.getBatch('batch-id');
402
+ const entityProofs = await proofStore.getCommitmentsForEntity('agent-123');
403
+
404
+ // Housekeeping
405
+ proofStore.getStats(); // { batches: number, commitments: number }
406
+ proofStore.close(); // Close DB connection on shutdown
407
+ ```
408
+
409
+ #### SQLiteTrustStore
410
+
411
+ ```typescript
412
+ import { createSQLiteTrustStore } from '@vorionsys/runtime/stores';
413
+
414
+ const trustStore = createSQLiteTrustStore({
415
+ dbPath: './data/trust.db', // Use ':memory:' for in-memory
416
+ walMode: true, // default: true
417
+ });
418
+
419
+ // Save/retrieve agent trust records
420
+ await trustStore.saveAgent(agentRecord);
421
+ const agent = await trustStore.getAgent('agent-123');
422
+
423
+ // Update scores
424
+ await trustStore.updateScore('agent-123', 450, 3);
425
+
426
+ // Revoke
427
+ await trustStore.revokeAgent('agent-123', 'Policy violation');
428
+
429
+ // Record and query trust signals
430
+ await trustStore.recordSignal(signalRecord);
431
+ const signals = await trustStore.getSignals('agent-123', 50);
432
+
433
+ // List active agents
434
+ const agents = await trustStore.listActiveAgents();
435
+
436
+ // Housekeeping
437
+ trustStore.getStats(); // { agents, activeAgents, signals }
438
+ trustStore.close();
439
+ ```
440
+
441
+ #### InMemoryProofStore
442
+
443
+ ```typescript
444
+ import { InMemoryProofStore } from '@vorionsys/runtime';
445
+
446
+ const store = new InMemoryProofStore();
447
+ // Same ProofStore interface, useful for testing
448
+ store.getStats(); // { batches: number, commitments: number }
449
+ store.clear(); // Reset all data
450
+ ```
451
+
452
+ ---
453
+
454
+ ### Logger
455
+
456
+ ```typescript
457
+ import { createLogger } from '@vorionsys/runtime';
458
+
459
+ const logger = createLogger({
460
+ component: 'my-component',
461
+ level: 'debug', // optional, defaults to LOG_LEVEL env var or 'info'
462
+ });
463
+ ```
464
+
465
+ Uses [pino](https://github.com/pinojs/pino) with pretty-printing in non-production environments.
466
+
467
+ ## Full Example: Intent Pipeline
468
+
469
+ ```typescript
470
+ import {
471
+ createTrustFacade,
472
+ createProofCommitter,
473
+ createIntentPipeline,
474
+ createSQLiteProofStore,
475
+ } from '@vorionsys/runtime';
476
+
477
+ // Set up persistent proof storage
478
+ const proofStore = createSQLiteProofStore({ dbPath: './data/proofs.db' });
479
+
480
+ // Create the governance stack
481
+ const facade = createTrustFacade();
482
+ const committer = createProofCommitter({ maxBufferSize: 50 }, proofStore);
483
+ const pipeline = createIntentPipeline(facade, committer, {
484
+ autoRecordSignals: true,
485
+ });
486
+
487
+ // Register execution handlers
488
+ pipeline.registerHandler('read', async (intent) => {
489
+ const data = await fetchData(intent.action.resource);
490
+ return { success: true, result: data };
491
+ });
492
+
493
+ // Submit an intent
494
+ const result = await pipeline.submit(
495
+ {
496
+ agentId: 'data-agent',
497
+ name: 'Data Agent',
498
+ capabilities: ['read:data'],
499
+ observationTier: 'GRAY_BOX',
500
+ },
501
+ { type: 'read', resource: 'data/reports' },
502
+ );
503
+
504
+ if (result.allowed) {
505
+ console.log(`Intent ${result.intentId} processed in ${result.processingTimeMs}ms`);
506
+ console.log(`Decision: ${result.tier}, Proof: ${result.commitmentId}`);
507
+ } else {
508
+ console.log(`Denied: ${result.reason}`);
509
+ }
510
+
511
+ // Graceful shutdown
512
+ await pipeline.stop();
513
+ proofStore.close();
514
+ ```
515
+
516
+ ## TypeScript
517
+
518
+ All types are exported from the root entry point:
519
+
520
+ ```typescript
521
+ import type {
522
+ // Trust Facade
523
+ TrustGate,
524
+ TrustFacadeConfig,
525
+ AgentCredentials,
526
+ AdmissionResult,
527
+ Action,
528
+ AuthorizationResult,
529
+ FullCheckResult,
530
+ TrustSignal,
531
+ TrustTier,
532
+ DecisionTier,
533
+ ObservationTier,
534
+ Constraints,
535
+ Refinement,
536
+
537
+ // Proof Committer
538
+ ProofEvent,
539
+ ProofEventType,
540
+ ProofCommitment,
541
+ ProofBatch,
542
+ ProofCommitterConfig,
543
+ ProofStore,
544
+
545
+ // Intent Pipeline
546
+ Intent,
547
+ IntentResult,
548
+ PipelineContext,
549
+ IntentPipelineConfig,
550
+ ExecutionHandler,
551
+
552
+ // Stores
553
+ SQLiteProofStoreConfig,
554
+ SQLiteTrustStoreConfig,
555
+ TrustStore,
556
+ AgentTrustRecord,
557
+ TrustSignalRecord,
558
+
559
+ // Logger
560
+ LoggerOptions,
561
+ } from '@vorionsys/runtime';
562
+ ```
563
+
564
+ ## Requirements
565
+
566
+ - Node.js >= 18.0.0
567
+ - TypeScript >= 5.0 (peer dependency)
568
+
569
+ ## License
570
+
571
+ [Apache-2.0](./LICENSE)
572
+
573
+ ## Links
574
+
575
+ - [Vorion Monorepo](https://github.com/vorionsys/vorion)
576
+ - [BASIS Specification](https://github.com/vorionsys/vorion/tree/main/docs) -- Baseline Authority for Safe & Interoperable Systems
@@ -31,65 +31,65 @@ export class SQLiteProofStore {
31
31
  logger.info({ dbPath: this.config.dbPath }, 'SQLite proof store initialized');
32
32
  }
33
33
  initializeSchema() {
34
- this.db.exec(`
35
- -- Batches table
36
- CREATE TABLE IF NOT EXISTS proof_batches (
37
- batch_id TEXT PRIMARY KEY,
38
- merkle_root TEXT NOT NULL,
39
- signature TEXT NOT NULL,
40
- created_at TEXT NOT NULL,
41
- event_count INTEGER NOT NULL
42
- );
43
-
44
- -- Commitments table
45
- CREATE TABLE IF NOT EXISTS proof_commitments (
46
- id TEXT PRIMARY KEY,
47
- hash TEXT NOT NULL,
48
- timestamp INTEGER NOT NULL,
49
- batch_id TEXT NOT NULL,
50
- event_type TEXT NOT NULL,
51
- entity_id TEXT NOT NULL,
52
- payload TEXT NOT NULL,
53
- correlation_id TEXT,
54
- FOREIGN KEY (batch_id) REFERENCES proof_batches(batch_id)
55
- );
56
-
57
- -- Index for entity lookups
58
- CREATE INDEX IF NOT EXISTS idx_commitments_entity_id ON proof_commitments(entity_id);
59
-
60
- -- Index for batch lookups
61
- CREATE INDEX IF NOT EXISTS idx_commitments_batch_id ON proof_commitments(batch_id);
62
-
63
- -- Index for timestamp queries
64
- CREATE INDEX IF NOT EXISTS idx_commitments_timestamp ON proof_commitments(timestamp);
34
+ this.db.exec(`
35
+ -- Batches table
36
+ CREATE TABLE IF NOT EXISTS proof_batches (
37
+ batch_id TEXT PRIMARY KEY,
38
+ merkle_root TEXT NOT NULL,
39
+ signature TEXT NOT NULL,
40
+ created_at TEXT NOT NULL,
41
+ event_count INTEGER NOT NULL
42
+ );
43
+
44
+ -- Commitments table
45
+ CREATE TABLE IF NOT EXISTS proof_commitments (
46
+ id TEXT PRIMARY KEY,
47
+ hash TEXT NOT NULL,
48
+ timestamp INTEGER NOT NULL,
49
+ batch_id TEXT NOT NULL,
50
+ event_type TEXT NOT NULL,
51
+ entity_id TEXT NOT NULL,
52
+ payload TEXT NOT NULL,
53
+ correlation_id TEXT,
54
+ FOREIGN KEY (batch_id) REFERENCES proof_batches(batch_id)
55
+ );
56
+
57
+ -- Index for entity lookups
58
+ CREATE INDEX IF NOT EXISTS idx_commitments_entity_id ON proof_commitments(entity_id);
59
+
60
+ -- Index for batch lookups
61
+ CREATE INDEX IF NOT EXISTS idx_commitments_batch_id ON proof_commitments(batch_id);
62
+
63
+ -- Index for timestamp queries
64
+ CREATE INDEX IF NOT EXISTS idx_commitments_timestamp ON proof_commitments(timestamp);
65
65
  `);
66
66
  logger.debug('Database schema initialized');
67
67
  }
68
68
  prepareStatements() {
69
69
  this.stmts = {
70
- insertBatch: this.db.prepare(`
71
- INSERT INTO proof_batches (batch_id, merkle_root, signature, created_at, event_count)
72
- VALUES (@batchId, @merkleRoot, @signature, @createdAt, @eventCount)
70
+ insertBatch: this.db.prepare(`
71
+ INSERT INTO proof_batches (batch_id, merkle_root, signature, created_at, event_count)
72
+ VALUES (@batchId, @merkleRoot, @signature, @createdAt, @eventCount)
73
73
  `),
74
- insertCommitment: this.db.prepare(`
75
- INSERT INTO proof_commitments (id, hash, timestamp, batch_id, event_type, entity_id, payload, correlation_id)
76
- VALUES (@id, @hash, @timestamp, @batchId, @eventType, @entityId, @payload, @correlationId)
74
+ insertCommitment: this.db.prepare(`
75
+ INSERT INTO proof_commitments (id, hash, timestamp, batch_id, event_type, entity_id, payload, correlation_id)
76
+ VALUES (@id, @hash, @timestamp, @batchId, @eventType, @entityId, @payload, @correlationId)
77
77
  `),
78
- getBatch: this.db.prepare(`
79
- SELECT batch_id, merkle_root, signature, created_at, event_count
80
- FROM proof_batches
81
- WHERE batch_id = ?
78
+ getBatch: this.db.prepare(`
79
+ SELECT batch_id, merkle_root, signature, created_at, event_count
80
+ FROM proof_batches
81
+ WHERE batch_id = ?
82
82
  `),
83
- getCommitment: this.db.prepare(`
84
- SELECT id, hash, timestamp, batch_id, event_type, entity_id, payload, correlation_id
85
- FROM proof_commitments
86
- WHERE id = ?
83
+ getCommitment: this.db.prepare(`
84
+ SELECT id, hash, timestamp, batch_id, event_type, entity_id, payload, correlation_id
85
+ FROM proof_commitments
86
+ WHERE id = ?
87
87
  `),
88
- getCommitmentsForEntity: this.db.prepare(`
89
- SELECT id, hash, timestamp, batch_id, event_type, entity_id, payload, correlation_id
90
- FROM proof_commitments
91
- WHERE entity_id = ?
92
- ORDER BY timestamp DESC
88
+ getCommitmentsForEntity: this.db.prepare(`
89
+ SELECT id, hash, timestamp, batch_id, event_type, entity_id, payload, correlation_id
90
+ FROM proof_commitments
91
+ WHERE entity_id = ?
92
+ ORDER BY timestamp DESC
93
93
  `),
94
94
  };
95
95
  }
@@ -135,10 +135,10 @@ export class SQLiteProofStore {
135
135
  if (!row)
136
136
  return null;
137
137
  // Get all commitments for this batch
138
- const commitmentRows = this.db.prepare(`
139
- SELECT id, hash, timestamp, event_type, entity_id, payload, correlation_id
140
- FROM proof_commitments
141
- WHERE batch_id = ?
138
+ const commitmentRows = this.db.prepare(`
139
+ SELECT id, hash, timestamp, event_type, entity_id, payload, correlation_id
140
+ FROM proof_commitments
141
+ WHERE batch_id = ?
142
142
  `).all(batchId);
143
143
  const commitments = commitmentRows.map((c) => ({
144
144
  id: c.id,