@hardkas/core 0.5.5-alpha → 0.6.0-alpha

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/dist/index.d.ts CHANGED
@@ -70,7 +70,7 @@ declare const asEventId: (id: string) => EventId;
70
70
  declare const asCorrelationId: (id: string) => CorrelationId;
71
71
  declare const asKaspaAddress: (addr: string) => KaspaAddress;
72
72
  declare const asRpcEndpointId: (id: string) => RpcEndpointId;
73
- declare const asNetworkId: (id: string) => NetworkId$1;
73
+ declare const asNetworkId: <T extends string>(id: T) => Brand<T, "NetworkId">;
74
74
  declare const asEventSequence: (seq: number) => EventSequence;
75
75
  declare const asDaaScore: (score: number | bigint) => DaaScore;
76
76
 
@@ -81,7 +81,7 @@ type EventDomain = "workflow" | "integrity" | "rpc" | "dag" | "replay" | "localn
81
81
  /**
82
82
  * HardKAS Core Event Kinds.
83
83
  */
84
- type EventKind = "workflow.plan.created" | "workflow.signed" | "workflow.submitted" | "workflow.receipt" | "workflow.started" | "workflow.completed" | "workflow.failed" | "integrity.hash_mismatch" | "integrity.schema_violation" | "integrity.lineage_break" | "integrity.violation" | "dag.conflict" | "dag.displacement" | "dag.sink_moved" | "rpc.health" | "rpc.error" | "rpc.stale" | "replay.divergence" | "replay.verified" | "localnet.started" | "localnet.stopped" | "l2.deposit.planned" | "l2.withdrawal.planned";
84
+ type EventKind = "workflow.plan.created" | "workflow.signed" | "workflow.submitted" | "workflow.receipt" | "workflow.started" | "workflow.completed" | "workflow.failed" | "integrity.hash_mismatch" | "integrity.schema_violation" | "integrity.lineage_break" | "integrity.violation" | "dag.conflict" | "dag.displacement" | "dag.sink_moved" | "rpc.health" | "rpc.error" | "rpc.stale" | "replay.divergence" | "replay.verified" | "localnet.started" | "localnet.stopped" | "l2.deposit.planned" | "l2.withdrawal.planned" | "artifact.written" | "artifact.indexed" | "artifact.corrupted" | "sqlite.commit" | "replay.invalidated" | "replay.completed" | "replay.excluded" | "sse.emitted" | "dashboard.cache_invalidated" | "dashboard.refetch_started" | "dashboard.refetch_completed" | "query_store.sync_started" | "query_store.sync_completed" | "lineage.verification_failed";
85
85
  /**
86
86
  * Payload mapping for each event kind.
87
87
  */
@@ -192,6 +192,60 @@ interface EventPayloadByKind {
192
192
  amount: bigint;
193
193
  from: string;
194
194
  };
195
+ "artifact.written": {
196
+ artifactId: ArtifactId;
197
+ path: string;
198
+ };
199
+ "artifact.indexed": {
200
+ artifactId: ArtifactId;
201
+ schema: string;
202
+ };
203
+ "artifact.corrupted": {
204
+ artifactId: ArtifactId;
205
+ path: string;
206
+ issue: string;
207
+ };
208
+ "sqlite.commit": {
209
+ transactionId: string;
210
+ rowCount: number;
211
+ };
212
+ "replay.invalidated": {
213
+ artifactId: ArtifactId;
214
+ reason: string;
215
+ };
216
+ "replay.completed": {
217
+ targetArtifactId: ArtifactId;
218
+ success: boolean;
219
+ };
220
+ "replay.excluded": {
221
+ artifactId: ArtifactId;
222
+ reason: string;
223
+ };
224
+ "sse.emitted": {
225
+ eventId: EventId;
226
+ channel: string;
227
+ };
228
+ "dashboard.cache_invalidated": {
229
+ key: string;
230
+ };
231
+ "dashboard.refetch_started": {
232
+ key: string;
233
+ };
234
+ "dashboard.refetch_completed": {
235
+ key: string;
236
+ success: boolean;
237
+ };
238
+ "query_store.sync_started": {
239
+ syncId: string;
240
+ };
241
+ "query_store.sync_completed": {
242
+ syncId: string;
243
+ stats: Record<string, number>;
244
+ };
245
+ "lineage.verification_failed": {
246
+ artifactId: ArtifactId;
247
+ missingParentId: ArtifactId;
248
+ };
195
249
  }
