@agentcomms/events-daemon 0.24.0 → 0.26.0

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.
@@ -1,4 +1,4 @@
1
- import { t as canonicalSecretWebhookUrl } from "./webhook-target-DyDTwWhV.mjs";
1
+ import { a as LAYA_MODEL_FAILURE_CODES, m as JUDGE_KINDS, t as canonicalSecretWebhookUrl } from "./webhook-target-EzLIFpIY.mjs";
2
2
  import { createCipheriv, createDecipheriv, hkdfSync, randomBytes } from "node:crypto";
3
3
  import "node:fs/promises";
4
4
  import { FileSecretStore, KeychainSecretStore, canonicalJson, keychainNamespace, loadKeyringModule, sha256Hex, withFileLock } from "@agentcomms/core";
@@ -354,7 +354,7 @@ var EventSecretStore = class {
354
354
  this.assertSelectedBackend();
355
355
  const row = this.#database.prepare("SELECT secret_ref, retired_at FROM event_secret_masters WHERE key_id = ?").get(input.keyId);
356
356
  if (row === void 0 || row.retired_at === null) throw new EventSecretError("EVENT_MASTER_UNKNOWN", "only a known retired event master may be destroyed");
357
- const { RECORD_LAYOUTS } = await import("./records-DjE5a4_H.mjs");
357
+ const { RECORD_LAYOUTS } = await import("./records-qtNEBi7g.mjs");
358
358
  for (const layout of RECORD_LAYOUTS) {
359
359
  const records = this.#database.prepare(`SELECT ${layout.sqlColumn} AS record FROM ${layout.table} WHERE ${layout.sqlColumn} IS NOT NULL`).all();
360
360
  for (const record of records) {
@@ -887,6 +887,103 @@ function unreadableRecordReason(error) {
887
887
  }
888
888
  return null;
889
889
  }
890
+ function layaModelText(value, name) {
891
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${name} is a non-empty string`);
892
+ return value;
893
+ }
894
+ function layaModelInteger(value, name) {
895
+ if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${name} is a non-negative safe integer`);
896
+ return value;
897
+ }
898
+ function layaModelState(value) {
899
+ if (value === "installing" || value === "downloading" || value === "ready" || value === "failed" || value === "removed") return value;
900
+ throw new Error("the model state is closed");
901
+ }
902
+ function layaModelFailureCode(value, name) {
903
+ if (value === null || value === void 0) return null;
904
+ if (LAYA_MODEL_FAILURE_CODES.includes(value)) return value;
905
+ throw new Error(`${name} is closed`);
906
+ }
907
+ /**
908
+ * The model-state repository is intentionally not an enablement mechanism. Callers hold an immediate transaction;
909
+ * the pointer is re-read in that same transaction directly before the write so a pre-claim or disabled lifecycle
910
+ * cannot leave a model row behind.
911
+ */
912
+ var LayaModelRepository = class {
913
+ #database;
914
+ constructor(database) {
915
+ this.#database = database;
916
+ }
917
+ write(input) {
918
+ if (this.#database.prepare("SELECT version FROM active_versions WHERE kind = 'judge-kind' AND object_id = ?").get(JUDGE_KINDS[1]) === void 0) throw new Error("the active Laya judge-kind pointer is required before model state changes");
919
+ const record = {
920
+ manifestId: layaModelText(input.manifestId, "the model manifest id"),
921
+ state: layaModelState(input.state),
922
+ bytesVerified: layaModelInteger(input.bytesVerified, "the verified model bytes"),
923
+ verifiedAt: input.verifiedAt === void 0 || input.verifiedAt === null ? null : layaModelInteger(input.verifiedAt, "the model verification time"),
924
+ failureCode: layaModelFailureCode(input.failureCode, "the model failure code"),
925
+ updatedAt: layaModelInteger(input.now, "the model update time")
926
+ };
927
+ const enabled = this.#database.prepare(`SELECT versions.document
928
+ FROM active_versions AS active
929
+ JOIN judge_kind_versions AS versions
930
+ ON versions.kind = active.object_id AND versions.version = active.version
931
+ WHERE active.kind = 'judge-kind' AND active.object_id = ? AND versions.revoked_at IS NULL`).get(JUDGE_KINDS[1]);
932
+ let enabledManifestId;
933
+ try {
934
+ const manifestId = JSON.parse(enabled?.document ?? "null").manifest?.manifestId;
935
+ if (typeof manifestId === "string" && manifestId.length > 0) enabledManifestId = manifestId;
936
+ } catch {}
937
+ if (enabledManifestId === void 0) throw new Error("the active Laya judge-kind pointer has no reviewed manifest");
938
+ if (record.manifestId !== enabledManifestId) throw new Error("the model manifest must match the active Laya judge-kind pointer");
939
+ this.#database.prepare(`INSERT INTO laya_models
940
+ (manifest_id, state, bytes_verified, verified_at, failure_code, updated_at)
941
+ VALUES (?, ?, ?, ?, ?, ?)
942
+ ON CONFLICT(manifest_id) DO UPDATE SET
943
+ state = excluded.state,
944
+ bytes_verified = excluded.bytes_verified,
945
+ verified_at = excluded.verified_at,
946
+ failure_code = excluded.failure_code,
947
+ updated_at = excluded.updated_at`).run(record.manifestId, record.state, record.bytesVerified, record.verifiedAt, record.failureCode, record.updatedAt);
948
+ return record;
949
+ }
950
+ /**
951
+ * `judge model remove` is the one model-state change made while Laya is disabled, so it carries the opposite fence:
952
+ * the same transaction re-reads the pointer and refuses if a later enablement claimed it. It records only the
953
+ * reviewed manifest id and the closed `removed` state.
954
+ */
955
+ markRemovedWhileDisabled(input) {
956
+ if (this.#database.prepare("SELECT version FROM active_versions WHERE kind = 'judge-kind' AND object_id = ?").get(JUDGE_KINDS[1]) !== void 0) throw new Error("a Laya model is removed only while its judge kind is disabled");
957
+ const record = {
958
+ manifestId: layaModelText(input.manifestId, "the model manifest id"),
959
+ state: "removed",
960
+ bytesVerified: 0,
961
+ verifiedAt: null,
962
+ failureCode: null,
963
+ updatedAt: layaModelInteger(input.now, "the model update time")
964
+ };
965
+ this.#database.prepare(`INSERT INTO laya_models
966
+ (manifest_id, state, bytes_verified, verified_at, failure_code, updated_at)
967
+ VALUES (?, 'removed', 0, NULL, NULL, ?)
968
+ ON CONFLICT(manifest_id) DO UPDATE SET
969
+ state = 'removed', bytes_verified = 0, verified_at = NULL, failure_code = NULL,
970
+ updated_at = excluded.updated_at`).run(record.manifestId, record.updatedAt);
971
+ return record;
972
+ }
973
+ get(manifestId) {
974
+ const row = this.#database.prepare(`SELECT manifest_id, state, bytes_verified, verified_at, failure_code, updated_at
975
+ FROM laya_models WHERE manifest_id = ?`).get(layaModelText(manifestId, "the model manifest id"));
976
+ if (row === void 0) return null;
977
+ return {
978
+ manifestId: layaModelText(row.manifest_id, "stored model manifest id"),
979
+ state: layaModelState(row.state),
980
+ bytesVerified: layaModelInteger(row.bytes_verified, "stored verified model bytes"),
981
+ verifiedAt: row.verified_at === null ? null : layaModelInteger(row.verified_at, "stored verification time"),
982
+ failureCode: layaModelFailureCode(row.failure_code, "stored model failure code"),
983
+ updatedAt: layaModelInteger(row.updated_at, "stored model update time")
984
+ };
985
+ }
986
+ };
890
987
  /** Each encrypted column, with its table's primary key in the order the v1 migration declares it — the AAD order. */
891
988
  const RECORD_LAYOUTS = [
892
989
  {
@@ -1140,4 +1237,4 @@ var EventRecordCipher = class {
1140
1237
  }
1141
1238
  };
1142
1239
  //#endregion
1143
- export { WriterQuiescer as a, openEventSecretStore as c, unreadableRecordReason as i, RECORD_LAYOUTS as n, withEventWriterLease as o, RecordStorageError as r, migrateEventSecrets as s, EventRecordCipher as t };
1240
+ export { unreadableRecordReason as a, migrateEventSecrets as c, RecordStorageError as i, openEventSecretStore as l, LayaModelRepository as n, WriterQuiescer as o, RECORD_LAYOUTS as r, withEventWriterLease as s, EventRecordCipher as t };
@@ -0,0 +1,2 @@
1
+ import { r as RECORD_LAYOUTS } from "./records-D15LoVeb.mjs";
2
+ export { RECORD_LAYOUTS };