@hcmai/cli 0.3.5 → 0.3.6

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.js CHANGED
@@ -8651,7 +8651,7 @@ import { createReadStream as createReadStream2, promises as fs8 } from "fs";
8651
8651
  import path8 from "path";
8652
8652
  import { CliError as CliError22, CliErrorCode as CliErrorCode21, formatObject as formatObject20 } from "@hcmai/sdk";
8653
8653
  init_exit();
8654
- var EXECUTION_CONTRACT_VERSION = "2026-08-28.controlled-v1";
8654
+ var EXECUTION_CONTRACT_VERSION = "2026-08-29.controlled-v2";
8655
8655
  var DEFAULT_TTL_SECONDS = 15 * 60;
8656
8656
  var MIN_TTL_SECONDS = 60;
8657
8657
  var MAX_TTL_SECONDS = 60 * 60;
@@ -8667,6 +8667,7 @@ async function prepareDeliveryExecution(input) {
8667
8667
  }
8668
8668
  const change = await bindDocument(project, input.changeRef, "\u53D8\u66F4\u8BF4\u660E");
8669
8669
  const rollback = await bindDocument(project, input.rollbackRef, "\u56DE\u6EDA\u8BF4\u660E");
8670
+ const payloads = await bindPayloadFiles(project, input.argv);
8670
8671
  const evidence = await bindEvidenceDirectory(project, input.evidenceDir);
8671
8672
  const { bytes: lockBytes, runtime: lockedRuntime } = await readChironLock(project);
8672
8673
  const runtime = await (input.runtimeIdentity ?? currentRuntimeIdentity)();
@@ -8683,6 +8684,7 @@ async function prepareDeliveryExecution(input) {
8683
8684
  runtime,
8684
8685
  assessment,
8685
8686
  documents: { change, rollback },
8687
+ payloads,
8686
8688
  evidenceDir: evidence.relative
8687
8689
  };
8688
8690
  const planId = sha2567(canonicalJson(core)).slice(0, 24);
@@ -8738,6 +8740,7 @@ async function executeDeliveryPlan(input) {
8738
8740
  }
8739
8741
  await assertDocumentUnchanged(project, plan.documents.change, "\u53D8\u66F4\u8BF4\u660E");
8740
8742
  await assertDocumentUnchanged(project, plan.documents.rollback, "\u56DE\u6EDA\u8BF4\u660E");
8743
+ await assertPayloadsUnchanged(project, plan.payloads);
8741
8744
  const evidenceDir = await bindEvidenceDirectory(project, plan.evidenceDir);
8742
8745
  const receiptFile = path8.join(evidenceDir.absolute, `${plan.planId}.receipt.json`);
8743
8746
  if (await pathExists(receiptFile)) throw invalid4(`\u6267\u884C\u6536\u636E\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u518D\u6B21\u6267\u884C\uFF1A${plan.planId}`);
@@ -8926,12 +8929,12 @@ function validateSupportedCommandShape(reasonCode, argv) {
8926
8929
  return;
8927
8930
  }
8928
8931
  if (reasonCode === "record-create") {
8929
- requireFlagValue(argv, "--data", "create \u5FC5\u987B\u5305\u542B --data <JSON>");
8932
+ requireExactlyOnePayload(argv, "create");
8930
8933
  return;
8931
8934
  }
8932
8935
  if (reasonCode === "record-update") {
8933
8936
  requireFlagValue(argv, "--id", "update \u5FC5\u987B\u5305\u542B --id <id>");
8934
- requireFlagValue(argv, "--data", "update \u5FC5\u987B\u5305\u542B --data <JSON>");
8937
+ requireExactlyOnePayload(argv, "update");
8935
8938
  return;
8936
8939
  }
8937
8940
  if (reasonCode === "cache-mutation") {
@@ -8962,6 +8965,40 @@ function optionalFlagValue(argv, flag) {
8962
8965
  }
8963
8966
  return void 0;
8964
8967
  }
