@apexops/kernel 0.10.0-next.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.
Files changed (110) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/benchmark.d.ts +14 -0
  3. package/dist/benchmark.d.ts.map +1 -0
  4. package/dist/benchmark.js +29 -0
  5. package/dist/benchmark.js.map +1 -0
  6. package/dist/canonical.d.ts +10 -0
  7. package/dist/canonical.d.ts.map +1 -0
  8. package/dist/canonical.js +52 -0
  9. package/dist/canonical.js.map +1 -0
  10. package/dist/content-cache.d.ts +18 -0
  11. package/dist/content-cache.d.ts.map +1 -0
  12. package/dist/content-cache.js +94 -0
  13. package/dist/content-cache.js.map +1 -0
  14. package/dist/event-journal.d.ts +20 -0
  15. package/dist/event-journal.d.ts.map +1 -0
  16. package/dist/event-journal.js +136 -0
  17. package/dist/event-journal.js.map +1 -0
  18. package/dist/evidence-store.d.ts +42 -0
  19. package/dist/evidence-store.d.ts.map +1 -0
  20. package/dist/evidence-store.js +151 -0
  21. package/dist/evidence-store.js.map +1 -0
  22. package/dist/files.d.ts +6 -0
  23. package/dist/files.d.ts.map +1 -0
  24. package/dist/files.js +33 -0
  25. package/dist/files.js.map +1 -0
  26. package/dist/gates.d.ts +6 -0
  27. package/dist/gates.d.ts.map +1 -0
  28. package/dist/gates.js +25 -0
  29. package/dist/gates.js.map +1 -0
  30. package/dist/improvement-store.d.ts +48 -0
  31. package/dist/improvement-store.d.ts.map +1 -0
  32. package/dist/improvement-store.js +263 -0
  33. package/dist/improvement-store.js.map +1 -0
  34. package/dist/index.d.ts +18 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +18 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/lease-store.d.ts +23 -0
  39. package/dist/lease-store.d.ts.map +1 -0
  40. package/dist/lease-store.js +108 -0
  41. package/dist/lease-store.js.map +1 -0
  42. package/dist/object-store.d.ts +10 -0
  43. package/dist/object-store.d.ts.map +1 -0
  44. package/dist/object-store.js +86 -0
  45. package/dist/object-store.js.map +1 -0
  46. package/dist/project-store.d.ts +30 -0
  47. package/dist/project-store.d.ts.map +1 -0
  48. package/dist/project-store.js +72 -0
  49. package/dist/project-store.js.map +1 -0
  50. package/dist/run-repository.d.ts +38 -0
  51. package/dist/run-repository.d.ts.map +1 -0
  52. package/dist/run-repository.js +151 -0
  53. package/dist/run-repository.js.map +1 -0
  54. package/dist/tasks.d.ts +14 -0
  55. package/dist/tasks.d.ts.map +1 -0
  56. package/dist/tasks.js +96 -0
  57. package/dist/tasks.js.map +1 -0
  58. package/dist/test/canonical.test.d.ts +2 -0
  59. package/dist/test/canonical.test.d.ts.map +1 -0
  60. package/dist/test/canonical.test.js +18 -0
  61. package/dist/test/canonical.test.js.map +1 -0
  62. package/dist/test/improvement-store.test.d.ts +2 -0
  63. package/dist/test/improvement-store.test.d.ts.map +1 -0
  64. package/dist/test/improvement-store.test.js +130 -0
  65. package/dist/test/improvement-store.test.js.map +1 -0
  66. package/dist/test/journal-lease.test.d.ts +2 -0
  67. package/dist/test/journal-lease.test.d.ts.map +1 -0
  68. package/dist/test/journal-lease.test.js +124 -0
  69. package/dist/test/journal-lease.test.js.map +1 -0
  70. package/dist/test/policies.test.d.ts +2 -0
  71. package/dist/test/policies.test.d.ts.map +1 -0
  72. package/dist/test/policies.test.js +115 -0
  73. package/dist/test/policies.test.js.map +1 -0
  74. package/dist/test/run-repository.test.d.ts +2 -0
  75. package/dist/test/run-repository.test.d.ts.map +1 -0
  76. package/dist/test/run-repository.test.js +100 -0
  77. package/dist/test/run-repository.test.js.map +1 -0
  78. package/dist/test/storage.test.d.ts +2 -0
  79. package/dist/test/storage.test.d.ts.map +1 -0
  80. package/dist/test/storage.test.js +41 -0
  81. package/dist/test/storage.test.js.map +1 -0
  82. package/dist/test/workflow-engine.test.d.ts +2 -0
  83. package/dist/test/workflow-engine.test.d.ts.map +1 -0
  84. package/dist/test/workflow-engine.test.js +108 -0
  85. package/dist/test/workflow-engine.test.js.map +1 -0
  86. package/dist/test/workflow.test.d.ts +2 -0
  87. package/dist/test/workflow.test.d.ts.map +1 -0
  88. package/dist/test/workflow.test.js +119 -0
  89. package/dist/test/workflow.test.js.map +1 -0
  90. package/dist/test/writer-transfer.test.d.ts +2 -0
  91. package/dist/test/writer-transfer.test.d.ts.map +1 -0
  92. package/dist/test/writer-transfer.test.js +355 -0
  93. package/dist/test/writer-transfer.test.js.map +1 -0
  94. package/dist/validator-registry.d.ts +22 -0
  95. package/dist/validator-registry.d.ts.map +1 -0
  96. package/dist/validator-registry.js +42 -0
  97. package/dist/validator-registry.js.map +1 -0
  98. package/dist/workflow-engine.d.ts +72 -0
  99. package/dist/workflow-engine.d.ts.map +1 -0
  100. package/dist/workflow-engine.js +269 -0
  101. package/dist/workflow-engine.js.map +1 -0
  102. package/dist/workflow-validator-ownership.d.ts +12 -0
  103. package/dist/workflow-validator-ownership.d.ts.map +1 -0
  104. package/dist/workflow-validator-ownership.js +163 -0
  105. package/dist/workflow-validator-ownership.js.map +1 -0
  106. package/dist/writer-transfer.d.ts +78 -0
  107. package/dist/writer-transfer.d.ts.map +1 -0
  108. package/dist/writer-transfer.js +313 -0
  109. package/dist/writer-transfer.js.map +1 -0
  110. package/package.json +39 -0