196
250
  /**
197
251
  * Formal Event Envelope (v1).
@@ -205,7 +259,10 @@ interface EventEnvelope<K extends EventKind = EventKind> {
205
259
  domain: EventDomain;
206
260
  kind: K;
207
261
  timestamp: string;
208
- sequence?: EventSequence | undefined;
262
+ emittedAt: string;
263
+ sequenceNumber: EventSequence;
264
+ globalOffset?: number;
265
+ sourceSubsystem: string;
209
266
  workflowId: WorkflowId;
210
267
  correlationId: CorrelationId;
211
268
  causationId?: EventId;
@@ -256,7 +313,9 @@ declare function createEventEnvelope<K extends EventKind>(params: {
256
313
  artifactId?: ArtifactId;
257
314
  txId?: TxId;
258
315
  eventId?: EventId;
259
- sequence?: EventSequence;
316
+ sequenceNumber: EventSequence;
317
+ globalOffset?: number;
318
+ sourceSubsystem: string;
260
319
  }): EventEnvelope<K>;
261
320
  /**
262
321
  * Lightweight runtime validation for event envelopes.
@@ -334,6 +393,37 @@ interface CorruptionIssue {
334
393
  */
335
394
  declare function formatCorruptionIssue(issue: CorruptionIssue): string;
336
395
 
396
+ type IntegrityStatus = "verified" | "corrupted" | "invalid_json" | "unknown";
397
+ /**
398
+ * Explains the causal origin and validation state of a derived value.
399
+ */
400
+ interface StateProvenance {
401
+ /**
402
+ * The architectural authority that asserts this state (e.g. "query-store projection", "filesystem artifact", "memory cache")
403
+ */
404
+ authority: string;
405
+ /**
406
+ * The source artifact ID from which this state was derived (if applicable)
407
+ */
408
+ derivedFrom?: ArtifactId;
409
+ /**
410
+ * The absolute or relative file path of the source artifact
411
+ */
412
+ originalPath?: string;
413
+ /**
414
+ * Current deterministic integrity of the source
415
+ */
416
+ integrity: IntegrityStatus;
417
+ /**
418
+ * The replay scope indicating where this state is valid (e.g., "local-only", "global")
419
+ */
420
+ replayScope: "local-only" | "global" | "unknown";
421
+ /**
422
+ * True if this state has been independently verified against network consensus
423
+ */
424
+ consensusValidated: boolean;
425
+ }
426
+
337
427
  /**
338
428
  * HardKAS Lock Metadata schema v1
339
429
  */
