@hardkas/artifacts 0.8.2-alpha → 0.8.4-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 +628 -33
- package/dist/index.js +497 -60
- package/package.json +3 -3
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.
|
|
4
|
+
version: "0.8.4-alpha",
|
|
5
5
|
type: "module",
|
|
6
6
|
license: "MIT",
|
|
7
7
|
author: "Javier Rodriguez",
|
|
@@ -53,7 +53,11 @@ var ARTIFACT_SCHEMAS = {
|
|
|
53
53
|
SNAPSHOT: "hardkas.snapshot",
|
|
54
54
|
IGRA_TX_PLAN: "hardkas.igraTxPlan.v1",
|
|
55
55
|
IGRA_SIGNED_TX: "hardkas.igraSignedTx.v1",
|
|
56
|
-
IGRA_TX_RECEIPT: "hardkas.igraTxReceipt.v1"
|
|
56
|
+
IGRA_TX_RECEIPT: "hardkas.igraTxReceipt.v1",
|
|
57
|
+
POLICY: "hardkas.policy.v1",
|
|
58
|
+
NETWORK_PROFILE: "hardkas.networkProfile.v1",
|
|
59
|
+
ASSUMPTION: "hardkas.assumption.v1",
|
|
60
|
+
MIGRATION_RECEIPT: "hardkas.migrationReceipt.v1"
|
|
57
61
|
};
|
|
58
62
|
|
|
59
63
|
// src/igra-artifacts.ts
|
|
@@ -345,6 +349,41 @@ var AccountRefSchema = z.object({
|
|
|
345
349
|
accountName: z.string().optional(),
|
|
346
350
|
input: z.string().optional()
|
|
347
351
|
});
|
|
352
|
+
var PolicySchema = BaseArtifactSchema.extend({
|
|
353
|
+
schema: z.literal("hardkas.policy.v1"),
|
|
354
|
+
decision: z.enum(["ALLOW", "DENY"]),
|
|
355
|
+
rules: z.array(
|
|
356
|
+
z.object({
|
|
357
|
+
id: z.string(),
|
|
358
|
+
result: z.enum(["PASS", "FAIL"]),
|
|
359
|
+
inputHash: z.string().optional()
|
|
360
|
+
})
|
|
361
|
+
)
|
|
362
|
+
});
|
|
363
|
+
var NetworkProfileSchema = BaseArtifactSchema.extend({
|
|
364
|
+
schema: z.literal("hardkas.networkProfile.v1"),
|
|
365
|
+
networkProfileId: z.string(),
|
|
366
|
+
layer: z.string(),
|
|
367
|
+
capabilities: z.record(z.any())
|
|
368
|
+
});
|
|
369
|
+
var AssumptionSchema = BaseArtifactSchema.extend({
|
|
370
|
+
schema: z.literal("hardkas.assumption.v1"),
|
|
371
|
+
settlement: z.string().optional(),
|
|
372
|
+
securityModel: z.string().optional(),
|
|
373
|
+
bridgePhase: z.string().optional(),
|
|
374
|
+
exitModel: z.string().optional(),
|
|
375
|
+
customAssumptions: z.record(z.any()).optional()
|
|
376
|
+
});
|
|
377
|
+
var MigrationReceiptSchema = BaseArtifactSchema.extend({
|
|
378
|
+
schema: z.literal("hardkas.migrationReceipt.v1"),
|
|
379
|
+
oldHash: z.string(),
|
|
380
|
+
newHash: z.string(),
|
|
381
|
+
fromSchema: z.string(),
|
|
382
|
+
toSchema: z.string(),
|
|
383
|
+
migrationId: z.string(),
|
|
384
|
+
migrationVersion: z.string().optional(),
|
|
385
|
+
decision: z.literal("MIGRATED_WITH_PROOF")
|
|
386
|
+
});
|
|
348
387
|
var TxPlanSchema = BaseArtifactSchema.extend({
|
|
349
388
|
schema: z.literal("hardkas.txPlan"),
|
|
350
389
|
networkId: kaspaNetworkIdSchema,
|
|
@@ -374,7 +413,11 @@ var TxPlanSchema = BaseArtifactSchema.extend({
|
|
|
374
413
|
address: z.string(),
|
|
375
414
|
amountSompi: z.string()
|
|
376
415
|
}).optional(),
|
|
377
|
-
rpcUrl: z.string().optional()
|
|
416
|
+
rpcUrl: z.string().optional(),
|
|
417
|
+
networkProfileRef: z.string().optional(),
|
|
418
|
+
policyRef: z.string().optional(),
|
|
419
|
+
policyRefs: z.array(z.string()).optional(),
|
|
420
|
+
assumptionRef: z.string().optional()
|
|
378
421
|
});
|
|
379
422
|
var DagContextSchema = z.object({
|
|
380
423
|
mode: z.enum(["linear", "dag-light"]),
|
|
@@ -539,6 +582,7 @@ var RuntimeSessionSchema = BaseArtifactSchema.extend({
|
|
|
539
582
|
|
|
540
583
|
// src/verify.ts
|
|
541
584
|
import fs from "fs";
|
|
585
|
+
import path from "path";
|
|
542
586
|
|
|
543
587
|
// src/feeVerify.ts
|
|
544
588
|
import {
|
|
@@ -727,12 +771,21 @@ function verifyLineage(artifact, parent, options = {}) {
|
|
|
727
771
|
}
|
|
728
772
|
if (parent) {
|
|
729
773
|
const validTransitions = {
|
|
730
|
-
"hardkas.snapshot": ["hardkas.txPlan"],
|
|
731
|
-
"hardkas.txPlan": ["hardkas.signedTx"],
|
|
732
|
-
"hardkas.signedTx": ["hardkas.txReceipt"]
|
|
774
|
+
"hardkas.snapshot": ["hardkas.txPlan", "hardkas.migrationReceipt.v1"],
|
|
775
|
+
"hardkas.txPlan": ["hardkas.signedTx", "hardkas.migrationReceipt.v1"],
|
|
776
|
+
"hardkas.signedTx": ["hardkas.txReceipt", "hardkas.signedTx", "hardkas.migrationReceipt.v1"],
|
|
777
|
+
"hardkas.txReceipt": ["hardkas.txTrace", "hardkas.migrationReceipt.v1"]
|
|
733
778
|
};
|
|
734
|
-
|
|
735
|
-
if (
|
|
779
|
+
let isValidTransition = false;
|
|
780
|
+
if (parent.schema === "hardkas.migrationReceipt.v1") {
|
|
781
|
+
isValidTransition = parent.toSchema === artifact.schema;
|
|
782
|
+
} else if (artifact.schema === "hardkas.migrationReceipt.v1") {
|
|
783
|
+
isValidTransition = artifact.fromSchema === parent.schema;
|
|
784
|
+
} else {
|
|
785
|
+
const allowed = validTransitions[parent.schema] || [];
|
|
786
|
+
isValidTransition = allowed.includes(artifact.schema);
|
|
787
|
+
}
|
|
788
|
+
if (!isValidTransition) {
|
|
736
789
|
addIssue(
|
|
737
790
|
"INVALID_TRANSITION",
|
|
738
791
|
`Invalid lineage transition: ${parent.schema} -> ${artifact.schema}`
|
|
@@ -764,15 +817,15 @@ function sortUtxosByOutpoint(utxos) {
|
|
|
764
817
|
return deterministicCompare2(aId, bId);
|
|
765
818
|
});
|
|
766
819
|
}
|
|
767
|
-
|
|
820
|
+
function verifyArtifactIntegritySync(artifactOrPath) {
|
|
768
821
|
const result = {
|
|
769
822
|
ok: false,
|
|
770
823
|
errors: [],
|
|
771
824
|
issues: []
|
|
772
825
|
};
|
|
773
|
-
const addError = (code, message,
|
|
826
|
+
const addError = (code, message, path5) => {
|
|
774
827
|
result.errors.push(message);
|
|
775
|
-
result.issues.push({ code, severity: "error", message, path:
|
|
828
|
+
result.issues.push({ code, severity: "error", message, path: path5 });
|
|
776
829
|
};
|
|
777
830
|
let artifact;
|
|
778
831
|
try {
|
|
@@ -844,6 +897,18 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
844
897
|
case "hardkas.workflow.v1":
|
|
845
898
|
schema = WorkflowSchema;
|
|
846
899
|
break;
|
|
900
|
+
case "hardkas.policy.v1":
|
|
901
|
+
schema = PolicySchema;
|
|
902
|
+
break;
|
|
903
|
+
case "hardkas.networkProfile.v1":
|
|
904
|
+
schema = NetworkProfileSchema;
|
|
905
|
+
break;
|
|
906
|
+
case "hardkas.assumption.v1":
|
|
907
|
+
schema = AssumptionSchema;
|
|
908
|
+
break;
|
|
909
|
+
case "hardkas.migrationReceipt.v1":
|
|
910
|
+
schema = MigrationReceiptSchema;
|
|
911
|
+
break;
|
|
847
912
|
}
|
|
848
913
|
if (schema) {
|
|
849
914
|
const validation = schema.safeParse(v);
|
|
@@ -874,6 +939,37 @@ async function verifyArtifactIntegrity(artifactOrPath) {
|
|
|
874
939
|
return result;
|
|
875
940
|
}
|
|
876
941
|
}
|
|
942
|
+
async function verifyArtifactIntegrity(artifactOrPath) {
|
|
943
|
+
return verifyArtifactIntegritySync(artifactOrPath);
|
|
944
|
+
}
|
|
945
|
+
function findFileByHash(hash, dirs) {
|
|
946
|
+
const shortHash = hash.startsWith("plan-") || hash.startsWith("signed-") ? hash : hash.slice(0, 16);
|
|
947
|
+
for (const dir of dirs) {
|
|
948
|
+
if (!fs.existsSync(dir)) continue;
|
|
949
|
+
try {
|
|
950
|
+
const files = fs.readdirSync(dir);
|
|
951
|
+
if (files.includes(`${hash}.json`)) {
|
|
952
|
+
return path.join(dir, `${hash}.json`);
|
|
953
|
+
}
|
|
954
|
+
for (const file of files) {
|
|
955
|
+
if (!file.endsWith(".json")) continue;
|
|
956
|
+
if (file.includes(hash) || file.includes(shortHash) || file.includes(hash.slice(0, 8))) {
|
|
957
|
+
const filePath = path.join(dir, file);
|
|
958
|
+
try {
|
|
959
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
960
|
+
const obj = JSON.parse(content);
|
|
961
|
+
if (obj.contentHash === hash || obj.artifactId === hash || obj.planId === hash || obj.signedId === hash || obj.txId === hash) {
|
|
962
|
+
return filePath;
|
|
963
|
+
}
|
|
964
|
+
} catch {
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
} catch {
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
877
973
|
function verifyArtifactSemantics(artifact, context = {}) {
|
|
878
974
|
const result = {
|
|
879
975
|
ok: true,
|
|
@@ -899,6 +995,225 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
899
995
|
});
|
|
900
996
|
}
|
|
901
997
|
const v = artifact;
|
|
998
|
+
let parentObj = null;
|
|
999
|
+
if (strict) {
|
|
1000
|
+
const searchDirs = [];
|
|
1001
|
+
if (context.artifactsDir) {
|
|
1002
|
+
searchDirs.push(context.artifactsDir);
|
|
1003
|
+
}
|
|
1004
|
+
searchDirs.push(path.join(process.cwd(), ".hardkas", "artifacts"));
|
|
1005
|
+
searchDirs.push(path.join(process.cwd(), "artifacts"));
|
|
1006
|
+
const policyRefs = [];
|
|
1007
|
+
if (Array.isArray(v.policyRefs)) {
|
|
1008
|
+
policyRefs.push(...v.policyRefs);
|
|
1009
|
+
} else if (typeof v.policyRef === "string") {
|
|
1010
|
+
policyRefs.push(v.policyRef);
|
|
1011
|
+
}
|
|
1012
|
+
for (const ref of policyRefs) {
|
|
1013
|
+
let refObj = context.resolveArtifact ? context.resolveArtifact(ref) : null;
|
|
1014
|
+
if (!refObj) {
|
|
1015
|
+
const refFile = findFileByHash(ref, searchDirs);
|
|
1016
|
+
if (refFile) {
|
|
1017
|
+
try {
|
|
1018
|
+
const content = fs.readFileSync(refFile, "utf-8");
|
|
1019
|
+
refObj = JSON.parse(content);
|
|
1020
|
+
} catch (e) {
|
|
1021
|
+
addIssue({
|
|
1022
|
+
code: "REFERENCE_CORRUPT",
|
|
1023
|
+
severity: "error",
|
|
1024
|
+
message: `Failed to read policy ${ref}: ${e.message}`
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
if (!refObj) {
|
|
1030
|
+
addIssue({
|
|
1031
|
+
code: "REFERENCE_MISSING",
|
|
1032
|
+
severity: "error",
|
|
1033
|
+
message: `Referenced policy artifact ${ref} not found in workspace`
|
|
1034
|
+
});
|
|
1035
|
+
} else {
|
|
1036
|
+
try {
|
|
1037
|
+
const integrity = verifyArtifactIntegritySync(refObj);
|
|
1038
|
+
if (!integrity.ok) {
|
|
1039
|
+
addIssue({
|
|
1040
|
+
code: "REFERENCE_HASH_MISMATCH",
|
|
1041
|
+
severity: "error",
|
|
1042
|
+
message: `Referenced policy ${ref} integrity check failed: ${integrity.errors.join(", ")}`
|
|
1043
|
+
});
|
|
1044
|
+
} else if (refObj.contentHash !== ref && refObj.artifactId !== ref) {
|
|
1045
|
+
addIssue({
|
|
1046
|
+
code: "REFERENCE_HASH_MISMATCH",
|
|
1047
|
+
severity: "error",
|
|
1048
|
+
message: `Policy reference mismatch: expected ${ref}, got ${refObj.contentHash}`
|
|
1049
|
+
});
|
|
1050
|
+
} else {
|
|
1051
|
+
if (refObj.schema === "hardkas.policy.v1") {
|
|
1052
|
+
if (refObj.decision === "DENY") {
|
|
1053
|
+
addIssue({
|
|
1054
|
+
code: "POLICY_VIOLATION",
|
|
1055
|
+
severity: "error",
|
|
1056
|
+
message: `Policy evaluation rejected: decision is DENY`
|
|
1057
|
+
});
|
|
1058
|
+
} else if (refObj.decision !== "ALLOW") {
|
|
1059
|
+
addIssue({
|
|
1060
|
+
code: "POLICY_VIOLATION",
|
|
1061
|
+
severity: "error",
|
|
1062
|
+
message: `Policy evaluation rejected: decision is invalid (${refObj.decision})`
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
const failedRules = refObj.rules?.filter((r) => r.result === "FAIL") || [];
|
|
1066
|
+
if (failedRules.length > 0) {
|
|
1067
|
+
addIssue({
|
|
1068
|
+
code: "POLICY_VIOLATION",
|
|
1069
|
+
severity: "error",
|
|
1070
|
+
message: `Policy rules failed: ${failedRules.map((r) => r.id).join(", ")}`
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
} catch (e) {
|
|
1076
|
+
addIssue({
|
|
1077
|
+
code: "REFERENCE_CORRUPT",
|
|
1078
|
+
severity: "error",
|
|
1079
|
+
message: `Failed to read/verify policy ${ref}: ${e.message}`
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (typeof v.networkProfileRef === "string") {
|
|
1085
|
+
const ref = v.networkProfileRef;
|
|
1086
|
+
let refObj = context.resolveArtifact ? context.resolveArtifact(ref) : null;
|
|
1087
|
+
if (!refObj) {
|
|
1088
|
+
const refFile = findFileByHash(ref, searchDirs);
|
|
1089
|
+
if (refFile) {
|
|
1090
|
+
try {
|
|
1091
|
+
refObj = JSON.parse(fs.readFileSync(refFile, "utf-8"));
|
|
1092
|
+
} catch {
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
if (!refObj) {
|
|
1097
|
+
addIssue({
|
|
1098
|
+
code: "REFERENCE_MISSING",
|
|
1099
|
+
severity: "error",
|
|
1100
|
+
message: `Referenced network profile ${ref} not found in workspace`
|
|
1101
|
+
});
|
|
1102
|
+
} else {
|
|
1103
|
+
try {
|
|
1104
|
+
const integrity = verifyArtifactIntegritySync(refObj);
|
|
1105
|
+
if (!integrity.ok) {
|
|
1106
|
+
addIssue({
|
|
1107
|
+
code: "REFERENCE_HASH_MISMATCH",
|
|
1108
|
+
severity: "error",
|
|
1109
|
+
message: `Referenced profile ${ref} integrity check failed`
|
|
1110
|
+
});
|
|
1111
|
+
} else if (refObj.contentHash !== ref && refObj.artifactId !== ref) {
|
|
1112
|
+
addIssue({
|
|
1113
|
+
code: "REFERENCE_HASH_MISMATCH",
|
|
1114
|
+
severity: "error",
|
|
1115
|
+
message: `Profile reference mismatch: expected ${ref}, got ${refObj.contentHash}`
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
} catch (e) {
|
|
1119
|
+
addIssue({
|
|
1120
|
+
code: "REFERENCE_CORRUPT",
|
|
1121
|
+
severity: "error",
|
|
1122
|
+
message: `Failed to verify profile ${ref}`
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
if (typeof v.assumptionRef === "string") {
|
|
1128
|
+
const ref = v.assumptionRef;
|
|
1129
|
+
let refObj = context.resolveArtifact ? context.resolveArtifact(ref) : null;
|
|
1130
|
+
if (!refObj) {
|
|
1131
|
+
const refFile = findFileByHash(ref, searchDirs);
|
|
1132
|
+
if (refFile) {
|
|
1133
|
+
try {
|
|
1134
|
+
refObj = JSON.parse(fs.readFileSync(refFile, "utf-8"));
|
|
1135
|
+
} catch {
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
if (!refObj) {
|
|
1140
|
+
addIssue({
|
|
1141
|
+
code: "REFERENCE_MISSING",
|
|
1142
|
+
severity: "error",
|
|
1143
|
+
message: `Referenced assumption ${ref} not found in workspace`
|
|
1144
|
+
});
|
|
1145
|
+
} else {
|
|
1146
|
+
try {
|
|
1147
|
+
const integrity = verifyArtifactIntegritySync(refObj);
|
|
1148
|
+
if (!integrity.ok) {
|
|
1149
|
+
addIssue({
|
|
1150
|
+
code: "REFERENCE_HASH_MISMATCH",
|
|
1151
|
+
severity: "error",
|
|
1152
|
+
message: `Referenced assumption ${ref} integrity check failed`
|
|
1153
|
+
});
|
|
1154
|
+
} else if (refObj.contentHash !== ref && refObj.artifactId !== ref) {
|
|
1155
|
+
addIssue({
|
|
1156
|
+
code: "REFERENCE_HASH_MISMATCH",
|
|
1157
|
+
severity: "error",
|
|
1158
|
+
message: `Assumption reference mismatch: expected ${ref}, got ${refObj.contentHash}`
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
} catch (e) {
|
|
1162
|
+
addIssue({
|
|
1163
|
+
code: "REFERENCE_CORRUPT",
|
|
1164
|
+
severity: "error",
|
|
1165
|
+
message: `Failed to verify assumption ${ref}`
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
let parentId;
|
|
1171
|
+
const lineage = v.lineage;
|
|
1172
|
+
if (lineage?.parentArtifactId && lineage?.parentArtifactId !== lineage?.artifactId) {
|
|
1173
|
+
parentId = lineage?.parentArtifactId;
|
|
1174
|
+
} else if (v.schema === "hardkas.signedTx") {
|
|
1175
|
+
parentId = v.sourcePlanId;
|
|
1176
|
+
} else if (v.schema === "hardkas.txReceipt") {
|
|
1177
|
+
parentId = v.sourceSignedId || lineage?.parentArtifactId;
|
|
1178
|
+
}
|
|
1179
|
+
if (parentId) {
|
|
1180
|
+
parentObj = context.resolveArtifact ? context.resolveArtifact(parentId) : null;
|
|
1181
|
+
if (!parentObj) {
|
|
1182
|
+
const parentFile = findFileByHash(parentId, searchDirs);
|
|
1183
|
+
if (parentFile) {
|
|
1184
|
+
try {
|
|
1185
|
+
parentObj = JSON.parse(fs.readFileSync(parentFile, "utf-8"));
|
|
1186
|
+
} catch (e) {
|
|
1187
|
+
addIssue({
|
|
1188
|
+
code: "PARENT_CORRUPT",
|
|
1189
|
+
severity: "error",
|
|
1190
|
+
message: `Failed to read parent ${parentId}: ${e.message}`
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
if (!parentObj) {
|
|
1196
|
+
addIssue({
|
|
1197
|
+
code: "PARENT_MISSING",
|
|
1198
|
+
severity: "warning",
|
|
1199
|
+
message: `Parent artifact ${parentId} not found in workspace`
|
|
1200
|
+
});
|
|
1201
|
+
} else {
|
|
1202
|
+
try {
|
|
1203
|
+
const parentSem = verifyArtifactSemantics(parentObj, { ...context, strict: true });
|
|
1204
|
+
if (!parentSem.ok) {
|
|
1205
|
+
parentSem.issues.forEach((issue) => addIssue(issue));
|
|
1206
|
+
}
|
|
1207
|
+
} catch (e) {
|
|
1208
|
+
addIssue({
|
|
1209
|
+
code: "PARENT_CORRUPT",
|
|
1210
|
+
severity: "error",
|
|
1211
|
+
message: `Failed to verify parent ${parentId}: ${e.message}`
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
902
1217
|
if (v.createdAt && typeof v.createdAt === "string") {
|
|
903
1218
|
const created = new Date(v.createdAt).getTime();
|
|
904
1219
|
const now = clock.now();
|
|
@@ -917,31 +1232,47 @@ function verifyArtifactSemantics(artifact, context = {}) {
|
|
|
917
1232
|
});
|
|
918
1233
|
}
|
|
919
1234
|
}
|
|
920
|
-
const lineageAudit = verifyLineage(v, context.parent, { strict });
|
|
1235
|
+
const lineageAudit = verifyLineage(v, parentObj || context.parent, { strict });
|
|
921
1236
|
if (!lineageAudit.ok || strict && !v.lineage && v.schema !== "hardkas.workflow.v1") {
|
|
922
1237
|
lineageAudit.issues.forEach((issue) => {
|
|
923
1238
|
addIssue(issue);
|
|
924
1239
|
});
|
|
925
1240
|
}
|
|
926
1241
|
if (strict) {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1242
|
+
const enforceMetadata = context.enforceMetadata ?? true;
|
|
1243
|
+
if (enforceMetadata) {
|
|
1244
|
+
if (!v.workflowId)
|
|
1245
|
+
addIssue({
|
|
1246
|
+
code: "MISSING_WORKFLOW_ID",
|
|
1247
|
+
severity: "error",
|
|
1248
|
+
message: "Strict mode requires workflowId"
|
|
1249
|
+
});
|
|
1250
|
+
if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
|
|
1251
|
+
addIssue({
|
|
1252
|
+
code: "MISSING_ASSUMPTION_LEVEL",
|
|
1253
|
+
severity: "error",
|
|
1254
|
+
message: "Strict mode requires assumptionLevel"
|
|
1255
|
+
});
|
|
1256
|
+
if (!v.executionMode && !v.mode)
|
|
1257
|
+
addIssue({
|
|
1258
|
+
code: "MISSING_EXECUTION_MODE",
|
|
1259
|
+
severity: "error",
|
|
1260
|
+
message: "Strict mode requires executionMode"
|
|
1261
|
+
});
|
|
1262
|
+
} else {
|
|
1263
|
+
if (!v.workflowId)
|
|
1264
|
+
addIssue({
|
|
1265
|
+
code: "MISSING_WORKFLOW_ID",
|
|
1266
|
+
severity: "warning",
|
|
1267
|
+
message: "Missing workflowId"
|
|
1268
|
+
});
|
|
1269
|
+
if (!v.assumptionLevel && v.schema !== "hardkas.workflow.v1")
|
|
1270
|
+
addIssue({
|
|
1271
|
+
code: "MISSING_ASSUMPTION_LEVEL",
|
|
1272
|
+
severity: "warning",
|
|
1273
|
+
message: "Missing assumptionLevel"
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
945
1276
|
} else {
|
|
946
1277
|
if (!v.workflowId)
|
|
947
1278
|
addIssue({
|
|
@@ -1214,6 +1545,16 @@ var InvariantWatcher = class {
|
|
|
1214
1545
|
};
|
|
1215
1546
|
|
|
1216
1547
|
// src/migration.ts
|
|
1548
|
+
var MigrationRequiredError = class extends Error {
|
|
1549
|
+
constructor(oldVersion, targetVersion) {
|
|
1550
|
+
super(`MIGRATION_REQUIRED: Artifact requires explicit migration from ${oldVersion} to ${targetVersion}`);
|
|
1551
|
+
this.oldVersion = oldVersion;
|
|
1552
|
+
this.targetVersion = targetVersion;
|
|
1553
|
+
this.name = "MigrationRequiredError";
|
|
1554
|
+
}
|
|
1555
|
+
oldVersion;
|
|
1556
|
+
targetVersion;
|
|
1557
|
+
};
|
|
1217
1558
|
var migrationRegistry = [];
|
|
1218
1559
|
function registerMigrationStep(step) {
|
|
1219
1560
|
const existing = migrationRegistry.find(
|
|
@@ -1235,6 +1576,9 @@ registerMigrationStep({
|
|
|
1235
1576
|
description: "Legacy v1 schemas to canonical 1.0.0-alpha format",
|
|
1236
1577
|
transform(artifact) {
|
|
1237
1578
|
const migrated = { ...artifact };
|
|
1579
|
+
if (migrated.lineage) {
|
|
1580
|
+
migrated.lineage = { ...migrated.lineage };
|
|
1581
|
+
}
|
|
1238
1582
|
if (typeof migrated.schema === "string" && migrated.schema.endsWith(".v1")) {
|
|
1239
1583
|
if (migrated.schema !== "hardkas.workflow.v1") {
|
|
1240
1584
|
migrated.schema = migrated.schema.replace(/\.v1$/, "");
|
|
@@ -1299,10 +1643,10 @@ function canMigrate(artifact, targetVersion = ARTIFACT_VERSION) {
|
|
|
1299
1643
|
if (currentVersion === targetVersion) {
|
|
1300
1644
|
return true;
|
|
1301
1645
|
}
|
|
1302
|
-
const
|
|
1303
|
-
return
|
|
1646
|
+
const path5 = getMigrationPath(currentVersion, targetVersion);
|
|
1647
|
+
return path5.length > 0;
|
|
1304
1648
|
}
|
|
1305
|
-
function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION) {
|
|
1649
|
+
function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION, options) {
|
|
1306
1650
|
const currentVersion = detectArtifactVersion(artifact);
|
|
1307
1651
|
if (currentVersion === targetVersion) {
|
|
1308
1652
|
return {
|
|
@@ -1312,8 +1656,11 @@ function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION) {
|
|
|
1312
1656
|
appliedSteps: []
|
|
1313
1657
|
};
|
|
1314
1658
|
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1659
|
+
if (options?.strictPolicy) {
|
|
1660
|
+
throw new MigrationRequiredError(currentVersion, targetVersion);
|
|
1661
|
+
}
|
|
1662
|
+
const path5 = getMigrationPath(currentVersion, targetVersion);
|
|
1663
|
+
if (path5.length === 0) {
|
|
1317
1664
|
throw new Error(
|
|
1318
1665
|
`No migration path from version "${currentVersion}" to "${targetVersion}". Registered steps: [${migrationRegistry.map((s) => `${s.fromVersion}\u2192${s.toVersion}`).join(", ")}]`
|
|
1319
1666
|
);
|
|
@@ -1322,7 +1669,7 @@ function migrateArtifactPayload(artifact, targetVersion = ARTIFACT_VERSION) {
|
|
|
1322
1669
|
const originalLineage = artifact.lineage;
|
|
1323
1670
|
let current = { ...artifact };
|
|
1324
1671
|
const appliedSteps = [];
|
|
1325
|
-
for (const step of
|
|
1672
|
+
for (const step of path5) {
|
|
1326
1673
|
current = step.transform(current);
|
|
1327
1674
|
appliedSteps.push({
|
|
1328
1675
|
fromVersion: step.fromVersion,
|
|
@@ -1355,10 +1702,51 @@ function migrateToCanonical(v1Artifact) {
|
|
|
1355
1702
|
const result = migrateArtifactPayload(v1Artifact, ARTIFACT_VERSION);
|
|
1356
1703
|
return result.artifact;
|
|
1357
1704
|
}
|
|
1705
|
+
function generateMigrationReceipt(oldArtifact, newArtifact, migrationId) {
|
|
1706
|
+
const oldHash = oldArtifact.contentHash || calculateContentHash(oldArtifact, CURRENT_HASH_VERSION);
|
|
1707
|
+
const newHash = newArtifact.contentHash || calculateContentHash(newArtifact, CURRENT_HASH_VERSION);
|
|
1708
|
+
const receipt = {
|
|
1709
|
+
schema: "hardkas.migrationReceipt.v1",
|
|
1710
|
+
hardkasVersion: HARDKAS_VERSION,
|
|
1711
|
+
version: ARTIFACT_VERSION,
|
|
1712
|
+
hashVersion: CURRENT_HASH_VERSION,
|
|
1713
|
+
networkId: oldArtifact.networkId || "simnet",
|
|
1714
|
+
mode: oldArtifact.mode || "simulated",
|
|
1715
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1716
|
+
oldHash,
|
|
1717
|
+
newHash,
|
|
1718
|
+
fromSchema: oldArtifact.schema || "unknown",
|
|
1719
|
+
toSchema: newArtifact.schema || "unknown",
|
|
1720
|
+
migrationId,
|
|
1721
|
+
decision: "MIGRATED_WITH_PROOF",
|
|
1722
|
+
lineage: {
|
|
1723
|
+
artifactId: "",
|
|
1724
|
+
// Filled after hash
|
|
1725
|
+
lineageId: oldArtifact.lineage?.lineageId || ("migration" + oldHash).padEnd(64, "0").slice(0, 64),
|
|
1726
|
+
parentArtifactId: oldHash,
|
|
1727
|
+
rootArtifactId: oldArtifact.lineage?.rootArtifactId || oldHash
|
|
1728
|
+
}
|
|
1729
|
+
};
|
|
1730
|
+
receipt.contentHash = calculateContentHash(receipt, CURRENT_HASH_VERSION);
|
|
1731
|
+
receipt.lineage.artifactId = receipt.contentHash;
|
|
1732
|
+
if (!newArtifact.lineage) {
|
|
1733
|
+
newArtifact.lineage = {
|
|
1734
|
+
artifactId: newHash,
|
|
1735
|
+
lineageId: receipt.lineage.lineageId,
|
|
1736
|
+
parentArtifactId: receipt.contentHash,
|
|
1737
|
+
rootArtifactId: receipt.lineage.rootArtifactId
|
|
1738
|
+
};
|
|
1739
|
+
} else {
|
|
1740
|
+
newArtifact.lineage.parentArtifactId = receipt.contentHash;
|
|
1741
|
+
}
|
|
1742
|
+
newArtifact.contentHash = calculateContentHash(newArtifact, CURRENT_HASH_VERSION);
|
|
1743
|
+
newArtifact.lineage.artifactId = newArtifact.contentHash;
|
|
1744
|
+
return receipt;
|
|
1745
|
+
}
|
|
1358
1746
|
|
|
1359
1747
|
// src/io.ts
|
|
1360
1748
|
import fs2 from "fs/promises";
|
|
1361
|
-
import
|
|
1749
|
+
import path2 from "path";
|
|
1362
1750
|
import { writeFileAtomic } from "@hardkas/core";
|
|
1363
1751
|
var bigIntReplacer = (_key, value) => typeof value === "bigint" ? value.toString() : value;
|
|
1364
1752
|
async function writeArtifact(filePath, artifact) {
|
|
@@ -1369,10 +1757,10 @@ async function writeArtifact(filePath, artifact) {
|
|
|
1369
1757
|
const artifactObj = typeof artifact === "string" ? JSON.parse(artifact) : artifact;
|
|
1370
1758
|
const id = artifactObj.planId || artifactObj.signedId || artifactObj.txId || Date.now().toString(36);
|
|
1371
1759
|
const prefix = artifactObj.schema ? artifactObj.schema.split(".")[1] || "artifact" : "artifact";
|
|
1372
|
-
targetPath =
|
|
1760
|
+
targetPath = path2.join(filePath, `${prefix}-${id}.json`);
|
|
1373
1761
|
console.log(
|
|
1374
1762
|
`
|
|
1375
|
-
Note: Provided path is a directory. Auto-generating artifact filename: ${
|
|
1763
|
+
Note: Provided path is a directory. Auto-generating artifact filename: ${path2.basename(targetPath)}`
|
|
1376
1764
|
);
|
|
1377
1765
|
}
|
|
1378
1766
|
} catch (e) {
|
|
@@ -1380,14 +1768,14 @@ Note: Provided path is a directory. Auto-generating artifact filename: ${path.ba
|
|
|
1380
1768
|
const artifactObj = typeof artifact === "string" ? JSON.parse(artifact) : artifact;
|
|
1381
1769
|
const id = artifactObj.planId || artifactObj.signedId || artifactObj.txId || Date.now().toString(36);
|
|
1382
1770
|
const prefix = artifactObj.schema ? artifactObj.schema.split(".")[1] || "artifact" : "artifact";
|
|
1383
|
-
targetPath =
|
|
1771
|
+
targetPath = path2.join(filePath, `${prefix}-${id}.json`);
|
|
1384
1772
|
}
|
|
1385
1773
|
}
|
|
1386
1774
|
const content = typeof artifact === "string" ? artifact : JSON.stringify(artifact, bigIntReplacer, 2) + "\n";
|
|
1387
1775
|
await writeFileAtomic(targetPath, content);
|
|
1388
1776
|
}
|
|
1389
1777
|
function getDefaultReceiptPath(txId, cwd = process.cwd()) {
|
|
1390
|
-
return
|
|
1778
|
+
return path2.join(cwd, "artifacts", "receipts", `${txId}.json`);
|
|
1391
1779
|
}
|
|
1392
1780
|
async function readArtifact(filePath) {
|
|
1393
1781
|
try {
|
|
@@ -1593,6 +1981,14 @@ function createTxPlanArtifact(options) {
|
|
|
1593
1981
|
amountSompi: o.amountSompi.toString()
|
|
1594
1982
|
})),
|
|
1595
1983
|
rpcUrl: options.rpcUrl,
|
|
1984
|
+
lineage: {
|
|
1985
|
+
artifactId: "",
|
|
1986
|
+
lineageId: "0".repeat(64),
|
|
1987
|
+
// placeholder, will be replaced if empty
|
|
1988
|
+
parentArtifactId: "",
|
|
1989
|
+
rootArtifactId: "",
|
|
1990
|
+
sequence: 1
|
|
1991
|
+
},
|
|
1596
1992
|
...options.ctx.workflowId ? { workflowId: options.ctx.workflowId } : {}
|
|
1597
1993
|
};
|
|
1598
1994
|
if (options.plan.change) {
|
|
@@ -1604,6 +2000,18 @@ function createTxPlanArtifact(options) {
|
|
|
1604
2000
|
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1605
2001
|
artifact.planId = `plan-${hash.slice(0, 16)}`;
|
|
1606
2002
|
artifact.contentHash = hash;
|
|
2003
|
+
if (artifact.lineage) {
|
|
2004
|
+
artifact.lineage.lineageId = artifact.contentHash;
|
|
2005
|
+
artifact.lineage.artifactId = artifact.contentHash;
|
|
2006
|
+
artifact.lineage.parentArtifactId = artifact.contentHash;
|
|
2007
|
+
artifact.lineage.rootArtifactId = artifact.contentHash;
|
|
2008
|
+
const finalHash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
2009
|
+
artifact.planId = `plan-${finalHash.slice(0, 16)}`;
|
|
2010
|
+
artifact.contentHash = finalHash;
|
|
2011
|
+
artifact.lineage.artifactId = finalHash;
|
|
2012
|
+
artifact.lineage.parentArtifactId = finalHash;
|
|
2013
|
+
artifact.lineage.rootArtifactId = finalHash;
|
|
2014
|
+
}
|
|
1607
2015
|
return artifact;
|
|
1608
2016
|
}
|
|
1609
2017
|
|
|
@@ -1628,11 +2036,21 @@ function createSimulatedSignedTxArtifact(plan, payload, ctx) {
|
|
|
1628
2036
|
format: "simulated",
|
|
1629
2037
|
payload
|
|
1630
2038
|
},
|
|
2039
|
+
lineage: {
|
|
2040
|
+
artifactId: "",
|
|
2041
|
+
lineageId: plan.lineage?.lineageId || plan.contentHash || "0".repeat(64),
|
|
2042
|
+
parentArtifactId: plan.contentHash || "0".repeat(64),
|
|
2043
|
+
rootArtifactId: plan.lineage?.rootArtifactId || plan.contentHash || "0".repeat(64),
|
|
2044
|
+
sequence: (plan.lineage?.sequence || 0) + 1
|
|
2045
|
+
},
|
|
1631
2046
|
...plan.workflowId ? { workflowId: plan.workflowId } : {}
|
|
1632
2047
|
};
|
|
1633
2048
|
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1634
2049
|
artifact.signedId = `signed-${hash.slice(0, 16)}`;
|
|
1635
2050
|
artifact.contentHash = hash;
|
|
2051
|
+
if (artifact.lineage) {
|
|
2052
|
+
artifact.lineage.artifactId = hash;
|
|
2053
|
+
}
|
|
1636
2054
|
return artifact;
|
|
1637
2055
|
}
|
|
1638
2056
|
function createSimulatedTxReceipt(plan, txId, ctx, extra) {
|
|
@@ -1658,10 +2076,22 @@ function createSimulatedTxReceipt(plan, txId, ctx, extra) {
|
|
|
1658
2076
|
preStateHash: extra?.preStateHash,
|
|
1659
2077
|
postStateHash: extra?.postStateHash,
|
|
1660
2078
|
dagContext: extra?.dagContext,
|
|
2079
|
+
lineage: {
|
|
2080
|
+
artifactId: "",
|
|
2081
|
+
lineageId: plan.lineage?.lineageId || plan.contentHash || "0".repeat(64),
|
|
2082
|
+
parentArtifactId: "0".repeat(64),
|
|
2083
|
+
// Will set to contentHash of signedTx later
|
|
2084
|
+
rootArtifactId: plan.lineage?.rootArtifactId || plan.contentHash || "0".repeat(64),
|
|
2085
|
+
sequence: (plan.lineage?.sequence || 1) + 1
|
|
2086
|
+
},
|
|
1661
2087
|
...plan.workflowId ? { workflowId: plan.workflowId } : {}
|
|
1662
2088
|
};
|
|
1663
2089
|
const hash = calculateContentHash(artifact, CURRENT_HASH_VERSION);
|
|
1664
2090
|
artifact.contentHash = hash;
|
|
2091
|
+
if (artifact.lineage) {
|
|
2092
|
+
artifact.lineage.artifactId = hash;
|
|
2093
|
+
artifact.lineage.parentArtifactId = extra?.preStateHash || txId.replace("simulated-", "").replace("-tx", "").padEnd(64, "0").slice(0, 64);
|
|
2094
|
+
}
|
|
1665
2095
|
return artifact;
|
|
1666
2096
|
}
|
|
1667
2097
|
function getBroadcastableSignedTransaction(artifact) {
|
|
@@ -1878,15 +2308,15 @@ async function explainArtifact(artifactUnknown) {
|
|
|
1878
2308
|
|
|
1879
2309
|
// src/igra-io.ts
|
|
1880
2310
|
import fs3 from "fs/promises";
|
|
1881
|
-
import
|
|
2311
|
+
import path3 from "path";
|
|
1882
2312
|
import { deterministicCompare as deterministicCompare3 } from "@hardkas/core";
|
|
1883
2313
|
function getDefaultL2ReceiptsDir(cwd = process.cwd()) {
|
|
1884
|
-
return
|
|
2314
|
+
return path3.join(cwd, ".hardkas", "l2-receipts");
|
|
1885
2315
|
}
|
|
1886
2316
|
function getL2ReceiptPath(txHash, options) {
|
|
1887
2317
|
validateTxHash(txHash);
|
|
1888
2318
|
const dir = getDefaultL2ReceiptsDir(options?.cwd);
|
|
1889
|
-
return
|
|
2319
|
+
return path3.join(dir, `${txHash}.igra.receipt.json`);
|
|
1890
2320
|
}
|
|
1891
2321
|
async function saveIgraTxReceiptArtifact(receipt, options) {
|
|
1892
2322
|
assertValidIgraTxReceiptArtifact(receipt);
|
|
@@ -1908,7 +2338,7 @@ async function listIgraTxReceiptArtifacts(options) {
|
|
|
1908
2338
|
const receipts = [];
|
|
1909
2339
|
for (const file of receiptFiles) {
|
|
1910
2340
|
try {
|
|
1911
|
-
const data = await readArtifact(
|
|
2341
|
+
const data = await readArtifact(path3.join(dir, file));
|
|
1912
2342
|
if (data && typeof data === "object" && data.schema === "hardkas.igraTxReceipt.v1") {
|
|
1913
2343
|
receipts.push(data);
|
|
1914
2344
|
}
|
|
@@ -1941,26 +2371,26 @@ function diffArtifacts(left, right) {
|
|
|
1941
2371
|
entries
|
|
1942
2372
|
};
|
|
1943
2373
|
}
|
|
1944
|
-
function compareRecursive(left, right,
|
|
2374
|
+
function compareRecursive(left, right, path5, entries) {
|
|
1945
2375
|
if (isPrimitive(left) || isPrimitive(right)) {
|
|
1946
2376
|
if (left !== right) {
|
|
1947
|
-
entries.push({ path:
|
|
2377
|
+
entries.push({ path: path5, kind: "changed", left, right });
|
|
1948
2378
|
}
|
|
1949
2379
|
return;
|
|
1950
2380
|
}
|
|
1951
2381
|
if (Array.isArray(left) || Array.isArray(right)) {
|
|
1952
2382
|
if (!Array.isArray(left) || !Array.isArray(right)) {
|
|
1953
|
-
entries.push({ path:
|
|
2383
|
+
entries.push({ path: path5, kind: "changed", left, right });
|
|
1954
2384
|
return;
|
|
1955
2385
|
}
|
|
1956
2386
|
const maxLength = Math.max(left.length, right.length);
|
|
1957
2387
|
for (let i = 0; i < maxLength; i++) {
|
|
1958
2388
|
if (i >= left.length) {
|
|
1959
|
-
entries.push({ path: `${
|
|
2389
|
+
entries.push({ path: `${path5}[${i}]`, kind: "added", right: right[i] });
|
|
1960
2390
|
} else if (i >= right.length) {
|
|
1961
|
-
entries.push({ path: `${
|
|
2391
|
+
entries.push({ path: `${path5}[${i}]`, kind: "removed", left: left[i] });
|
|
1962
2392
|
} else {
|
|
1963
|
-
compareRecursive(left[i], right[i], `${
|
|
2393
|
+
compareRecursive(left[i], right[i], `${path5}[${i}]`, entries);
|
|
1964
2394
|
}
|
|
1965
2395
|
}
|
|
1966
2396
|
return;
|
|
@@ -1969,7 +2399,7 @@ function compareRecursive(left, right, path4, entries) {
|
|
|
1969
2399
|
const rightKeys = Object.keys(right).filter((k) => !SEMANTIC_EXCLUSIONS.has(k));
|
|
1970
2400
|
const allKeys = /* @__PURE__ */ new Set([...leftKeys, ...rightKeys]);
|
|
1971
2401
|
for (const key of allKeys) {
|
|
1972
|
-
const nextPath =
|
|
2402
|
+
const nextPath = path5 === "$" ? key : `${path5}.${key}`;
|
|
1973
2403
|
if (!leftKeys.includes(key)) {
|
|
1974
2404
|
entries.push({ path: nextPath, kind: "added", right: right[key] });
|
|
1975
2405
|
} else if (!rightKeys.includes(key)) {
|
|
@@ -2033,16 +2463,16 @@ function updateDeploymentStatus(record, newStatus, txId) {
|
|
|
2033
2463
|
// src/deployment-store.ts
|
|
2034
2464
|
import fs4 from "fs/promises";
|
|
2035
2465
|
import { existsSync } from "fs";
|
|
2036
|
-
import
|
|
2466
|
+
import path4 from "path";
|
|
2037
2467
|
import { writeFileAtomic as writeFileAtomic2 } from "@hardkas/core";
|
|
2038
2468
|
async function saveDeployment(rootDir, record) {
|
|
2039
|
-
const deploymentsDir =
|
|
2040
|
-
const targetPath =
|
|
2469
|
+
const deploymentsDir = path4.join(rootDir, ".hardkas", "deployments", record.networkId);
|
|
2470
|
+
const targetPath = path4.join(deploymentsDir, `${record.label}.json`);
|
|
2041
2471
|
await writeFileAtomic2(targetPath, JSON.stringify(record, null, 2));
|
|
2042
2472
|
return targetPath;
|
|
2043
2473
|
}
|
|
2044
2474
|
async function loadDeployment(rootDir, networkId, label) {
|
|
2045
|
-
const targetPath =
|
|
2475
|
+
const targetPath = path4.join(
|
|
2046
2476
|
rootDir,
|
|
2047
2477
|
".hardkas",
|
|
2048
2478
|
"deployments",
|
|
@@ -2054,18 +2484,18 @@ async function loadDeployment(rootDir, networkId, label) {
|
|
|
2054
2484
|
return JSON.parse(content);
|
|
2055
2485
|
}
|
|
2056
2486
|
async function listDeployments(rootDir, networkId) {
|
|
2057
|
-
const baseDir =
|
|
2487
|
+
const baseDir = path4.join(rootDir, ".hardkas", "deployments");
|
|
2058
2488
|
if (!existsSync(baseDir)) return [];
|
|
2059
2489
|
const summaries = [];
|
|
2060
2490
|
const networks = networkId ? [networkId] : await fs4.readdir(baseDir);
|
|
2061
2491
|
for (const net of networks) {
|
|
2062
|
-
const netDir =
|
|
2492
|
+
const netDir = path4.join(baseDir, net);
|
|
2063
2493
|
if (!existsSync(netDir)) continue;
|
|
2064
2494
|
const files = await fs4.readdir(netDir);
|
|
2065
2495
|
for (const file of files) {
|
|
2066
2496
|
if (!file.endsWith(".json")) continue;
|
|
2067
2497
|
try {
|
|
2068
|
-
const content = await fs4.readFile(
|
|
2498
|
+
const content = await fs4.readFile(path4.join(netDir, file), "utf-8");
|
|
2069
2499
|
const record = JSON.parse(content);
|
|
2070
2500
|
const summary = {
|
|
2071
2501
|
label: record.label,
|
|
@@ -2098,7 +2528,7 @@ async function updateDeployment(rootDir, networkId, label, update) {
|
|
|
2098
2528
|
return updated;
|
|
2099
2529
|
}
|
|
2100
2530
|
async function deleteDeployment(rootDir, networkId, label) {
|
|
2101
|
-
const targetPath =
|
|
2531
|
+
const targetPath = path4.join(
|
|
2102
2532
|
rootDir,
|
|
2103
2533
|
".hardkas",
|
|
2104
2534
|
"deployments",
|
|
@@ -2114,6 +2544,7 @@ export {
|
|
|
2114
2544
|
ARTIFACT_VERSION,
|
|
2115
2545
|
AccountRefSchema,
|
|
2116
2546
|
ArtifactLineageSchema,
|
|
2547
|
+
AssumptionSchema,
|
|
2117
2548
|
BaseArtifactSchema,
|
|
2118
2549
|
BasicCorrelationInvariant,
|
|
2119
2550
|
BasicLineageInvariant,
|
|
@@ -2124,7 +2555,11 @@ export {
|
|
|
2124
2555
|
InvariantWatcher,
|
|
2125
2556
|
LifecycleInvariant,
|
|
2126
2557
|
LocalnetUtxoSchemaV2,
|
|
2558
|
+
MigrationReceiptSchema,
|
|
2559
|
+
MigrationRequiredError,
|
|
2127
2560
|
NetworkInvariant,
|
|
2561
|
+
NetworkProfileSchema,
|
|
2562
|
+
PolicySchema,
|
|
2128
2563
|
ReplayInvariant,
|
|
2129
2564
|
RuntimeSessionSchema,
|
|
2130
2565
|
SEMANTIC_EXCLUSIONS,
|
|
@@ -2169,6 +2604,7 @@ export {
|
|
|
2169
2604
|
formatSignedTxArtifact,
|
|
2170
2605
|
formatTxPlanArtifact,
|
|
2171
2606
|
formatTxReceiptArtifact,
|
|
2607
|
+
generateMigrationReceipt,
|
|
2172
2608
|
getBroadcastableSignedTransaction,
|
|
2173
2609
|
getDefaultL2ReceiptsDir,
|
|
2174
2610
|
getDefaultReceiptPath,
|
|
@@ -2207,6 +2643,7 @@ export {
|
|
|
2207
2643
|
verifyArtifact,
|
|
2208
2644
|
verifyArtifactFile,
|
|
2209
2645
|
verifyArtifactIntegrity,
|
|
2646
|
+
verifyArtifactIntegritySync,
|
|
2210
2647
|
verifyArtifactReplay,
|
|
2211
2648
|
verifyArtifactSemantics,
|
|
2212
2649
|
verifyFeeSemantics,
|