@deksden-com/dd-flow-cli 0.9.0-beta.137 → 0.9.0-beta.138

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 (260) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +9 -0
  3. package/dist/build-info.json +6 -6
  4. package/dist/cli/argument-values.js +5 -5
  5. package/dist/cli/command-inputs.js +89 -20
  6. package/dist/cli/command-metadata.js +197 -0
  7. package/dist/cli/command-option-descriptions.js +191 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/error-output.js +52 -0
  11. package/dist/cli/executor-onboarding.js +76 -0
  12. package/dist/cli/flows.js +29 -0
  13. package/dist/cli/harnesses.js +84 -0
  14. package/dist/cli/help.js +240 -6
  15. package/dist/cli/input-preparation.js +54 -5
  16. package/dist/cli/memory-flow-admission.js +44 -0
  17. package/dist/cli/memory-init-invocation.js +78 -0
  18. package/dist/cli/memory-init.js +240 -0
  19. package/dist/cli/memory-storage-admission.js +53 -0
  20. package/dist/cli/models.js +39 -0
  21. package/dist/cli/native-hook-ingress.js +1 -1
  22. package/dist/cli/operator-profiles.js +61 -0
  23. package/dist/cli/output-options.js +35 -0
  24. package/dist/cli/response-file.js +71 -0
  25. package/dist/cli/run-cli.js +283 -160
  26. package/dist/cli/setup.js +149 -0
  27. package/dist/cli.js +54 -2
  28. package/dist/domain/stage-handler-identities.js +20 -0
  29. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  30. package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
  31. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +4 -2
  32. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +11 -5
  33. package/dist/harness-runtime/lib/dd-codex.mjs +22 -10
  34. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
  35. package/dist/harness-runtime/lib/dd-droid.mjs +2 -1
  36. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +4 -2
  37. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +6 -4
  38. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +9 -9
  39. package/dist/harness-runtime/lib/delegation-instructions.mjs +5 -3
  40. package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
  41. package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
  42. package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
  43. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  44. package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
  45. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  46. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  47. package/dist/harness-runtime/lib/opencode-plugin.mjs +2 -0
  48. package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
  49. package/dist/runtime/context.js +1 -1
  50. package/dist/schemas/discovery-result.schema.json +184 -0
  51. package/dist/schemas/execution-bundle.schema.json +205 -0
  52. package/dist/schemas/execution-settings.schema.json +162 -0
  53. package/dist/schemas/flow-descriptor.schema.json +54 -0
  54. package/dist/schemas/flow-run.schema.json +22 -0
  55. package/dist/schemas/harness-catalog.schema.json +80 -0
  56. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  57. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  58. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  59. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  60. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  61. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  62. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  63. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  64. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  65. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  66. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  67. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  68. package/dist/schemas/model-catalog.schema.json +153 -0
  69. package/dist/schemas/profile-settings.schema.json +122 -0
  70. package/dist/schemas/release-manifest.schema.json +291 -0
  71. package/dist/schemas/run-engine-binding.schema.json +1 -1
  72. package/dist/services/check-runner-evidence.js +51 -4
  73. package/dist/services/cli-operation-classifier.js +8 -47
  74. package/dist/services/cli-upgrade-allowlist.js +27 -0
  75. package/dist/services/code-checks.js +387 -34
  76. package/dist/services/controller-execution.js +88 -0
  77. package/dist/services/controller-fanout.js +71 -12
  78. package/dist/services/dashboard.js +8 -2
  79. package/dist/services/descriptor-coordinator-session.js +35 -0
  80. package/dist/services/descriptor-root-work.js +53 -0
  81. package/dist/services/descriptor-run-settlement.js +105 -0
  82. package/dist/services/descriptor-run-start.js +449 -0
  83. package/dist/services/descriptor-stage-coordinator.js +197 -0
  84. package/dist/services/descriptor-stage-settlement.js +222 -0
  85. package/dist/services/descriptor-stage-start.js +139 -0
  86. package/dist/services/discovery/agy-discovery.js +2 -0
  87. package/dist/services/discovery/codex-discovery.js +2 -0
  88. package/dist/services/discovery/droid-discovery.js +2 -0
  89. package/dist/services/discovery/grok-discovery.js +2 -0
  90. package/dist/services/discovery/opencode-discovery.js +2 -0
  91. package/dist/services/discovery/static.js +31 -0
  92. package/dist/services/discovery/zcode-discovery.js +2 -0
  93. package/dist/services/engines.js +39 -22
  94. package/dist/services/eval-snapshots.js +83 -25
  95. package/dist/services/execution-bundles.js +263 -0
  96. package/dist/services/execution-policy.js +20 -16
  97. package/dist/services/executor-onboarding.js +56 -0
  98. package/dist/services/external-work-launch.js +91 -11
  99. package/dist/services/flow-catalog.js +21 -0
  100. package/dist/services/flow-descriptors.js +82 -0
  101. package/dist/services/frozen-engine.js +242 -0
  102. package/dist/services/generic-execution.js +164 -0
  103. package/dist/services/harness-adapter.js +28 -2
  104. package/dist/services/harness-discovery.js +29 -0
  105. package/dist/services/harness-doctor.js +75 -0
  106. package/dist/services/harness-probe-effects.js +51 -0
  107. package/dist/services/harness-version-probe.js +100 -0
  108. package/dist/services/hooks.js +24 -6
  109. package/dist/services/hybrid-contracts.js +483 -0
  110. package/dist/services/ids.js +29 -1
  111. package/dist/services/installation-lock.js +95 -0
  112. package/dist/services/installed-flow-source.js +183 -0
  113. package/dist/services/lifecycle-invocations.js +257 -78
  114. package/dist/services/memory-accepted-composition.js +77 -0
  115. package/dist/services/memory-baseline-preservation.js +65 -0
  116. package/dist/services/memory-completed-correction-wave.js +320 -0
  117. package/dist/services/memory-compose-handler.js +258 -0
  118. package/dist/services/memory-composition-acceptance.js +199 -0
  119. package/dist/services/memory-composition-graph.js +134 -0
  120. package/dist/services/memory-composition-registration.js +146 -0
  121. package/dist/services/memory-composition-work-custody.js +151 -0
  122. package/dist/services/memory-composition-work-results.js +96 -0
  123. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  124. package/dist/services/memory-corrected-review-batch.js +30 -0
  125. package/dist/services/memory-corrected-review-findings.js +106 -0
  126. package/dist/services/memory-corrected-review-inputs.js +210 -0
  127. package/dist/services/memory-corrected-review-projection.js +78 -0
  128. package/dist/services/memory-corrected-review-receipt.js +170 -0
  129. package/dist/services/memory-corrected-review-registration.js +191 -0
  130. package/dist/services/memory-correction-check-receipt.js +219 -0
  131. package/dist/services/memory-correction-input-owner.js +6 -0
  132. package/dist/services/memory-discover-handler.js +104 -0
  133. package/dist/services/memory-finish-evidence.js +435 -0
  134. package/dist/services/memory-finish-handler.js +215 -0
  135. package/dist/services/memory-finish-integration.js +280 -0
  136. package/dist/services/memory-finish-readiness.js +122 -0
  137. package/dist/services/memory-git-integration.js +151 -0
  138. package/dist/services/memory-historical-corrected-review.js +206 -0
  139. package/dist/services/memory-historical-original-review.js +130 -0
  140. package/dist/services/memory-historical-repair-registration.js +99 -0
  141. package/dist/services/memory-historical-second-review.js +128 -0
  142. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  143. package/dist/services/memory-init-contexts.js +89 -0
  144. package/dist/services/memory-init-controller-start.js +84 -0
  145. package/dist/services/memory-init-engine-release.js +223 -0
  146. package/dist/services/memory-init-git-policy.js +136 -0
  147. package/dist/services/memory-init-lint-capability.js +185 -0
  148. package/dist/services/memory-init-native-capacity.js +241 -0
  149. package/dist/services/memory-init-preflight.js +312 -0
  150. package/dist/services/memory-init-project-bootstrap.js +599 -0
  151. package/dist/services/memory-init-request-candidate.js +157 -0
  152. package/dist/services/memory-init-request-input.js +66 -0
  153. package/dist/services/memory-init-resource-storage.js +125 -0
  154. package/dist/services/memory-init-run-allocation.js +81 -0
  155. package/dist/services/memory-init-run-bundle.js +98 -0
  156. package/dist/services/memory-init-start.js +175 -0
  157. package/dist/services/memory-init-startup-custody.js +80 -0
  158. package/dist/services/memory-init-startup-input.js +240 -0
  159. package/dist/services/memory-init-storage.js +81 -0
  160. package/dist/services/memory-init-stores.js +359 -0
  161. package/dist/services/memory-init-worktrunk-capability.js +172 -0
  162. package/dist/services/memory-layer-publication.js +611 -0
  163. package/dist/services/memory-layer.js +156 -0
  164. package/dist/services/memory-lint-config.js +85 -0
  165. package/dist/services/memory-native-review-copy.js +165 -0
  166. package/dist/services/memory-normal-flow-entry.js +75 -0
  167. package/dist/services/memory-ordinary-defaults.js +112 -0
  168. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  169. package/dist/services/memory-preflight-handler.js +259 -0
  170. package/dist/services/memory-repair-current-view.js +299 -0
  171. package/dist/services/memory-repair-document-delta.js +451 -0
  172. package/dist/services/memory-repair-history.js +491 -0
  173. package/dist/services/memory-repair-physical-binding.js +312 -0
  174. package/dist/services/memory-repair-publication-files.js +152 -0
  175. package/dist/services/memory-repair-publication-intent.js +27 -0
  176. package/dist/services/memory-repair-publication-plan.js +160 -0
  177. package/dist/services/memory-repair-publication-source.js +225 -0
  178. package/dist/services/memory-repair-publication.js +794 -0
  179. package/dist/services/memory-repair-registration.js +239 -0
  180. package/dist/services/memory-repair-work-baseline.js +413 -0
  181. package/dist/services/memory-repair-work-completion.js +97 -0
  182. package/dist/services/memory-repair-work-custody.js +73 -0
  183. package/dist/services/memory-repair-work-results.js +89 -0
  184. package/dist/services/memory-repair-workspace.js +252 -0
  185. package/dist/services/memory-repair-writer-copy.js +735 -0
  186. package/dist/services/memory-result-binding.js +173 -0
  187. package/dist/services/memory-retained-review-authority.js +129 -0
  188. package/dist/services/memory-retained-review-results.js +70 -0
  189. package/dist/services/memory-retained-second-baseline.js +102 -0
  190. package/dist/services/memory-retained-second-repairs.js +156 -0
  191. package/dist/services/memory-review-acceptance.js +214 -0
  192. package/dist/services/memory-review-correction-plan.js +171 -0
  193. package/dist/services/memory-review-handler.js +585 -0
  194. package/dist/services/memory-review-inputs.js +200 -0
  195. package/dist/services/memory-review-receipt.js +180 -0
  196. package/dist/services/memory-review-registration.js +108 -0
  197. package/dist/services/memory-review-work-custody.js +124 -0
  198. package/dist/services/memory-review-work-input.js +72 -0
  199. package/dist/services/memory-review-work-results.js +73 -0
  200. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  201. package/dist/services/memory-second-correction-plan.js +76 -0
  202. package/dist/services/memory-second-repair-baseline.js +91 -0
  203. package/dist/services/memory-second-repair-launch.js +614 -0
  204. package/dist/services/memory-second-repair-registration.js +88 -0
  205. package/dist/services/memory-second-repair-source.js +187 -0
  206. package/dist/services/memory-second-review-acceptance.js +115 -0
  207. package/dist/services/memory-source-observations.js +117 -0
  208. package/dist/services/memory-stage-dispatch.js +28 -0
  209. package/dist/services/memory-stage-results.js +199 -0
  210. package/dist/services/memory-verification-acceptance.js +135 -0
  211. package/dist/services/memory-verification-checks.js +252 -0
  212. package/dist/services/memory-verification-receipt.js +159 -0
  213. package/dist/services/memory-verify-handler.js +135 -0
  214. package/dist/services/memory-work-result-preparation.js +63 -0
  215. package/dist/services/model-catalog.js +109 -0
  216. package/dist/services/model-discovery.js +46 -0
  217. package/dist/services/operator-profiles.js +236 -0
  218. package/dist/services/projects.js +17 -2
  219. package/dist/services/recovery-snapshot-database.js +416 -1
  220. package/dist/services/release-archive-producer.js +52 -0
  221. package/dist/services/release-archive.js +143 -0
  222. package/dist/services/release-cache.js +142 -0
  223. package/dist/services/release-compatibility.js +18 -0
  224. package/dist/services/release-download.js +67 -0
  225. package/dist/services/release-envelope.js +104 -0
  226. package/dist/services/release-manifest.js +45 -0
  227. package/dist/services/release-payload.js +114 -0
  228. package/dist/services/release-producer.js +63 -0
  229. package/dist/services/release-provenance.js +160 -0
  230. package/dist/services/release-registry.js +66 -0
  231. package/dist/services/release-source.js +194 -0
  232. package/dist/services/repair-intents.js +1 -1
  233. package/dist/services/review-copy.js +10 -2
  234. package/dist/services/run-control.js +80 -9
  235. package/dist/services/run-controller-capture.js +10 -3
  236. package/dist/services/run-controller-process.js +21 -0
  237. package/dist/services/run-controller-recovery.js +3 -1
  238. package/dist/services/run-controller-state.js +1 -1
  239. package/dist/services/run-controller.js +101 -40
  240. package/dist/services/run-recovery-guard.js +2 -0
  241. package/dist/services/run-recovery.js +145 -5
  242. package/dist/services/run-start-custody.js +177 -0
  243. package/dist/services/runs.js +319 -25
  244. package/dist/services/setup.js +377 -0
  245. package/dist/services/stage-context.js +9 -1
  246. package/dist/services/stage-handlers.js +74 -0
  247. package/dist/services/stage-report-renderer.js +63 -0
  248. package/dist/services/stage-work-graph.js +17 -0
  249. package/dist/services/vnext-code.js +3 -3
  250. package/dist/services/vnext-execution-profile.js +2 -2
  251. package/dist/services/vnext-fanout.js +70 -9
  252. package/dist/services/vnext-merge.js +8 -3
  253. package/dist/services/vnext-plan-review.js +6 -4
  254. package/dist/services/work-registry.js +616 -71
  255. package/dist/services/workspace-files.js +1 -1
  256. package/dist/storage/database.js +84 -6
  257. package/dist/storage/writer-contract.js +11 -7
  258. package/package.json +13 -3
  259. package/tools/create-canon-release.mjs +33 -0
  260. package/tools/produce-hybrid-release.mjs +41 -0