@@ -406,16 +496,94 @@ declare function clearLock(rootDir: string, name: string, options?: {
406
496
  reason?: string;
407
497
  };
408
498
 
499
+ interface StructuralDiff {
500
+ missingArtifacts: string[];
501
+ excludedArtifacts: string[];
502
+ missingProjections: string[];
503
+ }
504
+ interface DeterministicDiff {
505
+ stateRootDiverged: boolean;
506
+ lineageDiverged: boolean;
507
+ graphDiverged: boolean;
508
+ differences: Array<{
509
+ path: string;
510
+ a: any;
511
+ b: any;
512
+ }>;
513
+ }
514
+ interface RuntimeNoiseDiff {
515
+ timestampShifts: Array<{
516
+ path: string;
517
+ shiftMs: number;
518
+ }>;
519
+ eventOrderingShifts: string[];
520
+ metadataDrift: string[];
521
+ }
522
+ interface LayeredReplayDiff {
523
+ schema: "hardkas.replayDiff.v1";
524
+ structural: StructuralDiff;
525
+ deterministic: DeterministicDiff;
526
+ observational: RuntimeNoiseDiff;
527
+ }
528
+ declare function diffReplays(replayA: any, replayB: any): LayeredReplayDiff;
529
+
530
+ interface SnapshotManifest {
531
+ snapshotVersion: number;
532
+ createdAt: string;
533
+ hardkasVersion: string;
534
+ stateAuthority: "filesystem";
535
+ projectionAuthority: "sqlite";
536
+ deterministicScope: "local-only" | "consensus-validated";
537
+ consensusValidated: boolean;
538
+ includedArtifacts: number;
539
+ excludedArtifacts: number;
540
+ corruptedArtifacts: number;
541
+ }
542
+ interface CreateSnapshotOptions {
543
+ hardkasDir: string;
544
+ outputDir: string;
545
+ deterministicScope?: "local-only" | "consensus-validated";
546
+ }
547
+ declare function createSnapshot(options: CreateSnapshotOptions): Promise<SnapshotManifest>;
548
+ declare function readSnapshotManifest(snapshotDir: string): Promise<SnapshotManifest>;
549
+
550
+ /**
551
+ * Deterministic comparison utility for cross-platform string sorting.
552
+ * Avoids localeCompare() which is dependent on the host machine's ICU version and OS locale.
553
+ */
554
+ declare function deterministicCompare(a: string, b: string): number;
555
+
556
+ interface DeterministicClock {
557
+ now(): number;
558
+ }
559
+ interface DeterministicRandom {
560
+ next(): number;
561
+ }
562
+ interface IdProvider {
563
+ execution(): string;
564
+ workflow(): string;
565
+ }
566
+ interface RuntimeContext {
567
+ clock: DeterministicClock;
568
+ random: DeterministicRandom;
569
+ ids: IdProvider;
570
+ }
571
+ /**
572
+ * A default system runtime context (for non-deterministic contexts like dev server or CLI entry points)
573
+ * This should NOT be used directly in pure canonical domain logic (e.g. artifacts, replays).
574
+ */
575
+ declare const systemRuntimeContext: RuntimeContext;
576
+
409
577
  declare const SOMPI_PER_KAS = 100000000n;
410
- declare const kaspaNetworkIdSchema: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet"]>;
578
+ declare const kaspaNetworkIdSchema: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet", "simulated"]>;
411
579
  type NetworkId = Brand<z.infer<typeof kaspaNetworkIdSchema>, "NetworkId">;
412
580
  declare const executionModeSchema: z.ZodEnum<["simulated", "real", "readonly"]>;
413
581
  type ExecutionMode = z.infer<typeof executionModeSchema>;
414
- declare const artifactTypeSchema: z.ZodEnum<["txPlan", "signedTx", "txReceipt", "txTrace", "snapshot"]>;
582
+ declare const artifactTypeSchema: z.ZodEnum<["txPlan", "signedTx", "txReceipt", "txTrace", "snapshot", "workflow.v1"]>;
415
583
  type ArtifactType = z.infer<typeof artifactTypeSchema>;
416
- declare const NetworkIdSchema: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet"]>;
584
+ declare const NetworkIdSchema: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet", "simulated"]>;
417
585
  declare const ExecutionModeSchema: z.ZodEnum<["simulated", "real", "readonly"]>;
418
- declare const ArtifactTypeSchema: z.ZodEnum<["txPlan", "signedTx", "txReceipt", "txTrace", "snapshot"]>;
586
+ declare const ArtifactTypeSchema: z.ZodEnum<["txPlan", "signedTx", "txReceipt", "txTrace", "snapshot", "workflow.v1"]>;
419
587
  declare const hardkasConfigSchema: z.ZodObject<{
420
588
  project: z.ZodObject<{
421
589
  name: z.ZodString;
@@ -428,13 +596,13 @@ declare const hardkasConfigSchema: z.ZodObject<{
428
596
  root: string;
429
597
  }>;
430
598
  network: z.ZodObject<{
431
- id: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet"]>;
599
+ id: z.ZodEnum<["mainnet", "testnet-10", "testnet-11", "testnet-12", "simnet", "simnet-1", "devnet", "simulated"]>;
432
600
  rpcUrl: z.ZodOptional<z.ZodString>;
433
601
  }, "strip", z.ZodTypeAny, {
434
- id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet";
602
+ id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet" | "simulated";
435
603
  rpcUrl?: string | undefined;
436
604
  }, {
437
- id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet";
605
+ id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet" | "simulated";
438
606
  rpcUrl?: string | undefined;
439
607
  }>;
440
608
  localnet: z.ZodDefault<z.ZodObject<{
@@ -453,7 +621,7 @@ declare const hardkasConfigSchema: z.ZodObject<{
453
621
  root: string;
454
622
  };
455
623
  network: {
456
- id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet";
624
+ id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet" | "simulated";
457
625
  rpcUrl?: string | undefined;
458
626
  };
459
627
  localnet: {
@@ -466,7 +634,7 @@ declare const hardkasConfigSchema: z.ZodObject<{
466
634
  root: string;
467
635
  };
468
636
  network: {
469
- id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet";
637
+ id: "mainnet" | "testnet-10" | "testnet-11" | "testnet-12" | "simnet" | "simnet-1" | "devnet" | "simulated";
470
638
  rpcUrl?: string | undefined;
471
639
  };
472
640
  localnet?: {
@@ -496,4 +664,4 @@ declare function parseHardkasConfig(input: unknown): HardkasConfig;
496
664
  declare function parseKasToSompi(input: string): bigint;
497
665
  declare function formatSompi(amountSompi: bigint): string;
498
666
 
499
- export { type AcquireLockArgs, type ArtifactId, type ArtifactType, ArtifactTypeSchema, type Brand, type Branded, type ContentHash, type CoreEvent, type CoreEventListener, type CorrelationId, type CorruptionCode, type CorruptionIssue, type CorruptionSeverity, type DaaScore, type EventDomain, type EventEnvelope, type EventId, type EventKind, type EventPayloadByKind, type EventSequence, type ExecutionMode, ExecutionModeSchema, type HardkasConfig, HardkasError, type InvariantDomain, type InvariantSeverity, InvariantViolationError, type KaspaAddress, LOCK_ORDER, type LineageId, type LockHandle, type LockMetadata, type NetworkId, NetworkIdSchema, type RpcEndpointId, SOMPI_PER_KAS, type StampedEvent, type TxId, type UnknownEventPayload, type WorkflowId, type WriteFileAtomicOptions, acquireLock, artifactTypeSchema, asArtifactId, asContentHash, asCorrelationId, asDaaScore, asEventId, asEventSequence, asKaspaAddress, asLineageId, asNetworkId, asRpcEndpointId, asTxId, asWorkflowId, clearLock, coreEvents, createEventEnvelope, executionModeSchema, formatCorruptionIssue, formatSompi, hardkasConfigSchema, isProcessAlive, kaspaNetworkIdSchema, listLocks, maskSecrets, parseHardkasConfig, parseKasToSompi, redactSecret, validateEventEnvelope, withLock, withLocks, writeFileAtomic, writeFileAtomicSync };
667
+ export { type AcquireLockArgs, type ArtifactId, type ArtifactType, ArtifactTypeSchema, type Brand, type Branded, type ContentHash, type CoreEvent, type CoreEventListener, type CorrelationId, type CorruptionCode, type CorruptionIssue, type CorruptionSeverity, type CreateSnapshotOptions, type DaaScore, type DeterministicClock, type DeterministicDiff, type DeterministicRandom, type EventDomain, type EventEnvelope, type EventId, type EventKind, type EventPayloadByKind, type EventSequence, type ExecutionMode, ExecutionModeSchema, type HardkasConfig, HardkasError, type IdProvider, type IntegrityStatus, type InvariantDomain, type InvariantSeverity, InvariantViolationError, type KaspaAddress, LOCK_ORDER, type LayeredReplayDiff, type LineageId, type LockHandle, type LockMetadata, type NetworkId, NetworkIdSchema, type RpcEndpointId, type RuntimeContext, type RuntimeNoiseDiff, SOMPI_PER_KAS, type SnapshotManifest, type StampedEvent, type StateProvenance, type StructuralDiff, type TxId, type UnknownEventPayload, type WorkflowId, type WriteFileAtomicOptions, acquireLock, artifactTypeSchema, asArtifactId, asContentHash, asCorrelationId, asDaaScore, asEventId, asEventSequence, asKaspaAddress, asLineageId, asNetworkId, asRpcEndpointId, asTxId, asWorkflowId, clearLock, coreEvents, createEventEnvelope, createSnapshot, deterministicCompare, diffReplays, executionModeSchema, formatCorruptionIssue, formatSompi, hardkasConfigSchema, isProcessAlive, kaspaNetworkIdSchema, listLocks, maskSecrets, parseHardkasConfig, parseKasToSompi, readSnapshotManifest, redactSecret, systemRuntimeContext, validateEventEnvelope, withLock, withLocks, writeFileAtomic, writeFileAtomicSync };
package/dist/index.js CHANGED
@@ -37,13 +37,16 @@ var CoreEventBus = class {
37
37
  };
38
38
  var coreEvents = new CoreEventBus();
39
39
  function createEventEnvelope(params) {
40
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
40
41
  return {
41
42
  schema: "hardkas.event",
42
43
  version: "1.0.0",
43
44
  eventId: params.eventId || crypto.randomUUID(),
44
45
  domain: params.domain,
45
46
  kind: params.kind,
46
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
47
+ timestamp,
48
+ emittedAt: timestamp,
49
+ sourceSubsystem: params.sourceSubsystem,
47
50
  workflowId: params.workflowId,
48
51
  correlationId: params.correlationId,
49
52
  causationId: params.causationId,
@@ -51,7 +54,8 @@ function createEventEnvelope(params) {
51
54
  txId: params.txId,
52
55
  networkId: params.networkId,
53
56
  payload: params.payload,
54
- ...params.sequence !== void 0 ? { sequence: params.sequence } : {}
57
+ sequenceNumber: params.sequenceNumber,
58
+ globalOffset: params.globalOffset
55
59
  };
56
60
  }
57
61
  function validateEventEnvelope(event) {
@@ -114,10 +118,11 @@ function redactSecret(value) {
114
118
  // src/fs.ts
115
119
  import fs from "fs";
116
120
  import path from "path";
121
+ import crypto2 from "crypto";
117
122
  async function writeFileAtomic(targetPath, data, options = {}) {
118
123
  const dir = path.dirname(targetPath);
119
124
  const base = path.basename(targetPath);
120
- const tempPath = path.join(dir, `.tmp.${base}.${Math.random().toString(36).slice(2)}`);
125
+ const tempPath = path.join(dir, `.tmp.${base}.${crypto2.randomUUID()}`);
121
126
  let fd = null;
122
127
  try {
123
128
  if (!fs.existsSync(dir)) {
@@ -179,7 +184,7 @@ async function writeFileAtomic(targetPath, data, options = {}) {
179
184
  function writeFileAtomicSync(targetPath, data, options = {}) {
180
185
  const dir = path.dirname(targetPath);
181
186
  const base = path.basename(targetPath);
182
- const tempPath = path.join(dir, `.tmp.${base}.${Math.random().toString(36).slice(2)}`);
187
+ const tempPath = path.join(dir, `.tmp.${base}.${crypto2.randomUUID()}`);
183
188
  let fd = null;
184
189
  try {
185
190
  if (!fs.existsSync(dir)) {
@@ -420,6 +425,150 @@ function clearLock(rootDir, name, options = {}) {
420
425
  return { cleared: true };
421
426
  }
422
427
 
428
+ // src/replay.ts
429
+ function diffReplays(replayA, replayB) {
430
+ const diff = {
431
+ schema: "hardkas.replayDiff.v1",
432
+ structural: {
433
+ missingArtifacts: [],
434
+ excludedArtifacts: [],
435
+ missingProjections: []
436
+ },
437
+ deterministic: {
438
+ stateRootDiverged: false,
439
+ lineageDiverged: false,
440
+ graphDiverged: false,
441
+ differences: []
442
+ },
443
+ observational: {
444
+ timestampShifts: [],
445
+ eventOrderingShifts: [],
446
+ metadataDrift: []
447
+ }
448
+ };
449
+ if (replayA.artifacts?.length !== replayB.artifacts?.length) {
450
+ diff.structural.missingArtifacts.push("artifact_count_mismatch");
451
+ }
452
+ const stateA = replayA.stateRoot || replayA.postStateHash;
453
+ const stateB = replayB.stateRoot || replayB.postStateHash;
454
+ if (stateA !== stateB) {
455
+ diff.deterministic.stateRootDiverged = true;
456
+ diff.deterministic.differences.push({
457
+ path: "stateRoot",
458
+ a: stateA,
459
+ b: stateB
460
+ });
461
+ }
462
+ if (replayA.amountSompi !== void 0 && replayB.amountSompi !== void 0 && replayA.amountSompi !== replayB.amountSompi) {
463
+ diff.deterministic.differences.push({
464
+ path: "amountSompi",
465
+ a: replayA.amountSompi,
466
+ b: replayB.amountSompi
467
+ });
468
+ }
469
+ const tsA = replayA.timestamp || replayA.createdAt;
470
+ const tsB = replayB.timestamp || replayB.createdAt;
471
+ if (tsA && tsB) {
472
+ const timeA = new Date(tsA).getTime();
473
+ const timeB = new Date(tsB).getTime();
474
+ if (timeA !== timeB) {
475
+ diff.observational.timestampShifts.push({ path: "timestamp", shiftMs: Math.abs(timeA - timeB) });
476
+ }
477
+ }
478
+ return diff;
479
+ }
480
+
481
+ // src/snapshot.ts
482
+ import fs3 from "fs/promises";
483
+ import path3 from "path";
484
+ async function createSnapshot(options) {
485
+ const { hardkasDir, outputDir, deterministicScope = "local-only" } = options;
486
+ await fs3.mkdir(outputDir, { recursive: true });
487
+ await fs3.mkdir(path3.join(outputDir, "artifacts"), { recursive: true });
488
+ await fs3.mkdir(path3.join(outputDir, "projections"), { recursive: true });
489
+ await fs3.mkdir(path3.join(outputDir, "events"), { recursive: true });
490
+ await fs3.mkdir(path3.join(outputDir, "replay"), { recursive: true });
491
+ await fs3.mkdir(path3.join(outputDir, "metadata"), { recursive: true });
492
+ let included = 0;
493
+ let excluded = 0;
494
+ let corrupted = 0;
495
+ const artifactsDir = path3.join(hardkasDir, "artifacts");
496
+ try {
497
+ const list = await fs3.readdir(artifactsDir);
498
+ for (const f of list) {
499
+ if (f.endsWith(".json")) {
500
+ const src = path3.join(artifactsDir, f);
501
+ const dest = path3.join(outputDir, "artifacts", f);
502
+ try {
503
+ const content = await fs3.readFile(src, "utf-8");
504
+ const parsed = JSON.parse(content);
505
+ if (parsed.schema && parsed.schema.startsWith("hardkas.")) {
506
+ await fs3.copyFile(src, dest);
507
+ included++;
508
+ } else {
509
+ excluded++;
510
+ }
511
+ } catch {
512
+ corrupted++;
513
+ }
514
+ }
515
+ }
516
+ } catch {
517
+ }
518
+ try {
519
+ const eventsLog = path3.join(hardkasDir, "events.jsonl");
520
+ await fs3.copyFile(eventsLog, path3.join(outputDir, "events", "events.jsonl"));
521
+ } catch {
522
+ }
523
+ try {
524
+ const dbPath = path3.join(hardkasDir, "store.db");
525
+ await fs3.copyFile(dbPath, path3.join(outputDir, "projections", "store.db"));
526
+ } catch {
527
+ }
528
+ const manifest = {
529
+ snapshotVersion: 1,
530
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
531
+ hardkasVersion: "0.6.0-alpha",
532
+ stateAuthority: "filesystem",
533
+ projectionAuthority: "sqlite",
534
+ deterministicScope,
535
+ consensusValidated: deterministicScope === "consensus-validated",
536
+ includedArtifacts: included,
537
+ excludedArtifacts: excluded,
538
+ corruptedArtifacts: corrupted
539
+ };
540
+ await fs3.writeFile(
541
+ path3.join(outputDir, "manifest.json"),
542
+ JSON.stringify(manifest, null, 2),
543
+ "utf-8"
544
+ );
545
+ return manifest;
546
+ }
547
+ async function readSnapshotManifest(snapshotDir) {
548
+ const manifestPath = path3.join(snapshotDir, "manifest.json");
549
+ const content = await fs3.readFile(manifestPath, "utf-8");
550
+ return JSON.parse(content);
551
+ }
552
+
553
+ // src/deterministic.ts
554
+ function deterministicCompare(a, b) {
555
+ return a < b ? -1 : a > b ? 1 : 0;
556
+ }
557
+
558
+ // src/runtime-context.ts
559
+ var systemRuntimeContext = {
560
+ clock: {
561
+ now: () => Date.now()
562
+ },
563
+ random: {
564
+ next: () => Math.random()
565
+ },
566
+ ids: {
567
+ execution: () => `exec_${Date.now().toString(36)}`,
568
+ workflow: () => `wf_${Date.now().toString(36)}`
569
+ }
570
+ };
571
+
423
572
  // src/index.ts
424
573
  var SOMPI_PER_KAS = 100000000n;
425
574
  var kaspaNetworkIdSchema = z.enum([
@@ -429,7 +578,8 @@ var kaspaNetworkIdSchema = z.enum([
429
578
  "testnet-12",
430
579
  "simnet",
431
580
  "simnet-1",
432
- "devnet"
581
+ "devnet",
582
+ "simulated"
433
583
  ]);
434
584
  var executionModeSchema = z.enum([
435
585
  "simulated",
@@ -441,7 +591,8 @@ var artifactTypeSchema = z.enum([
441
591
  "signedTx",
442
592
  "txReceipt",
443
593
  "txTrace",
444
- "snapshot"
594
+ "snapshot",
595
+ "workflow.v1"
445
596
  ]);
446
597
  var NetworkIdSchema = kaspaNetworkIdSchema;
447
598
  var ExecutionModeSchema = executionModeSchema;
@@ -534,6 +685,9 @@ export {
534
685
  clearLock,
535
686
  coreEvents,
536
687
  createEventEnvelope,
688
+ createSnapshot,
689
+ deterministicCompare,
690
+ diffReplays,
537
691
  executionModeSchema,
538
692
  formatCorruptionIssue,
539
693
  formatSompi,
@@ -544,7 +698,9 @@ export {
544
698
  maskSecrets,
545
699
  parseHardkasConfig,
546
700
  parseKasToSompi,
701
+ readSnapshotManifest,
547
702
  redactSecret,
703
+ systemRuntimeContext,
548
704
  validateEventEnvelope,
549
705
  withLock,
550
706
  withLocks,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/core",
3
- "version": "0.5.5-alpha",
3
+ "version": "0.6.0-alpha",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",