@hardkas/artifacts 0.8.3-alpha → 0.8.5-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
@@ -843,6 +843,7 @@ declare const TxPlanSchema: z.ZodObject<{
843
843
  rpcUrl: z.ZodOptional<z.ZodString>;
844
844
  networkProfileRef: z.ZodOptional<z.ZodString>;
845
845
  policyRef: z.ZodOptional<z.ZodString>;
846
+ policyRefs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
846
847
  assumptionRef: z.ZodOptional<z.ZodString>;
847
848
  }, "strip", z.ZodTypeAny, {
848
849
  version: "1.0.0-alpha";
@@ -905,6 +906,7 @@ declare const TxPlanSchema: z.ZodObject<{
905
906
  rpcUrl?: string | undefined;
906
907
  networkProfileRef?: string | undefined;
907
908
  policyRef?: string | undefined;
909
+ policyRefs?: string[] | undefined;
908
910
  assumptionRef?: string | undefined;
909
911
  }, {
910
912
  version: "1.0.0-alpha";
@@ -967,6 +969,7 @@ declare const TxPlanSchema: z.ZodObject<{
967
969
  rpcUrl?: string | undefined;
968
970
  networkProfileRef?: string | undefined;
969
971
  policyRef?: string | undefined;
972
+ policyRefs?: string[] | undefined;
970
973
  assumptionRef?: string | undefined;
971
974
  }>;
972
975
  declare const DagContextSchema: z.ZodObject<{
@@ -2670,6 +2673,7 @@ interface TxPlanArtifact extends BaseArtifact<"txPlan"> {
2670
2673
  } | undefined;
2671
2674
  networkProfileRef?: string | undefined;
2672
2675
  policyRef?: string | undefined;
2676
+ policyRefs?: string[] | undefined;
2673
2677
  assumptionRef?: string | undefined;
2674
2678
  }
2675
2679
  interface SignedTxArtifact extends BaseArtifact<"signedTx"> {
@@ -2894,6 +2898,9 @@ interface VerificationContext {
2894
2898
  strict?: boolean;
2895
2899
  networkId?: NetworkId;
2896
2900
  parent?: unknown;
2901
+ artifactsDir?: string;
2902
+ enforceMetadata?: boolean;
2903
+ resolveArtifact?: (id: string) => any;
2897
2904
  }
2898
2905
  type VerificationSeverity = CorruptionSeverity | "info" | "critical";
2899
2906
  type VerificationIssue = {
@@ -2918,7 +2925,12 @@ type ArtifactVerificationResult = {
2918
2925
  */
2919
2926
  declare function sortUtxosByOutpoint<T>(utxos: T[]): T[];
2920
2927
  /**
2921
- * Verifies an artifact's integrity.
2928
+ * Verifies an artifact's integrity synchronously.
2929
+ * Can take a raw object or a file path.
2930
+ */
2931
+ declare function verifyArtifactIntegritySync(artifactOrPath: unknown): ArtifactVerificationResult;
2932
+ /**
2933
+ * Verifies an artifact's integrity asynchronously.
2922
2934
  * Can take a raw object or a file path.
2923
2935
  */
2924
2936
  declare function verifyArtifactIntegrity(artifactOrPath: unknown): Promise<ArtifactVerificationResult>;
@@ -3413,4 +3425,4 @@ declare function listDeployments(rootDir: string, networkId?: string): Promise<D
3413
3425
  declare function updateDeployment(rootDir: string, networkId: string, label: string, update: Partial<DeploymentRecord>): Promise<DeploymentRecord>;
3414
3426
  declare function deleteDeployment(rootDir: string, networkId: string, label: string): Promise<boolean>;
3415
3427
 
3416
- export { ARTIFACT_SCHEMAS, ARTIFACT_VERSION, AccountRefSchema, type ArtifactDiff, type ArtifactExplanation, ArtifactLineageSchema, type ArtifactLookup, type ArtifactPayload, type ArtifactValidationResult, type ArtifactVerificationResult, type Assumption, type AssumptionArtifact, type AssumptionLevel, AssumptionSchema, type BaseArtifact, BaseArtifactSchema, BasicCorrelationInvariant, BasicLineageInvariant, CURRENT_HASH_VERSION, type Clock, type CreateTxPlanArtifactOptions, type DagContext, DagContextSchema, type DeploymentIndex, type DeploymentRecord, type DeploymentSummary, type DiffEntry, type DraftArtifact, type FeeAuditResult, HARDKAS_VERSION, type HardkasArtifactBase, type HardkasArtifactMode, type HardkasArtifactSchema, HashInvariant, type IgraSignedTxArtifact, type IgraTxPlanArtifact, type IgraTxReceiptArtifact, type IgraTxRequestArtifact, type Invariant, type InvariantContext, type InvariantViolation, InvariantWatcher, LifecycleInvariant, type LineageOptions, type LineageValidationResult, LocalnetUtxoSchemaV2, type MigrationReceipt, type MigrationReceiptArtifact, MigrationReceiptSchema, MigrationRequiredError, type MigrationResult, type MigrationStep, NetworkInvariant, type NetworkProfile, type NetworkProfileArtifact, NetworkProfileSchema, type Policy, type PolicyArtifact, PolicySchema, ReplayInvariant, type RuntimeSession, RuntimeSessionSchema, SEMANTIC_EXCLUSIONS, STRICT_PATH_KEYS, SchemaInvariant, type ScriptCapability, ScriptCapabilitySchema, ScriptMetadataSchema, SignatureEntrySchema, SignatureMetadataEntrySchema, type SignedTx, type SignedTxArtifact, type SignedTxArtifactV1, SignedTxSchema, type Snapshot, type SnapshotArtifact, SnapshotSchema, type TxOutputArtifact, type TxPlan, type TxPlanArtifact, type TxPlanArtifactV1, TxPlanSchema, type TxReceipt, type TxReceiptArtifact, type TxReceiptArtifactV1, TxReceiptSchema, type TxTrace, type TxTraceArtifact, type TxTraceArtifactV1, TxTraceSchema, type UtxoArtifact, type VerificationContext, type VerificationIssue, type VerificationSeverity, type WatcherOptions, type Workflow, type WorkflowArtifact, WorkflowSchema, assertDecimalBigIntString, assertEvmAddress, assertEvmTxHash, assertHexData, assertValidIgraSignedTxArtifact, assertValidIgraTxPlanArtifact, assertValidIgraTxReceiptArtifact, assertValidSignedTxArtifact, assertValidTxPlanArtifact, assertValidTxReceiptArtifact, bigIntReplacer, calculateContentHash, canMigrate, canonicalStringify, createDeploymentRecord, createIgraDeployPlanId, createIgraPlanId, createIgraSignedId, createSimulatedSignedTxArtifact, createSimulatedTxReceipt, createTxPlanArtifact, defaultClock, deleteDeployment, detectArtifactVersion, diffArtifacts, explainArtifact, formatSignedTxArtifact, formatTxPlanArtifact, formatTxReceiptArtifact, generateMigrationReceipt, getBroadcastableSignedTransaction, getDefaultL2ReceiptsDir, getDefaultReceiptPath, getL2ReceiptPath, getMigrationPath, getRegisteredMigrationSteps, isIgraTxPlanArtifact, listDeployments, listIgraTxReceiptArtifacts, loadDeployment, loadIgraTxReceiptArtifact, migrateArtifactPayload, migrateToCanonical, readArtifact, readSignedTxArtifact, readTxPlanArtifact, readTxReceiptArtifact, recomputeMass, registerMigrationStep, saveDeployment, saveIgraTxReceiptArtifact, sortUtxosByOutpoint, txOutputFromArtifact, txOutputToArtifact, updateDeployment, updateDeploymentStatus, utxoFromArtifact, utxoToArtifact, validateArtifact, validateIgraSignedTxArtifact, validateIgraTxPlanArtifact, validateIgraTxReceiptArtifact, validateSignedTxArtifact, validateTxPlanArtifact, validateTxReceiptArtifact, verifyArtifact, verifyArtifactFile, verifyArtifactIntegrity, verifyArtifactReplay, verifyArtifactSemantics, verifyFeeSemantics, verifyLineage, writeArtifact };
3428
+ export { ARTIFACT_SCHEMAS, ARTIFACT_VERSION, AccountRefSchema, type ArtifactDiff, type ArtifactExplanation, ArtifactLineageSchema, type ArtifactLookup, type ArtifactPayload, type ArtifactValidationResult, type ArtifactVerificationResult, type Assumption, type AssumptionArtifact, type AssumptionLevel, AssumptionSchema, type BaseArtifact, BaseArtifactSchema, BasicCorrelationInvariant, BasicLineageInvariant, CURRENT_HASH_VERSION, type Clock, type CreateTxPlanArtifactOptions, type DagContext, DagContextSchema, type DeploymentIndex, type DeploymentRecord, type DeploymentSummary, type DiffEntry, type DraftArtifact, type FeeAuditResult, HARDKAS_VERSION, type HardkasArtifactBase, type HardkasArtifactMode, type HardkasArtifactSchema, HashInvariant, type IgraSignedTxArtifact, type IgraTxPlanArtifact, type IgraTxReceiptArtifact, type IgraTxRequestArtifact, type Invariant, type InvariantContext, type InvariantViolation, InvariantWatcher, LifecycleInvariant, type LineageOptions, type LineageValidationResult, LocalnetUtxoSchemaV2, type MigrationReceipt, type MigrationReceiptArtifact, MigrationReceiptSchema, MigrationRequiredError, type MigrationResult, type MigrationStep, NetworkInvariant, type NetworkProfile, type NetworkProfileArtifact, NetworkProfileSchema, type Policy, type PolicyArtifact, PolicySchema, ReplayInvariant, type RuntimeSession, RuntimeSessionSchema, SEMANTIC_EXCLUSIONS, STRICT_PATH_KEYS, SchemaInvariant, type ScriptCapability, ScriptCapabilitySchema, ScriptMetadataSchema, SignatureEntrySchema, SignatureMetadataEntrySchema, type SignedTx, type SignedTxArtifact, type SignedTxArtifactV1, SignedTxSchema, type Snapshot, type SnapshotArtifact, SnapshotSchema, type TxOutputArtifact, type TxPlan, type TxPlanArtifact, type TxPlanArtifactV1, TxPlanSchema, type TxReceipt, type TxReceiptArtifact, type TxReceiptArtifactV1, TxReceiptSchema, type TxTrace, type TxTraceArtifact, type TxTraceArtifactV1, TxTraceSchema, type UtxoArtifact, type VerificationContext, type VerificationIssue, type VerificationSeverity, type WatcherOptions, type Workflow, type WorkflowArtifact, WorkflowSchema, assertDecimalBigIntString, assertEvmAddress, assertEvmTxHash, assertHexData, assertValidIgraSignedTxArtifact, assertValidIgraTxPlanArtifact, assertValidIgraTxReceiptArtifact, assertValidSignedTxArtifact, assertValidTxPlanArtifact, assertValidTxReceiptArtifact, bigIntReplacer, calculateContentHash, canMigrate, canonicalStringify, createDeploymentRecord, createIgraDeployPlanId, createIgraPlanId, createIgraSignedId, createSimulatedSignedTxArtifact, createSimulatedTxReceipt, createTxPlanArtifact, defaultClock, deleteDeployment, detectArtifactVersion, diffArtifacts, explainArtifact, formatSignedTxArtifact, formatTxPlanArtifact, formatTxReceiptArtifact, generateMigrationReceipt, getBroadcastableSignedTransaction, getDefaultL2ReceiptsDir, getDefaultReceiptPath, getL2ReceiptPath, getMigrationPath, getRegisteredMigrationSteps, isIgraTxPlanArtifact, listDeployments, listIgraTxReceiptArtifacts, loadDeployment, loadIgraTxReceiptArtifact, migrateArtifactPayload, migrateToCanonical, readArtifact, readSignedTxArtifact, readTxPlanArtifact, readTxReceiptArtifact, recomputeMass, registerMigrationStep, saveDeployment, saveIgraTxReceiptArtifact, sortUtxosByOutpoint, txOutputFromArtifact, txOutputToArtifact, updateDeployment, updateDeploymentStatus, utxoFromArtifact, utxoToArtifact, validateArtifact, validateIgraSignedTxArtifact, validateIgraTxPlanArtifact, validateIgraTxReceiptArtifact, validateSignedTxArtifact, validateTxPlanArtifact, validateTxReceiptArtifact, verifyArtifact, verifyArtifactFile, verifyArtifactIntegrity, verifyArtifactIntegritySync, verifyArtifactReplay, verifyArtifactSemantics, verifyFeeSemantics, verifyLineage, writeArtifact };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@hardkas/artifacts",
4
- version: "0.8.3-alpha",
4
+ version: "0.8.5-alpha",
5
5
  type: "module",
6
6
  license: "MIT",
7
7
  author: "Javier Rodriguez",
@@ -20,7 +20,11 @@ var package_default = {
20
20
  "LICENSE"
21
21
  ],
22
22
  exports: {
23
- ".": "./dist/index.js"
23
+ ".": {
24
+ types: "./dist/index.d.ts",
25
+ import: "./dist/index.js",
26
+ default: "./dist/index.js"
27
+ }
24
28
  },
25
29
  types: "./dist/index.d.ts",
26
30
  scripts: {
@@ -38,7 +42,8 @@ var package_default = {
38
42
  tsup: "^8.3.5",
39
43
  typescript: "^5.6.3",
40
44
  vitest: "^2.1.4"
41
- }
45
+ },
46
+ main: "./dist/index.js"
42
47
  };
43
48
 
44
49
  // src/constants.ts
@@ -416,6 +421,7 @@ var TxPlanSchema = BaseArtifactSchema.extend({
416
421
  rpcUrl: z.string().optional(),
417
422
  networkProfileRef: z.string().optional(),
418
423
  policyRef: z.string().optional(),
424
+ policyRefs: z.array(z.string()).optional(),
419
425
  assumptionRef: z.string().optional()
420
426
  });
421
427
  var DagContextSchema = z.object({
@@ -581,6 +587,7 @@ var RuntimeSessionSchema = BaseArtifactSchema.extend({
581
587
 
582
588
  // src/verify.ts
583
589
  import fs from "fs";
590
+ import path from "path";
584
591
 
585
592
  // src/feeVerify.ts
586
593
  import {
@@ -815,15 +822,15 @@ function sortUtxosByOutpoint(utxos) {
815
822
  return deterministicCompare2(aId, bId);
816
823
  });
817
824
  }
818
- async function verifyArtifactIntegrity(artifactOrPath) {
825
+ function verifyArtifactIntegritySync(artifactOrPath) {
819
826
  const result = {
820
827
  ok: false,
821
828
  errors: [],
822
829
  issues: []
823
830
  };
824
- const addError = (code, message, path4) => {
831
+ const addError = (code, message, path5) => {
825
832
  result.errors.push(message);
826
- result.issues.push({ code, severity: "error", message, path: path4 });
833
+ result.issues.push({ code, severity: "error", message, path: path5 });
827
834
  };
828
835
  let artifact;
829
836
  try {
@@ -937,6 +944,37 @@ async function verifyArtifactIntegrity(artifactOrPath) {
937
944
  return result;
938
945
  }
939
946
  }
947
+ async function verifyArtifactIntegrity(artifactOrPath) {
948
+ return verifyArtifactIntegritySync(artifactOrPath);
949
+ }
950
+ function findFileByHash(hash, dirs) {
951
+ const shortHash = hash.startsWith("plan-") || hash.startsWith("signed-") ? hash : hash.slice(0, 16);
952
+ for (const dir of dirs) {
953
+ if (!fs.existsSync(dir)) continue;
954
+ try {
955
+ const files = fs.readdirSync(dir);
956
+ if (files.includes(`${hash}.json`)) {
957
+ return path.join(dir, `${hash}.json`);
958
+ }
959
+ for (const file of files) {
960
+ if (!file.endsWith(".json")) continue;
961
+ if (file.includes(hash) || file.includes(shortHash) || file.includes(hash.slice(0, 8))) {
962
+ const filePath = path.join(dir, file);
963
+ try {
964
+ const content = fs.readFileSync(filePath, "utf-8");
965
+ const obj = JSON.parse(content);
966
+ if (obj.contentHash === hash || obj.artifactId === hash || obj.planId === hash || obj.signedId === hash || obj.txId === hash) {
967
+ return filePath;
968
+ }
969
+ } catch {
970
+ }
971
+ }
972
+ }
973
+ } catch {
974
+ }
975
+ }
976
+ return null;
977
+ }
940
978
  function verifyArtifactSemantics(artifact, context = {}) {
941
979
  const result = {
942
980
  ok: true,
@@ -962,6 +1000,225 @@ function verifyArtifactSemantics(artifact, context = {}) {
962
1000
  });
963
1001
  }
964
1002
  const v = artifact;
1003
+ let parentObj = null;
1004
+ if (strict) {
1005
+ const searchDirs = [];
1006
+ if (context.artifactsDir) {
1007
+ searchDirs.push(context.artifactsDir);
1008
+ }
1009
+ searchDirs.push(path.join(process.cwd(), ".hardkas", "artifacts"));
1010
+ searchDirs.push(path.join(process.cwd(), "artifacts"));
1011
+ const policyRefs = [];
1012
+ if (Array.isArray(v.policyRefs)) {
1013
+ policyRefs.push(...v.policyRefs);
1014
+ } else if (typeof v.policyRef === "string") {
1015
+ policyRefs.push(v.policyRef);
1016
+ }
1017
+ for (const ref of policyRefs) {
1018
+ let refObj = context.resolveArtifact ? context.resolveArtifact(ref) : null;
1019
+ if (!refObj) {
1020
+ const refFile = findFileByHash(ref, searchDirs);
1021
+ if (refFile) {
1022
+ try {
1023
+ const content = fs.readFileSync(refFile, "utf-8");
1024
+ refObj = JSON.parse(content);
1025
+ } catch (e) {
1026
+ addIssue({
1027
+ code: "REFERENCE_CORRUPT",
1028
+ severity: "error",
1029
+ message: `Failed to read policy ${ref}: ${e.message}`
1030
+ });
1031
+ }
1032
+ }
1033
+ }
1034
+ if (!refObj) {
1035
+ addIssue({
1036
+ code: "REFERENCE_MISSING",
1037
+ severity: "error",
1038
+ message: `Referenced policy artifact ${ref} not found in workspace`
1039
+ });
1040
+ } else {
1041
+ try {
1042
+ const integrity = verifyArtifactIntegritySync(refObj);
1043
+ if (!integrity.ok) {
1044
+ addIssue({
1045
+ code: "REFERENCE_HASH_MISMATCH",
1046
+ severity: "error",
1047
+ message: `Referenced policy ${ref} integrity check failed: ${integrity.errors.join(", ")}`
1048
+ });
1049
+ } else if (refObj.contentHash !== ref && refObj.artifactId !== ref) {
1050
+ addIssue({
1051
+ code: "REFERENCE_HASH_MISMATCH",
1052
+ severity: "error",
1053
+ message: `Policy reference mismatch: expected ${ref}, got ${refObj.contentHash}`
1054
+ });
1055
+ } else {
1056
+ if (refObj.schema === "hardkas.policy.v1") {
1057
+ if (refObj.decision === "DENY") {
1058
+ addIssue({
1059
+ code: "POLICY_VIOLATION",
1060
+ severity: "error",
1061
+ message: `Policy evaluation rejected: decision is DENY`
1062
+ });
1063
+ } else if (refObj.decision !== "ALLOW") {
1064
+ addIssue({
1065
+ code: "POLICY_VIOLATION",
1066
+ severity: "error",
1067
+ message: `Policy evaluation rejected: decision is invalid (${refObj.decision})`
1068
+ });
1069
+ }
1070
+ const failedRules = refObj.rules?.filter((r) => r.result === "FAIL") || [];
1071
+ if (failedRules.length > 0) {
1072
+ addIssue({
1073
+ code: "POLICY_VIOLATION",
1074
+ severity: "error",
1075
+ message: `Policy rules failed: ${failedRules.map((r) => r.id).join(", ")}`
1076
+ });
1077
+ }
1078
+ }
1079
+ }
1080
+ } catch (e) {
1081
+ addIssue({
1082
+ code: "REFERENCE_CORRUPT",
1083
+ severity: "error",
1084
+ message: `Failed to read/verify policy ${ref}: ${e.message}`
1085
+ });
1086
+ }
1087
+ }
1088
+ }
1089
+ if (typeof v.networkProfileRef === "string") {
1090
+ const ref = v.networkProfileRef;
1091
+ let refObj = context.resolveArtifact ? context.resolveArtifact(ref) : null;
1092
+ if (!refObj) {
1093
+ const refFile = findFileByHash(ref, searchDirs);
1094
+ if (refFile) {
1095
+ try {
1096
+ refObj = JSON.parse(fs.readFileSync(refFile, "utf-8"));
1097
+ } catch {
1098
+ }
1099
+ }
1100
+ }
1101
+ if (!refObj) {
1102
+ addIssue({
1103
+ code: "REFERENCE_MISSING",
1104
+ severity: "error",
1105
+ message: `Referenced network profile ${ref} not found in workspace`
1106
+ });
1107
+ } else {
1108
+ try {
1109
+ const integrity = verifyArtifactIntegritySync(refObj);
1110
+ if (!integrity.ok) {
1111
+ addIssue({
1112
+ code: "REFERENCE_HASH_MISMATCH",
1113
+ severity: "error",
1114
+ message: `Referenced profile ${ref} integrity check failed`
1115
+ });
1116
+ } else if (refObj.contentHash !== ref && refObj.artifactId !== ref) {
1117
+ addIssue({
1118
+ code: "REFERENCE_HASH_MISMATCH",
1119
+ severity: "error",
1120
+ message: `Profile reference mismatch: expected ${ref}, got ${refObj.contentHash}`
1121
+ });
1122
+ }
1123
+ } catch (e) {
1124
+ addIssue({
1125
+ code: "REFERENCE_CORRUPT",
1126
+ severity: "error",
1127
+ message: `Failed to verify profile ${ref}`
1128
+ });
1129
+ }
1130
+ }
1131
+ }
1132
+ if (typeof v.assumptionRef === "string") {
1133
+ const ref = v.assumptionRef;
1134
+ let refObj = context.resolveArtifact ? context.resolveArtifact(ref) : null;
1135
+ if (!refObj) {
1136
+ const refFile = findFileByHash(ref, searchDirs);
1137
+ if (refFile) {
1138
+ try {
1139
+ refObj = JSON.parse(fs.readFileSync(refFile, "utf-8"));
1140
+ } catch {
1141
+ }
1142
+ }
1143
+ }
1144
+ if (!refObj) {
1145
+ addIssue({
1146
+ code: "REFERENCE_MISSING",
1147
+ severity: "error",
1148
+ message: `Referenced assumption ${ref} not found in workspace`
1149
+ });
1150
+ } else {
1151
+ try {
1152
+ const integrity = verifyArtifactIntegritySync(refObj);
1153
+ if (!integrity.ok) {
1154
+ addIssue({
1155
+ code: "REFERENCE_HASH_MISMATCH",
1156
+ severity: "error",
1157
+ message: `Referenced assumption ${ref} integrity check failed`
1158
+ });
1159
+ } else if (refObj.contentHash !== ref && refObj.artifactId !== ref) {
1160
+ addIssue({
1161
+ code: "REFERENCE_HASH_MISMATCH",
1162
+ severity: "error",
1163
+ message: `Assumption reference mismatch: expected ${ref}, got ${refObj.contentHash}`
1164
+ });
1165
+ }
1166
+ } catch (e) {
1167
+ addIssue({
1168
+ code: "REFERENCE_CORRUPT",
1169
+ severity: "error",
1170
+ message: `Failed to verify assumption ${ref}`
1171
+ });
1172
+ }
1173
+ }
1174
+ }
1175
+ let parentId;
1176
+ const lineage = v.lineage;
1177
+ if (lineage?.parentArtifactId && lineage?.parentArtifactId !== lineage?.artifactId) {
1178
+ parentId = lineage?.parentArtifactId;
1179
+ } else if (v.schema === "hardkas.signedTx") {
1180
+ parentId = v.sourcePlanId;
1181
+ } else if (v.schema === "hardkas.txReceipt") {
1182
+ parentId = v.sourceSignedId || lineage?.parentArtifactId;
1183
+ }
1184
+ if (parentId) {
1185
+ parentObj = context.resolveArtifact ? context.resolveArtifact(parentId) : null;
1186
+ if (!parentObj) {
1187
+ const parentFile = findFileByHash(parentId, searchDirs);
1188
+ if (parentFile) {
1189
+ try {
1190
+ parentObj = JSON.parse(fs.readFileSync(parentFile, "utf-8"));
1191
+ } catch (e) {
1192
+ addIssue({
1193
+ code: "PARENT_CORRUPT",
1194
+ severity: "error",
1195
+ message: `Failed to read parent ${parentId}: ${e.message}`
1196
+ });
1197
+ }
1198
+ }
1199
+ }
1200
+ if (!parentObj) {
1201
+ addIssue({
1202
+ code: "PARENT_MISSING",
1203
+ severity: "warning",
1204
+ message: `Parent artifact ${parentId} not found in workspace`
1205
+ });
1206
+ } else {
1207
+ try {
1208
+ const parentSem = verifyArtifactSemantics(parentObj, { ...context, strict: true });
1209
+ if (!parentSem.ok) {
1210
+ parentSem.issues.forEach((issue) => addIssue(issue));
1211
+ }
1212
+ } catch (e) {
1213
+ addIssue({
1214
+ code: "PARENT_CORRUPT",
1215
+ severity: "error",
1216
+ message: `Failed to verify parent ${parentId}: ${e.message}`
1217
+ });
1218
+ }
1219
+ }
1220
+ }
1221
+ }
965
1222
  if (v.createdAt && typeof v.createdAt === "string") {
966
1223
  const created = new Date(v.createdAt).getTime();
967
1224
  const now = clock.now();
@@ -980,31 +1237,47 @@ function verifyArtifactSemantics(artifact, context = {}) {
980
1237
  });
981
1238
  }
982
1239
  }
983
- const lineageAudit = verifyLineage(v, context.parent, { strict });
1240
+ const lineageAudit = verifyLineage(v, parentObj || context.parent, { strict });
984
1241
  if (!lineageAudit.ok || strict && !v.lineage && v.schema !== "hardkas.workflow.v1") {
985
1242
  lineageAudit.issues.forEach((issue) => {
986
1243
  addIssue(issue);
987
1244
  });
988
1245
  }
989
1246
  if (strict) {
990
- if (!v.workflowId)
991
- addIssue({
992
- code: "MISSING_WORKFLOW_ID",
993
- severity: "error",
994
- message: "Strict mode requires workflowId"
995
- });
996
- if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
997
- addIssue({
998
- code: "MISSING_ASSUMPTION_LEVEL",
999
- severity: "error",
1000
- message: "Strict mode requires assumptionLevel"
1001
- });
1002
- if (!v.executionMode && !v.mode)
1003
- addIssue({
1004
- code: "MISSING_EXECUTION_MODE",
1005
- severity: "error",
1006
- message: "Strict mode requires executionMode"
1007
- });
1247
+ const enforceMetadata = context.enforceMetadata ?? true;
1248
+ if (enforceMetadata) {
1249
+ if (!v.workflowId)
1250
+ addIssue({
1251
+ code: "MISSING_WORKFLOW_ID",
1252
+ severity: "error",
1253
+ message: "Strict mode requires workflowId"
1254
+ });
1255
+ if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
1256
+ addIssue({
1257
+ code: "MISSING_ASSUMPTION_LEVEL",
1258
+ severity: "error",
1259
+ message: "Strict mode requires assumptionLevel"
1260
+ });
1261
+ if (!v.executionMode && !v.mode)
1262
+ addIssue({
1263
+ code: "MISSING_EXECUTION_MODE",
1264
+ severity: "error",
1265
+ message: "Strict mode requires executionMode"
1266
+ });
1267
+ } else {
1268
+ if (!v.workflowId)
1269
+ addIssue({
1270
+ code: "MISSING_WORKFLOW_ID",
1271
+ severity: "warning",
1272
+ message: "Missing workflowId"
1273
+ });
1274
+ if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
1275
+ addIssue({
1276
+ code: "MISSING_ASSUMPTION_LEVEL",
1277
+ severity: "warning",
1278
+ message: "Missing assumptionLevel"
1279
+ });
1280
+ }
1008
1281
  } else {
1009
1282
  if (!v.workflowId)
1010
1283
  addIssue({
@@ -1375,8 +1648,8 @@ function canMigrate(artifact, targetVersion = ARTIFACT_VERSION) {
1375
1648
  if (currentVersion === targetVersion) {
1376
1649
  return true;
1377
1650
  }
1378
- const path4 = getMigrationPath(currentVersion, targetVersion);
1379
- return path4.length > 0;
1651
+ const path5 = getMigrationPath(currentVersion, targetVersion);
1652
+ return path5.length > 0;
1380
1653
  }
1381
1654
  function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION, options) {
1382
1655
  const currentVersion = detectArtifactVersion(artifact);
@@ -1391,8 +1664,8 @@ function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION, opti
1391
1664
  if (options?.strictPolicy) {
1392
1665
  throw new MigrationRequiredError(currentVersion, targetVersion);
1393
1666
  }
1394
- const path4 = getMigrationPath(currentVersion, targetVersion);
1395
- if (path4.length === 0) {
1667
+ const path5 = getMigrationPath(currentVersion, targetVersion);
1668
+ if (path5.length === 0) {
1396
1669
  throw new Error(
1397
1670
  `No migration path from version "${currentVersion}" to "${targetVersion}". Registered steps: [${migrationRegistry.map((s) => `${s.fromVersion}\u2192${s.toVersion}`).join(", ")}]`
1398
1671
  );
@@ -1401,7 +1674,7 @@ function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION, opti
1401
1674
  const originalLineage = artifact.lineage;
1402
1675
  let current = { ...artifact };
1403
1676
  const appliedSteps = [];
1404
- for (const step of path4) {
1677
+ for (const step of path5) {
1405
1678
  current = step.transform(current);
1406
1679
  appliedSteps.push({
1407
1680
  fromVersion: step.fromVersion,
@@ -1478,7 +1751,7 @@ function generateMigrationReceipt(oldArtifact, newArtifact, migrationId) {
1478
1751
 
1479
1752
  // src/io.ts
1480
1753
  import fs2 from "fs/promises";
1481
- import path from "path";
1754
+ import path2 from "path";
1482
1755
  import { writeFileAtomic } from "@hardkas/core";
1483
1756
  var bigIntReplacer = (_key, value) => typeof value === "bigint" ? value.toString() : value;
1484
1757
  async function writeArtifact(filePath, artifact) {
@@ -1489,10 +1762,10 @@ async function writeArtifact(filePath, artifact) {
1489
1762
  const artifactObj = typeof artifact === "string" ? JSON.parse(artifact) : artifact;
1490
1763
  const id = artifactObj.planId || artifactObj.signedId || artifactObj.txId || Date.now().toString(36);
1491
1764
  const prefix = artifactObj.schema ? artifactObj.schema.split(".")[1] || "artifact" : "artifact";
1492
- targetPath = path.join(filePath, `${prefix}-${id}.json`);
1765
+ targetPath = path2.join(filePath, `${prefix}-${id}.json`);
1493
1766
  console.log(
1494
1767
  `
1495
- Note: Provided path is a directory. Auto-generating artifact filename: ${path.basename(targetPath)}`
1768
+ Note: Provided path is a directory. Auto-generating artifact filename: ${path2.basename(targetPath)}`
1496
1769
  );
1497
1770
  }
1498
1771
  } catch (e) {
@@ -1500,14 +1773,14 @@ Note: Provided path is a directory. Auto-generating artifact filename: ${path.ba
1500
1773
  const artifactObj = typeof artifact === "string" ? JSON.parse(artifact) : artifact;
1501
1774
  const id = artifactObj.planId || artifactObj.signedId || artifactObj.txId || Date.now().toString(36);
1502
1775
  const prefix = artifactObj.schema ? artifactObj.schema.split(".")[1] || "artifact" : "artifact";
1503
- targetPath = path.join(filePath, `${prefix}-${id}.json`);
1776
+ targetPath = path2.join(filePath, `${prefix}-${id}.json`);
1504
1777
  }
1505
1778
  }
1506
1779
  const content = typeof artifact === "string" ? artifact : JSON.stringify(artifact, bigIntReplacer, 2) + "\n";
1507
1780
  await writeFileAtomic(targetPath, content);
1508
1781
  }
1509
1782
  function getDefaultReceiptPath(txId, cwd = process.cwd()) {
1510
- return path.join(cwd, "artifacts", "receipts", `${txId}.json`);
1783
+ return path2.join(cwd, "artifacts", "receipts", `${txId}.json`);
1511
1784
  }
1512
1785
  async function readArtifact(filePath) {
1513
1786
  try {
@@ -2040,15 +2313,15 @@ async function explainArtifact(artifactUnknown) {
2040
2313
 
2041
2314
  // src/igra-io.ts
2042
2315
  import fs3 from "fs/promises";
2043
- import path2 from "path";
2316
+ import path3 from "path";
2044
2317
  import { deterministicCompare as deterministicCompare3 } from "@hardkas/core";
2045
2318
  function getDefaultL2ReceiptsDir(cwd = process.cwd()) {
2046
- return path2.join(cwd, ".hardkas", "l2-receipts");
2319
+ return path3.join(cwd, ".hardkas", "l2-receipts");
2047
2320
  }
2048
2321
  function getL2ReceiptPath(txHash, options) {
2049
2322
  validateTxHash(txHash);
2050
2323
  const dir = getDefaultL2ReceiptsDir(options?.cwd);
2051
- return path2.join(dir, `${txHash}.igra.receipt.json`);
2324
+ return path3.join(dir, `${txHash}.igra.receipt.json`);
2052
2325
  }
2053
2326
  async function saveIgraTxReceiptArtifact(receipt, options) {
2054
2327
  assertValidIgraTxReceiptArtifact(receipt);
@@ -2070,7 +2343,7 @@ async function listIgraTxReceiptArtifacts(options) {
2070
2343
  const receipts = [];
2071
2344
  for (const file of receiptFiles) {
2072
2345
  try {
2073
- const data = await readArtifact(path2.join(dir, file));
2346
+ const data = await readArtifact(path3.join(dir, file));
2074
2347
  if (data && typeof data === "object" && data.schema === "hardkas.igraTxReceipt.v1") {
2075
2348
  receipts.push(data);
2076
2349
  }
@@ -2103,26 +2376,26 @@ function diffArtifacts(left, right) {
2103
2376
  entries
2104
2377
  };
2105
2378
  }
2106
- function compareRecursive(left, right, path4, entries) {
2379
+ function compareRecursive(left, right, path5, entries) {
2107
2380
  if (isPrimitive(left) || isPrimitive(right)) {
2108
2381
  if (left !== right) {
2109
- entries.push({ path: path4, kind: "changed", left, right });
2382
+ entries.push({ path: path5, kind: "changed", left, right });
2110
2383
  }
2111
2384
  return;
2112
2385
  }
2113
2386
  if (Array.isArray(left) || Array.isArray(right)) {
2114
2387
  if (!Array.isArray(left) || !Array.isArray(right)) {
2115
- entries.push({ path: path4, kind: "changed", left, right });
2388
+ entries.push({ path: path5, kind: "changed", left, right });
2116
2389
  return;
2117
2390
  }
2118
2391
  const maxLength = Math.max(left.length, right.length);
2119
2392
  for (let i = 0; i < maxLength; i++) {
2120
2393
  if (i >= left.length) {
2121
- entries.push({ path: `${path4}[${i}]`, kind: "added", right: right[i] });
2394
+ entries.push({ path: `${path5}[${i}]`, kind: "added", right: right[i] });
2122
2395
  } else if (i >= right.length) {
2123
- entries.push({ path: `${path4}[${i}]`, kind: "removed", left: left[i] });
2396
+ entries.push({ path: `${path5}[${i}]`, kind: "removed", left: left[i] });
2124
2397
  } else {
2125
- compareRecursive(left[i], right[i], `${path4}[${i}]`, entries);
2398
+ compareRecursive(left[i], right[i], `${path5}[${i}]`, entries);
2126
2399
  }
2127
2400
  }
2128
2401
  return;
@@ -2131,7 +2404,7 @@ function compareRecursive(left, right, path4, entries) {
2131
2404
  const rightKeys = Object.keys(right).filter((k) => !SEMANTIC_EXCLUSIONS.has(k));
2132
2405
  const allKeys = /* @__PURE__ */ new Set([...leftKeys, ...rightKeys]);
2133
2406
  for (const key of allKeys) {
2134
- const nextPath = path4 === "$" ? key : `${path4}.${key}`;
2407
+ const nextPath = path5 === "$" ? key : `${path5}.${key}`;
2135
2408
  if (!leftKeys.includes(key)) {
2136
2409
  entries.push({ path: nextPath, kind: "added", right: right[key] });
2137
2410
  } else if (!rightKeys.includes(key)) {
@@ -2195,16 +2468,16 @@ function updateDeploymentStatus(record, newStatus, txId) {
2195
2468
  // src/deployment-store.ts
2196
2469
  import fs4 from "fs/promises";
2197
2470
  import { existsSync } from "fs";
2198
- import path3 from "path";
2471
+ import path4 from "path";
2199
2472
  import { writeFileAtomic as writeFileAtomic2 } from "@hardkas/core";
2200
2473
  async function saveDeployment(rootDir, record) {
2201
- const deploymentsDir = path3.join(rootDir, ".hardkas", "deployments", record.networkId);
2202
- const targetPath = path3.join(deploymentsDir, `${record.label}.json`);
2474
+ const deploymentsDir = path4.join(rootDir, ".hardkas", "deployments", record.networkId);
2475
+ const targetPath = path4.join(deploymentsDir, `${record.label}.json`);
2203
2476
  await writeFileAtomic2(targetPath, JSON.stringify(record, null, 2));
2204
2477
  return targetPath;
2205
2478
  }
2206
2479
  async function loadDeployment(rootDir, networkId, label) {
2207
- const targetPath = path3.join(
2480
+ const targetPath = path4.join(
2208
2481
  rootDir,
2209
2482
  ".hardkas",
2210
2483
  "deployments",
@@ -2216,18 +2489,18 @@ async function loadDeployment(rootDir, networkId, label) {
2216
2489
  return JSON.parse(content);
2217
2490
  }
2218
2491
  async function listDeployments(rootDir, networkId) {
2219
- const baseDir = path3.join(rootDir, ".hardkas", "deployments");
2492
+ const baseDir = path4.join(rootDir, ".hardkas", "deployments");
2220
2493
  if (!existsSync(baseDir)) return [];
2221
2494
  const summaries = [];
2222
2495
  const networks = networkId ? [networkId] : await fs4.readdir(baseDir);
2223
2496
  for (const net of networks) {
2224
- const netDir = path3.join(baseDir, net);
2497
+ const netDir = path4.join(baseDir, net);
2225
2498
  if (!existsSync(netDir)) continue;
2226
2499
  const files = await fs4.readdir(netDir);
2227
2500
  for (const file of files) {
2228
2501
  if (!file.endsWith(".json")) continue;
2229
2502
  try {
2230
- const content = await fs4.readFile(path3.join(netDir, file), "utf-8");
2503
+ const content = await fs4.readFile(path4.join(netDir, file), "utf-8");
2231
2504
  const record = JSON.parse(content);
2232
2505
  const summary = {
2233
2506
  label: record.label,
@@ -2260,7 +2533,7 @@ async function updateDeployment(rootDir, networkId, label, update) {
2260
2533
  return updated;
2261
2534
  }
2262
2535
  async function deleteDeployment(rootDir, networkId, label) {
2263
- const targetPath = path3.join(
2536
+ const targetPath = path4.join(
2264
2537
  rootDir,
2265
2538
  ".hardkas",
2266
2539
  "deployments",
@@ -2375,6 +2648,7 @@ export {
2375
2648
  verifyArtifact,
2376
2649
  verifyArtifactFile,
2377
2650
  verifyArtifactIntegrity,
2651
+ verifyArtifactIntegritySync,
2378
2652
  verifyArtifactReplay,
2379
2653
  verifyArtifactSemantics,
2380
2654
  verifyFeeSemantics,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hardkas/artifacts",
3
- "version": "0.8.3-alpha",
3
+ "version": "0.8.5-alpha",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Javier Rodriguez",
@@ -19,19 +19,24 @@
19
19
  "LICENSE"
20
20
  ],
21
21
  "exports": {
22
- ".": "./dist/index.js"
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js",
25
+ "default": "./dist/index.js"
26
+ }
23
27
  },
24
28
  "types": "./dist/index.d.ts",
25
29
  "dependencies": {
26
30
  "zod": "^3.24.1",
27
- "@hardkas/core": "0.8.3-alpha",
28
- "@hardkas/tx-builder": "0.8.3-alpha"
31
+ "@hardkas/core": "0.8.5-alpha",
32
+ "@hardkas/tx-builder": "0.8.5-alpha"
29
33
  },
30
34
  "devDependencies": {
31
35
  "tsup": "^8.3.5",
32
36
  "typescript": "^5.6.3",
33
37
  "vitest": "^2.1.4"
34
38
  },
39
+ "main": "./dist/index.js",
35
40
  "scripts": {
36
41
  "build": "tsup src/index.ts --format esm --dts --clean",
37
42
  "dev": "tsup src/index.ts --format esm --watch --dts",