@@ -0,0 +1,119 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtemp } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ import { Type } from "@sinclair/typebox";
7
+ import { assertTaskCurrent, createTaskEnvelope, inheritGate, needsInput, ProjectStore, validateInputAnswers, ValidatorRegistry, } from "../index.js";
8
+ const hash = "a".repeat(64);
9
+ test("project store creates deterministic project and run layouts with four closed gates", async () => {
10
+ const root = await mkdtemp(join(tmpdir(), "apex-project-"));
11
+ const clock = () => new Date("2026-01-01T00:00:00.000Z");
12
+ const store = new ProjectStore(root, clock, () => "run-fixed");
13
+ await store.initializeProject({ projectId: "demo", displayName: "Demo", defaultIacTool: "bicep" });
14
+ const run = await store.createRun("demo", {
15
+ environment: "dev",
16
+ targetScope: "/subscriptions/test",
17
+ runtimeLockHash: hash,
18
+ });
19
+ assert.equal(run.runId, "run-fixed");
20
+ assert.deepEqual(run.gates.map(({ gate, state }) => ({ gate, state })), [
21
+ { gate: 1, state: "closed" },
22
+ { gate: 2, state: "closed" },
23
+ { gate: 3, state: "closed" },
24
+ { gate: 4, state: "closed" },
25
+ ]);
26
+ assert.deepEqual(await store.getRun("demo", "run-fixed"), run);
27
+ });
28
+ test("Gate 4 inheritance is always denied", () => {
29
+ assert.throws(() => inheritGate({ gate: 4, state: "approved", dependencyHash: hash }, "parent", hash, "2026-01-01T00:00:00.000Z"), /cannot be inherited/);
30
+ });
31
+ test("task guards reject expiry, stale head, and stale epoch and provide typed needs_input", () => {
32
+ let now = new Date("2026-01-01T00:00:00.000Z");
33
+ const clock = () => now;
34
+ const task = createTaskEnvelope({
35
+ projectId: "demo",
36
+ runId: "run-1",
37
+ role: "planner",
38
+ taskType: "plan",
39
+ expectedHead: hash,
40
+ ownerEpoch: 2,
41
+ inputRefs: [],
42
+ allowedOutputKinds: ["plan"],
43
+ capabilityGrants: [],
44
+ maxOutputBytes: 1000,
45
+ ttlMs: 1000,
46
+ }, clock, () => "task-1");
47
+ assertTaskCurrent(task, hash, 2, clock);
48
+ assert.throws(() => assertTaskCurrent(task, "b".repeat(64), 2, clock), /head is stale/);
49
+ assert.throws(() => assertTaskCurrent(task, hash, 1, clock), /epoch is stale/);
50
+ now = new Date("2026-01-01T00:00:02.000Z");
51
+ assert.throws(() => assertTaskCurrent(task, hash, 2, clock), /expired/);
52
+ assert.equal(needsInput(task.taskId, [{ id: "region", prompt: "Which region?" }]).status, "needs_input");
53
+ });
54
+ test("kernel validates freeform, single-select, and multi-select answers", () => {
55
+ const questions = [
56
+ { id: "name", prompt: "Name?" },
57
+ { id: "region", prompt: "Region?", options: ["sweden", "germany"] },
58
+ { id: "features", prompt: "Features?", options: ["logs", "backup"], multiSelect: true },
59
+ ];
60
+ assert.deepEqual(validateInputAnswers(questions, [
61
+ { questionId: "features", value: ["backup", "logs"] },
62
+ { questionId: "name", value: "demo" },
63
+ { questionId: "region", value: "sweden" },
64
+ ]), [
65
+ { questionId: "name", value: "demo" },
66
+ { questionId: "region", value: "sweden" },
67
+ { questionId: "features", value: ["logs", "backup"] },
68
+ ]);
69
+ assert.throws(() => validateInputAnswers(questions, [{ questionId: "name", value: "one" }]), /exactly one answer/u);
70
+ assert.throws(() => validateInputAnswers(questions, [
71
+ { questionId: "name", value: "one" },
72
+ { questionId: "name", value: "two" },
73
+ { questionId: "region", value: "sweden" },
74
+ ]), /Duplicate answer/u);
75
+ assert.throws(() => validateInputAnswers(questions, [
76
+ { questionId: "name", value: "demo" },
77
+ { questionId: "unknown", value: "value" },
78
+ { questionId: "features", value: ["logs"] },
79
+ ]), /Unknown answer: unknown/u);
80
+ assert.throws(() => validateInputAnswers(questions, [
81
+ { questionId: "name", value: "demo" },
82
+ { questionId: "region", value: "invalid" },
83
+ { questionId: "features", value: ["logs"] },
84
+ ]), /declared option/u);
85
+ assert.throws(() => validateInputAnswers(questions, [
86
+ { questionId: "name", value: "demo" },
87
+ { questionId: "region", value: ["sweden"] },
88
+ { questionId: "features", value: "logs" },
89
+ ]), /shape does not match/u);
90
+ for (const value of ["", " ", "none", "N/A", ["logs", " "]]) {
91
+ assert.throws(() => validateInputAnswers([{ id: "answer", prompt: "Answer?", ...(Array.isArray(value) ? { multiSelect: true } : {}) }], [{ questionId: "answer", value }]), /explicitly provided or deferred/u);
92
+ }
93
+ assert.deepEqual(validateInputAnswers([{ id: "answer", prompt: "Answer?" }], [{ questionId: "answer", value: "unknown" }]), [{ questionId: "answer", value: "unknown" }]);
94
+ });
95
+ test("validator registry caches pure results by content and never caches freshness or authorization", () => {
96
+ const schema = Type.Object({ value: Type.Integer() }, { additionalProperties: false });
97
+ const registry = new ValidatorRegistry();
98
+ registry.register("pure", schema);
99
+ registry.register("fresh", schema, "freshness");
100
+ registry.register("auth", schema, "authorization");
101
+ registry.registerHandler("business", (value) => value.value === 1 ? [] : [{ path: "/value", message: "Expected one" }]);
102
+ assert.equal(registry.has("business"), true);
103
+ assert.equal(registry.has("missing"), false);
104
+ assert.equal(registry.validate("pure", { value: 1 }).cached, false);
105
+ assert.equal(registry.validate("pure", { value: 1 }).cached, true);
106
+ assert.equal(registry.validate("pure", { value: 2 }).cached, false);
107
+ assert.equal(registry.validate("pure", { value: "invalid" }).valid, false);
108
+ assert.equal(registry.validate("fresh", { value: 1 }).cached, false);
109
+ assert.equal(registry.validate("fresh", { value: 1 }).cached, false);
110
+ assert.equal(registry.validate("auth", { value: 1 }).cached, false);
111
+ assert.equal(registry.validate("auth", { value: 1 }).cached, false);
112
+ assert.equal(registry.validate("business", { value: 1 }).valid, true);
113
+ assert.equal(registry.validate("business", { value: 1 }).cached, true);
114
+ const failed = registry.validate("business", { value: 2 });
115
+ assert.deepEqual(failed.issues, [{ path: "/value", message: "Expected one" }]);
116
+ failed.issues.length = 0;
117
+ assert.deepEqual(registry.validate("business", { value: 2 }).issues, [{ path: "/value", message: "Expected one" }]);
118
+ });
119
+ //# sourceMappingURL=workflow.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.test.js","sourceRoot":"","sources":["../../src/test/workflow.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE5B,IAAI,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;IACpG,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC;IAC/D,MAAM,KAAK,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC;IACnG,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE;QACxC,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,qBAAqB;QAClC,eAAe,EAAE,IAAI;KACtB,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACrC,MAAM,CAAC,SAAS,CACd,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,EACrD;QACE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;QAC5B,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;QAC5B,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;QAC5B,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE;KAC7B,CACF,CAAC;IACF,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;IAC/C,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,0BAA0B,CAAC,EACnH,qBAAqB,CACtB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,sFAAsF,EAAE,GAAG,EAAE;IAChG,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC;IACxB,MAAM,IAAI,GAAG,kBAAkB,CAC7B;QACE,SAAS,EAAE,MAAM;QACjB,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,CAAC;QACb,SAAS,EAAE,EAAE;QACb,kBAAkB,EAAE,CAAC,MAAM,CAAC;QAC5B,gBAAgB,EAAE,EAAE;QACpB,cAAc,EAAE,IAAI;QACpB,KAAK,EAAE,IAAI;KACZ,EACD,KAAK,EACL,GAAG,EAAE,CAAC,QAAQ,CACf,CAAC;IACF,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,eAAe,CAAC,CAAC;IACxF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/E,GAAG,GAAG,IAAI,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,CAAC;IACxE,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC3G,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oEAAoE,EAAE,GAAG,EAAE;IAC9E,MAAM,SAAS,GAAG;QAChB,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;QAC/B,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE;QACnE,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;KACxF,CAAC;IACF,MAAM,CAAC,SAAS,CACd,oBAAoB,CAAC,SAAS,EAAE;QAC9B,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;QACrD,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;QACrC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;KAC1C,CAAC,EACF;QACE,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;QACrC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;QACzC,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE;KACtD,CACF,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;IACpH,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CACH,oBAAoB,CAAC,SAAS,EAAE;QAC9B,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE;QACpC,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE;QACpC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;KAC1C,CAAC,EACJ,mBAAmB,CACpB,CAAC;IACF,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CACH,oBAAoB,CAAC,SAAS,EAAE;QAC9B,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;QACrC,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE;QACzC,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;KAC5C,CAAC,EACJ,0BAA0B,CAC3B,CAAC;IACF,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CACH,oBAAoB,CAAC,SAAS,EAAE;QAC9B,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;QACrC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;QAC1C,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;KAC5C,CAAC,EACJ,kBAAkB,CACnB,CAAC;IACF,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CACH,oBAAoB,CAAC,SAAS,EAAE;QAC9B,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;QACrC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE;QAC3C,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;KAC1C,CAAC,EACJ,uBAAuB,CACxB,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CACH,oBAAoB,CAClB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC7F,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAClC,EACH,kCAAkC,CACnC,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,SAAS,CACd,oBAAoB,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,EACzG,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAC7C,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+FAA+F,EAAE,GAAG,EAAE;IACzG,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAChD,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IACnD,QAAQ,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAC5C,KAA6B,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAChG,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3D,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AACtH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=writer-transfer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer-transfer.test.d.ts","sourceRoot":"","sources":["../../src/test/writer-transfer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,355 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtemp, readFile, readdir, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ import { EventJournal, ProjectStore, WriterTransferStore } from "../index.js";
7
+ async function fixture(repositoryOptions = {}) {
8
+ const root = await mkdtemp(join(tmpdir(), "apex-transfer-"));
9
+ let now = new Date("2026-01-01T00:00:00.000Z");
10
+ const clock = () => now;
11
+ const projects = new ProjectStore(root, clock, () => "run-1");
12
+ await projects.initializeProject({ projectId: "demo", displayName: "Demo", defaultIacTool: "bicep" });
13
+ await projects.createRun("demo", { environment: "dev", targetScope: "scope", runtimeLockHash: "a".repeat(64) });
14
+ const transfers = new WriterTransferStore(projects.runDirectory("demo", "run-1"), clock, repositoryOptions);
15
+ await transfers.leaseStore().acquire("alice", 10_000);
16
+ return {
17
+ transfers,
18
+ runDirectory: projects.runDirectory("demo", "run-1"),
19
+ setNow: (value) => {
20
+ now = new Date(value);
21
+ },
22
+ };
23
+ }
24
+ const request = {
25
+ projectId: "demo",
26
+ runId: "run-1",
27
+ repository: "org/repo",
28
+ branch: "main",
29
+ commit: "abc123",
30
+ workflowId: "workflow-v1",
31
+ approvalEnvironment: "vnext-qualification",
32
+ sender: "alice",
33
+ recipient: "bob",
34
+ currentEpoch: 1,
35
+ currentGitHead: "abc123",
36
+ ttlMs: 5_000,
37
+ eventId: "requested-1",
38
+ };
39
+ test("writer transfer binds head and recipient, releases sender, and atomically records ownership", async () => {
40
+ const { transfers } = await fixture();
41
+ const created = await transfers.create(request);
42
+ assert.equal(await transfers.leaseStore().current(), null);
43
+ const ownership = await transfers.accept({
44
+ claimHash: created.hash,
45
+ recipient: "bob",
46
+ currentGitHead: "abc123",
47
+ eventId: "accepted-1",
48
+ });
49
+ assert.equal(ownership.ownerEpoch, 2);
50
+ assert.equal(ownership.claimHash, created.hash);
51
+ assert.equal(ownership.previousOwnerId, "alice");
52
+ assert.equal(ownership.previousOwnerEpoch, 1);
53
+ assert.equal(ownership.approvalEnvironment, "vnext-qualification");
54
+ assert.equal((await transfers.currentOwnership())?.ownerId, "bob");
55
+ });
56
+ test("failed pre-import transfer reclaims the local lease only with exact workflow evidence", async () => {
57
+ const { transfers } = await fixture();
58
+ const created = await transfers.create(request);
59
+ const recovery = {
60
+ claimHash: created.hash,
61
+ sender: "alice",
62
+ expectedRecipient: "bob",
63
+ failedCandidateCommit: "abc123",
64
+ workflowRunId: 123,
65
+ workflowStatus: "completed",
66
+ workflowConclusion: "failure",
67
+ importAuthorityConclusion: "skipped",
68
+ deployConclusion: "skipped",
69
+ ttlMs: 10_000,
70
+ eventId: "cancelled-1",
71
+ };
72
+ await assert.rejects(transfers.reclaimFailedTransfer({ ...recovery, deployConclusion: "success" }), /failed pre-import dispatch/);
73
+ await assert.rejects(transfers.reclaimFailedTransfer({ ...recovery, failedCandidateCommit: "def456" }), /current run authority/);
74
+ await assert.rejects(transfers.reclaimFailedTransfer({ ...recovery, expectedRecipient: "mallory" }), /current run authority/);
75
+ await transfers.reclaimFailedTransfer(recovery);
76
+ assert.equal(await transfers.hasPendingTransfer(), false);
77
+ assert.equal((await transfers.leaseStore().current())?.ownerId, "alice");
78
+ await assert.rejects(transfers.accept({
79
+ claimHash: created.hash,
80
+ recipient: "bob",
81
+ currentGitHead: "abc123",
82
+ eventId: "late-accept",
83
+ }), /no longer pending/);
84
+ const fresh = await transfers.create({
85
+ ...request,
86
+ commit: "def456",
87
+ currentGitHead: "def456",
88
+ recipient: "carol",
89
+ eventId: "requested-2",
90
+ });
91
+ const ownership = await transfers.accept({
92
+ claimHash: fresh.hash,
93
+ recipient: "carol",
94
+ currentGitHead: "def456",
95
+ eventId: "accepted-2",
96
+ });
97
+ assert.equal(ownership.ownerId, "carol");
98
+ assert.equal(ownership.commit, "def456");
99
+ await assert.rejects(transfers.reclaimFailedTransfer(recovery), /already exists|no longer pending/);
100
+ });
101
+ test("cancelled transfer remains terminal after the recovery lease expires", async () => {
102
+ const { transfers, setNow } = await fixture();
103
+ const created = await transfers.create(request);
104
+ const recovery = {
105
+ claimHash: created.hash,
106
+ sender: "alice",
107
+ expectedRecipient: "bob",
108
+ failedCandidateCommit: "abc123",
109
+ workflowRunId: 123,
110
+ workflowStatus: "completed",
111
+ workflowConclusion: "failure",
112
+ importAuthorityConclusion: "skipped",
113
+ deployConclusion: "skipped",
114
+ ttlMs: 10_000,
115
+ eventId: "cancelled-1",
116
+ };
117
+ await transfers.reclaimFailedTransfer(recovery);
118
+ setNow("2026-01-01T00:00:11.000Z");
119
+ assert.equal(await transfers.leaseStore().current(), null);
120
+ await assert.rejects(transfers.accept({
121
+ claimHash: created.hash,
122
+ recipient: "bob",
123
+ currentGitHead: "abc123",
124
+ eventId: "late-accept",
125
+ }), /no longer pending/);
126
+ await assert.rejects(transfers.reclaimFailedTransfer(recovery), /no longer pending/);
127
+ });
128
+ test("writer transfer lease mismatch creates no claim or journal event", async () => {
129
+ const { transfers, runDirectory } = await fixture();
130
+ const journalBefore = await readdir(join(runDirectory, "journal"));
131
+ await assert.rejects(transfers.create({ ...request, sender: "mallory" }), /current lease/);
132
+ await assert.rejects(readdir(join(runDirectory, "transfers")), /ENOENT/);
133
+ assert.deepEqual(await readdir(join(runDirectory, "journal")), journalBefore);
134
+ });
135
+ test("writer transfer proves exact one-hop post-preview lineage", async () => {
136
+ const { transfers, runDirectory } = await fixture();
137
+ const journal = new EventJournal(join(runDirectory, "journal"));
138
+ const previewHash = "b".repeat(64);
139
+ await journal.append({
140
+ eventId: "preview-1",
141
+ projectId: "demo",
142
+ runId: "run-1",
143
+ type: "preview.created",
144
+ timestamp: "2026-01-01T00:00:00.000Z",
145
+ ownerEpoch: 1,
146
+ expectedHead: await journal.head(),
147
+ payload: { previewHash },
148
+ });
149
+ const created = await transfers.create(request);
150
+ await transfers.accept({
151
+ claimHash: created.hash,
152
+ recipient: "bob",
153
+ currentGitHead: "abc123",
154
+ eventId: "accepted-lineage",
155
+ });
156
+ assert.equal(await transfers.proveOneHopPostPreviewLineage(previewHash, 1), created.hash);
157
+ assert.equal(await transfers.proveOneHopPostPreviewLineage("c".repeat(64), 1), null);
158
+ assert.equal(await transfers.proveOneHopPostPreviewLineage(previewHash, 2), null);
159
+ });
160
+ test("writer transfer proves exact one-hop post-approval lineage", async () => {
161
+ const { transfers, runDirectory } = await fixture();
162
+ const journal = new EventJournal(join(runDirectory, "journal"));
163
+ const previewHash = "b".repeat(64);
164
+ const approvalHash = "c".repeat(64);
165
+ await journal.append({
166
+ eventId: "preview-approved-1",
167
+ projectId: "demo",
168
+ runId: "run-1",
169
+ type: "preview.created",
170
+ timestamp: "2026-01-01T00:00:00.000Z",
171
+ ownerEpoch: 1,
172
+ expectedHead: await journal.head(),
173
+ payload: { previewHash },
174
+ });
175
+ await journal.append({
176
+ eventId: "gate-approved-1",
177
+ projectId: "demo",
178
+ runId: "run-1",
179
+ type: "gate.decided",
180
+ timestamp: "2026-01-01T00:00:00.000Z",
181
+ ownerEpoch: 1,
182
+ expectedHead: await journal.head(),
183
+ payload: { gate: 4, approvalHash, previewHash },
184
+ });
185
+ const created = await transfers.create(request);
186
+ await transfers.accept({
187
+ claimHash: created.hash,
188
+ recipient: "bob",
189
+ currentGitHead: "abc123",
190
+ eventId: "accepted-approved-lineage",
191
+ });
192
+ assert.equal(await transfers.proveOneHopPostApprovalLineage(previewHash, 1, approvalHash), created.hash);
193
+ assert.equal(await transfers.proveOneHopPostApprovalLineage(previewHash, 1, "d".repeat(64)), null);
194
+ });
195
+ test("writer transfer lineage expires and is superseded by a later request", async () => {
196
+ const expiring = await fixture();
197
+ const previewHash = "b".repeat(64);
198
+ const journal = new EventJournal(join(expiring.runDirectory, "journal"));
199
+ await journal.append({
200
+ eventId: "preview-expiry",
201
+ projectId: "demo",
202
+ runId: "run-1",
203
+ type: "preview.created",
204
+ timestamp: "2026-01-01T00:00:00.000Z",
205
+ ownerEpoch: 1,
206
+ expectedHead: await journal.head(),
207
+ payload: { previewHash },
208
+ });
209
+ const first = await expiring.transfers.create(request);
210
+ await expiring.transfers.accept({
211
+ claimHash: first.hash,
212
+ recipient: "bob",
213
+ currentGitHead: "abc123",
214
+ eventId: "accepted-expiry",
215
+ });
216
+ expiring.setNow("2026-01-01T00:00:06.000Z");
217
+ assert.equal(await expiring.transfers.proveOneHopPostPreviewLineage(previewHash, 1), null);
218
+ const superseded = await fixture();
219
+ const supersededJournal = new EventJournal(join(superseded.runDirectory, "journal"));
220
+ await supersededJournal.append({
221
+ eventId: "preview-superseded",
222
+ projectId: "demo",
223
+ runId: "run-1",
224
+ type: "preview.created",
225
+ timestamp: "2026-01-01T00:00:00.000Z",
226
+ ownerEpoch: 1,
227
+ expectedHead: await supersededJournal.head(),
228
+ payload: { previewHash },
229
+ });
230
+ const accepted = await superseded.transfers.create(request);
231
+ await superseded.transfers.accept({
232
+ claimHash: accepted.hash,
233
+ recipient: "bob",
234
+ currentGitHead: "abc123",
235
+ eventId: "accepted-superseded",
236
+ });
237
+ await superseded.transfers.create({
238
+ ...request,
239
+ sender: "bob",
240
+ recipient: "carol",
241
+ currentEpoch: 2,
242
+ eventId: "requested-next",
243
+ });
244
+ assert.equal(await superseded.transfers.proveOneHopPostPreviewLineage(previewHash, 1), null);
245
+ });
246
+ test("writer transfer rejects a claim requested before the preview", async () => {
247
+ const { transfers, runDirectory } = await fixture();
248
+ const created = await transfers.create(request);
249
+ const journal = new EventJournal(join(runDirectory, "journal"));
250
+ const previewHash = "b".repeat(64);
251
+ await journal.append({
252
+ eventId: "preview-after-transfer",
253
+ projectId: "demo",
254
+ runId: "run-1",
255
+ type: "preview.created",
256
+ timestamp: "2026-01-01T00:00:00.000Z",
257
+ ownerEpoch: 1,
258
+ expectedHead: await journal.head(),
259
+ payload: { previewHash },
260
+ });
261
+ await transfers.accept({
262
+ claimHash: created.hash,
263
+ recipient: "bob",
264
+ currentGitHead: "abc123",
265
+ eventId: "accepted-after-preview",
266
+ });
267
+ assert.equal(await transfers.proveOneHopPostPreviewLineage(previewHash, 1), null);
268
+ });
269
+ test("writer transfer lineage fails closed on ownership or claim tampering", async () => {
270
+ const { transfers, runDirectory } = await fixture();
271
+ const journal = new EventJournal(join(runDirectory, "journal"));
272
+ const previewHash = "b".repeat(64);
273
+ await journal.append({
274
+ eventId: "preview-tamper",
275
+ projectId: "demo",
276
+ runId: "run-1",
277
+ type: "preview.created",
278
+ timestamp: "2026-01-01T00:00:00.000Z",
279
+ ownerEpoch: 1,
280
+ expectedHead: await journal.head(),
281
+ payload: { previewHash },
282
+ });
283
+ const created = await transfers.create(request);
284
+ await transfers.accept({
285
+ claimHash: created.hash,
286
+ recipient: "bob",
287
+ currentGitHead: "abc123",
288
+ eventId: "accepted-tamper",
289
+ });
290
+ const ownershipPath = join(runDirectory, "ownership.json");
291
+ const ownership = await readFile(ownershipPath, "utf8");
292
+ await writeFile(ownershipPath, ownership.replace('"ownerId":"bob"', '"ownerId":"eve"'));
293
+ assert.equal(await transfers.proveOneHopPostPreviewLineage(previewHash, 1), null);
294
+ await writeFile(ownershipPath, ownership);
295
+ const claimPath = join(runDirectory, "transfers", `${created.hash}.json`);
296
+ const claim = await readFile(claimPath, "utf8");
297
+ await writeFile(claimPath, claim.replace('"recipient":"bob"', '"recipient":"eve"'));
298
+ assert.equal(await transfers.proveOneHopPostPreviewLineage(previewHash, 1), null);
299
+ });
300
+ test("writer transfer rejects stale head, epoch, expiry, and wrong recipient", async () => {
301
+ const staleHead = await fixture();
302
+ await assert.rejects(staleHead.transfers.create({ ...request, currentGitHead: "other" }), /Git head/);
303
+ const wrongRecipient = await fixture();
304
+ const claim = await wrongRecipient.transfers.create(request);
305
+ await assert.rejects(wrongRecipient.transfers.accept({
306
+ claimHash: claim.hash,
307
+ recipient: "eve",
308
+ currentGitHead: "abc123",
309
+ eventId: "accepted",
310
+ }), /recipient/);
311
+ await assert.rejects(wrongRecipient.transfers.accept({
312
+ claimHash: claim.hash,
313
+ recipient: "bob",
314
+ currentGitHead: "other",
315
+ eventId: "accepted",
316
+ }), /Git head/);
317
+ const expired = await fixture();
318
+ const expiredClaim = await expired.transfers.create(request);
319
+ expired.setNow("2026-01-01T00:00:06.000Z");
320
+ await assert.rejects(expired.transfers.accept({
321
+ claimHash: expiredClaim.hash,
322
+ recipient: "bob",
323
+ currentGitHead: "abc123",
324
+ eventId: "accepted",
325
+ }), /expired/);
326
+ const staleEpoch = await fixture();
327
+ await assert.rejects(staleEpoch.transfers.create({ ...request, currentEpoch: 2 }), /Stale transfer epoch/);
328
+ });
329
+ test("writer transfer releases the recipient lease when run mutation fails", async () => {
330
+ let failMutation = true;
331
+ const { transfers } = await fixture({
332
+ faultInjector: (stage) => {
333
+ if (stage === "intent" && failMutation) {
334
+ failMutation = false;
335
+ throw new Error("injected-transfer-failure");
336
+ }
337
+ },
338
+ });
339
+ const claim = await transfers.create(request);
340
+ await assert.rejects(transfers.accept({
341
+ claimHash: claim.hash,
342
+ recipient: "bob",
343
+ currentGitHead: "abc123",
344
+ eventId: "accepted-failure",
345
+ }), /injected-transfer-failure/);
346
+ assert.equal(await transfers.leaseStore().current(), null);
347
+ const retried = await transfers.accept({
348
+ claimHash: claim.hash,
349
+ recipient: "bob",
350
+ currentGitHead: "abc123",
351
+ eventId: "accepted-retry",
352
+ });
353
+ assert.equal(retried.ownerEpoch, 2);
354
+ });
355
+ //# sourceMappingURL=writer-transfer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer-transfer.test.js","sourceRoot":"","sources":["../../src/test/writer-transfer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { TSchema } from "@sinclair/typebox";
2
+ export type ValidatorKind = "pure" | "freshness" | "authorization";
3
+ export interface ValidationIssue {
4
+ path: string;
5
+ message: string;
6
+ }
7
+ export interface ValidationResult {
8
+ valid: boolean;
9
+ issues: ValidationIssue[];
10
+ cached: boolean;
11
+ }
12
+ export type ValidatorHandler = (value: unknown) => ValidationIssue[];
13
+ export declare class ValidatorRegistry {
14
+ private readonly validators;
15
+ private readonly cache;
16
+ register(name: string, schema: TSchema, kind?: ValidatorKind): void;
17
+ registerHandler(name: string, handler: ValidatorHandler, kind?: ValidatorKind): void;
18
+ has(name: string): boolean;
19
+ validate(name: string, value: unknown): ValidationResult;
20
+ clearCache(): void;
21
+ }
22
+ //# sourceMappingURL=validator-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator-registry.d.ts","sourceRoot":"","sources":["../src/validator-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIjD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,eAAe,EAAE,CAAC;AAOrE,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuD;IAE7E,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAE,aAAsB,GAAG,IAAI,CAU1E;IAED,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,GAAE,aAAsB,GAAG,IAAI,CAK3F;IAED,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzB;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAgBvD;IAED,UAAU,IAAI,IAAI,CAEjB;CACF"}
@@ -0,0 +1,42 @@
1
+ import { Value } from "@sinclair/typebox/value";
2
+ import { sha256Json } from "./canonical.js";
3
+ export class ValidatorRegistry {
4
+ validators = new Map();
5
+ cache = new Map();
6
+ register(name, schema, kind = "pure") {
7
+ this.registerHandler(name, (value) => [...Value.Errors(schema, value)].map((error) => ({
8
+ path: error.path,
9
+ message: error.message,
10
+ })), kind);
11
+ }
12
+ registerHandler(name, handler, kind = "pure") {
13
+ if (this.validators.has(name)) {
14
+ throw new Error(`Validator ${name} is already registered`);
15
+ }
16
+ this.validators.set(name, { handler, kind });
17
+ }
18
+ has(name) {
19
+ return this.validators.has(name);
20
+ }
21
+ validate(name, value) {
22
+ const validator = this.validators.get(name);
23
+ if (validator === undefined) {
24
+ throw new Error(`Unknown validator ${name}`);
25
+ }
26
+ const cacheKey = validator.kind === "pure" ? `${name}:${sha256Json(value)}` : undefined;
27
+ const cached = cacheKey === undefined ? undefined : this.cache.get(cacheKey);
28
+ if (cached !== undefined) {
29
+ return { ...cached, issues: [...cached.issues], cached: true };
30
+ }
31
+ const issues = validator.handler(value);
32
+ const result = { valid: issues.length === 0, issues };
33
+ if (cacheKey !== undefined) {
34
+ this.cache.set(cacheKey, { ...result, issues: [...issues] });
35
+ }
36
+ return { ...result, issues: [...issues], cached: false };
37
+ }
38
+ clearCache() {
39
+ this.cache.clear();
40
+ }
41
+ }
42
+ //# sourceMappingURL=validator-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator-registry.js","sourceRoot":"","sources":["../src/validator-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAsB5C,MAAM,OAAO,iBAAiB;IACX,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;IACpD,KAAK,GAAG,IAAI,GAAG,EAA4C,CAAC;IAE7E,QAAQ,CAAC,IAAY,EAAE,MAAe,EAAE,IAAI,GAAkB,MAAM;QAClE,IAAI,CAAC,eAAe,CAClB,IAAI,EACJ,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC/C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC,EACL,IAAI,CACL,CAAC;IACJ,CAAC;IAED,eAAe,CAAC,IAAY,EAAE,OAAyB,EAAE,IAAI,GAAkB,MAAM;QACnF,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,wBAAwB,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,KAAc;QACnC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACxF,MAAM,MAAM,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7E,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACtD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}