@@ -0,0 +1,183 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import { AppError } from "../shared/errors.js";
5
+ import { readSetupStatus } from "./setup.js";
6
+ import { readBoundedReleaseFile } from "./release-source.js";
7
+ import { hybridDigest, validateHybridShape } from "./hybrid-contracts.js";
8
+ import { admitBundledFlow } from "./stage-handlers.js";
9
+ const limit = 1024 * 1024;
10
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
11
+ function refuse(reason) {
12
+ throw new AppError("installed_flow_source_invalid", "Installed flow source is not the selected verified canon", 1, { reason, phase: "prepare", effect: "no_effect" });
13
+ }
14
+ function directory(target) {
15
+ if (!fs.lstatSync(target).isDirectory())
16
+ refuse("unsafe_source_directory");
17
+ }
18
+ function containedFile(root, logical) {
19
+ if (!/^[A-Za-z0-9_-][A-Za-z0-9_.-]*(\/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*$/.test(logical)
20
+ || logical.split("/").some(part => part === "." || part === ".."))
21
+ refuse("unsafe_source_path");
22
+ let current = root;
23
+ for (const part of logical.split("/").slice(0, -1)) {
24
+ current = path.join(current, part);
25
+ directory(current);
26
+ }
27
+ return path.join(root, logical);
28
+ }
29
+ /** Initial RUN materialization input, not handler/engine/storage admission.
30
+ * Built-in memory flows live in the global canon, not the curated project pack.
31
+ * Existing RUNs must restore their retained bundle rather than call this reader.
32
+ */
33
+ export class PreparedInstalledFlowSource {
34
+ sha256;
35
+ #home;
36
+ #installationSha256;
37
+ #flowId;
38
+ #descriptor;
39
+ #canon;
40
+ #blobs;
41
+ constructor(home, installationSha256, flowId, descriptor, canon, blobs) {
42
+ this.#home = home;
43
+ this.#installationSha256 = installationSha256;
44
+ this.#flowId = flowId;
45
+ this.#descriptor = descriptor;
46
+ this.#canon = canon;
47
+ this.#blobs = blobs;
48
+ this.sha256 = hybridDigest({ installation_sha256: installationSha256, canon, inventory: this.inventory() });
49
+ Object.freeze(this);
50
+ }
51
+ static fromInstalledRelease(home, expectedInstallationSha256, flowId) {
52
+ try {
53
+ if (!path.isAbsolute(home) || !/^[a-f0-9]{64}$/.test(expectedInstallationSha256) || flowId !== "mb-init")
54
+ refuse("invalid_selection");
55
+ const selected = readSetupStatus(home);
56
+ if (!selected.installation || selected.installation_readiness !== "installed")
57
+ refuse("installed_release_unavailable");
58
+ const installation = selected.installation;
59
+ if (installation.manifest_sha256 !== expectedInstallationSha256)
60
+ refuse("installation_selection_changed");
61
+ directory(installation.canon_root);
62
+ const roots = fs.readdirSync(installation.canon_root);
63
+ if (roots.length !== 1)
64
+ refuse("ambiguous_archive_root");
65
+ const canonRoot = path.join(installation.canon_root, roots[0]);
66
+ directory(canonRoot);
67
+ const dotRoot = path.join(canonRoot, ".memory-bank"), memoryRoot = fs.existsSync(dotRoot) ? dotRoot : canonRoot;
68
+ directory(memoryRoot);
69
+ const flowRoot = path.join(memoryRoot, "dd-flow");
70
+ directory(flowRoot);
71
+ const descriptorPath = `${flowId}/flow-descriptor.json`;
72
+ const bytes = readBoundedReleaseFile(containedFile(flowRoot, descriptorPath), limit);
73
+ const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
74
+ if (validateHybridShape("flow-descriptor", value).length || value.id !== flowId || value.origin !== "canon"
75
+ || value.stages.length > 64)
76
+ refuse("invalid_descriptor");
77
+ const blobs = new Map([[descriptorPath, Buffer.from(bytes)]]), folded = new Map([[descriptorPath.toLowerCase(), descriptorPath]]);
78
+ let total = bytes.length;
79
+ for (const stage of value.stages)
80
+ for (const kind of ["instruction", "result_schema"]) {
81
+ const reference = stage[kind], existing = blobs.get(reference.path);
82
+ if (existing) {
83
+ if (hash(existing) !== reference.sha256)
84
+ refuse("conflicting_source_reference");
85
+ continue;
86
+ }
87
+ if (folded.has(reference.path.toLowerCase()))
88
+ refuse("conflicting_source_path");
89
+ const content = readBoundedReleaseFile(containedFile(flowRoot, reference.path), limit);
90
+ if (!content.length || (total += content.length) > 32 * limit || hash(content) !== reference.sha256)
91
+ refuse("source_bytes_changed");
92
+ new TextDecoder("utf-8", { fatal: true }).decode(content);
93
+ if (kind === "result_schema")
94
+ JSON.parse(content.toString("utf8"));
95
+ folded.set(reference.path.toLowerCase(), reference.path);
96
+ blobs.set(reference.path, Buffer.from(content));
97
+ }
98
+ // Verify compressed/expanded archive identity again after collecting bytes.
99
+ // A coherent descriptor+prompt edit cannot become a new trusted selection.
100
+ const final = readSetupStatus(home);
101
+ if (final.installation_readiness !== "installed" || hybridDigest(final.installation) !== hybridDigest(installation))
102
+ refuse("source_changed_during_preparation");
103
+ return new PreparedInstalledFlowSource(home, expectedInstallationSha256, flowId, { path: descriptorPath, sha256: hash(bytes) }, { version: installation.manifest.canon.version, commit: installation.manifest.canon.commit, archive_sha256: installation.manifest.canon.archive.sha256 }, blobs);
104
+ }
105
+ catch (error) {
106
+ if (error instanceof AppError && error.code === "installed_flow_source_invalid")
107
+ throw error;
108
+ return refuse("source_unavailable_or_changed");
109
+ }
110
+ }
111
+ descriptorReference() { return { ...this.#descriptor }; }
112
+ installationSha256() { return this.#installationSha256; }
113
+ snapshot() {
114
+ return { schema_id: "dd-flow/installed-flow-source@1", installation_sha256: this.#installationSha256,
115
+ descriptor: this.descriptorReference(), canon: this.canonProvenance(),
116
+ blobs: [...this.#blobs].map(([logical, bytes]) => ({ path: logical, base64: bytes.toString("base64") })) };
117
+ }
118
+ /** Copied source restoration only. expectedSha256 must come from independent
119
+ * request custody, not from the same input. This does not verify a new release
120
+ * or admit its engine/storage; those remain the bootstrap owner's duties.
121
+ */
122
+ static restoreRetained(input, expectedSha256) {
123
+ try {
124
+ if (!input || typeof input !== "object" || Array.isArray(input) || typeof expectedSha256 !== "string"
125
+ || !/^[a-f0-9]{64}$/.test(expectedSha256))
126
+ refuse("invalid_retained_source");
127
+ const value = input;
128
+ if (Object.keys(value).sort().join() !== "blobs,canon,descriptor,installation_sha256,schema_id"
129
+ || value.schema_id !== "dd-flow/installed-flow-source@1" || typeof value.installation_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(value.installation_sha256)
130
+ || !value.canon || Object.keys(value.canon).sort().join() !== "archive_sha256,commit,version"
131
+ || typeof value.canon.commit !== "string" || !/^[a-f0-9]{40}$/.test(value.canon.commit)
132
+ || typeof value.canon.archive_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(value.canon.archive_sha256)
133
+ || typeof value.canon.version !== "string" || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(value.canon.version)
134
+ || !value.descriptor || Object.keys(value.descriptor).sort().join() !== "path,sha256"
135
+ || value.descriptor.path !== "mb-init/flow-descriptor.json" || typeof value.descriptor.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(value.descriptor.sha256)
136
+ || !Array.isArray(value.blobs) || value.blobs.length < 1 || value.blobs.length > 129)
137
+ refuse("invalid_retained_source");
138
+ const blobs = new Map(), folded = new Set();
139
+ let total = 0;
140
+ for (const entry of value.blobs) {
141
+ if (!entry || Object.keys(entry).sort().join() !== "base64,path" || typeof entry.path !== "string"
142
+ || !/^[A-Za-z0-9_-][A-Za-z0-9_.-]*(\/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*$/.test(entry.path)
143
+ || entry.path.split("/").some(part => part === "." || part === "..")
144
+ || folded.has(entry.path.toLowerCase()) || typeof entry.base64 !== "string" || entry.base64.length > 2 * limit)
145
+ refuse("invalid_retained_source");
146
+ const content = Buffer.from(entry.base64, "base64");
147
+ if (!content.length || content.length > limit || content.toString("base64") !== entry.base64
148
+ || (total += content.length) > 32 * limit)
149
+ refuse("invalid_retained_source");
150
+ new TextDecoder("utf-8", { fatal: true }).decode(content);
151
+ folded.add(entry.path.toLowerCase());
152
+ blobs.set(entry.path, content);
153
+ }
154
+ const descriptor = blobs.get(value.descriptor.path);
155
+ if (!descriptor || hash(descriptor) !== value.descriptor.sha256)
156
+ refuse("retained_source_changed");
157
+ const result = new PreparedInstalledFlowSource(null, value.installation_sha256, "mb-init", { ...value.descriptor }, { ...value.canon }, blobs);
158
+ if (result.sha256 !== expectedSha256)
159
+ refuse("retained_source_changed");
160
+ result.resolveRegisteredFlow();
161
+ return result;
162
+ }
163
+ catch (error) {
164
+ if (error instanceof AppError && error.code === "installed_flow_source_invalid")
165
+ throw error;
166
+ return refuse("invalid_retained_source");
167
+ }
168
+ }
169
+ canonProvenance() { return { ...this.#canon }; }
170
+ blobs() { return new Map([...this.#blobs].map(([logical, bytes]) => [logical, Buffer.from(bytes)])); }
171
+ inventory() { return [...this.#blobs].map(([logical, bytes]) => ({ path: logical, sha256: hash(bytes) })).sort((a, b) => a.path.localeCompare(b.path, "en")); }
172
+ /** Production handler registry only: source declarations cannot register code. */
173
+ resolveRegisteredFlow() { return admitBundledFlow(this.#blobs.get(this.#descriptor.path), this.#descriptor.sha256, this.#blobs); }
174
+ /** Initial materialization only, outside SQL writers. */
175
+ revalidate() {
176
+ if (this.#home === null) {
177
+ PreparedInstalledFlowSource.restoreRetained(this.snapshot(), this.sha256);
178
+ return;
179
+ }
180
+ if (PreparedInstalledFlowSource.fromInstalledRelease(this.#home, this.#installationSha256, this.#flowId).sha256 !== this.sha256)
181
+ refuse("source_changed_after_preparation");
182
+ }
183
+ }