8968
+ function requireExactlyOnePayload(argv, command) {
8969
+ const inline = optionalFlagValue(argv, "--data") !== void 0;
8970
+ const fromFile = optionalFlagValue(argv, "--data-file") !== void 0;
8971
+ if (inline && fromFile) {
8972
+ throw invalid4(`${command} \u7684 --data \u4E0E --data-file \u4E92\u65A5\uFF0C\u53EA\u80FD\u7ED9\u4E00\u4E2A`);
8973
+ }
8974
+ if (!inline && !fromFile) {
8975
+ throw invalid4(`${command} \u5FC5\u987B\u5305\u542B --data <JSON> \u6216 --data-file <\u6587\u4EF6>`);
8976
+ }
8977
+ }
8978
+ var PAYLOAD_FILE_FLAGS = ["--data-file", "--params-file"];
8979
+ async function bindPayloadFiles(project, argv) {
8980
+ const bound = [];
8981
+ for (const flag of PAYLOAD_FILE_FLAGS) {
8982
+ const reference = optionalFlagValue(argv, flag);
8983
+ if (reference === void 0) continue;
8984
+ bound.push(await bindPayloadFile(project, reference, `${flag} \u8F7D\u8377`));
8985
+ }
8986
+ return bound;
8987
+ }
8988
+ async function bindPayloadFile(project, reference, label) {
8989
+ const relative2 = safeRelative(reference, label);
8990
+ const file = path8.join(project, relative2);
8991
+ const bytes = await readSafeFile(project, file, label);
8992
+ return { path: relative2, sha256: sha2567(bytes) };
8993
+ }
8994
+ async function assertPayloadsUnchanged(project, payloads) {
8995
+ for (const payload of payloads) {
8996
+ const current = await bindPayloadFile(project, payload.path, `\u8F7D\u8377 ${payload.path}`);
8997
+ if (current.sha256 !== payload.sha256) {
8998
+ throw invalid4(`\u8F7D\u8377\u6587\u4EF6 ${payload.path} \u7684\u5185\u5BB9\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0 prepare`);
8999
+ }
9000
+ }
9001
+ }
8965
9002
  function requireFlagValue(argv, flag, message) {
8966
9003
  for (let index = 0; index < argv.length; index += 1) {
8967
9004
  const value = argv[index];
@@ -9100,7 +9137,7 @@ function isRuntimeIdentity(value) {
9100
9137
  }
9101
9138
  function isExecutionPlan(value) {
9102
9139
  if (!isRecord(value)) return false;
9103
- return value.schemaVersion === 1 && value.contractVersion === EXECUTION_CONTRACT_VERSION && typeof value.planId === "string" && PLAN_ID_PATTERN.test(value.planId) && typeof value.createdAt === "string" && typeof value.expiresAt === "string" && isSha(value.nonceSha256) && isSha(value.chironLockSha256) && isRuntimeIdentity(value.runtime) && isRecord(value.assessment) && isRecord(value.documents) && isBoundDocument(value.documents.change) && isBoundDocument(value.documents.rollback) && typeof value.evidenceDir === "string";
9140
+ return value.schemaVersion === 1 && value.contractVersion === EXECUTION_CONTRACT_VERSION && typeof value.planId === "string" && PLAN_ID_PATTERN.test(value.planId) && typeof value.createdAt === "string" && typeof value.expiresAt === "string" && isSha(value.nonceSha256) && isSha(value.chironLockSha256) && isRuntimeIdentity(value.runtime) && isRecord(value.assessment) && isRecord(value.documents) && isBoundDocument(value.documents.change) && isBoundDocument(value.documents.rollback) && Array.isArray(value.payloads) && value.payloads.every(isBoundDocument) && typeof value.evidenceDir === "string";
9104
9141
  }
9105
9142
  function isBoundDocument(value) {
9106
9143
  return isRecord(value) && typeof value.path === "string" && isSha(value.sha256);