@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.
- package/CHANGELOG.md +4 -0
- package/README.md +9 -0
- package/dist/build-info.json +6 -6
- package/dist/cli/argument-values.js +5 -5
- package/dist/cli/command-inputs.js +89 -20
- package/dist/cli/command-metadata.js +197 -0
- package/dist/cli/command-option-descriptions.js +191 -0
- package/dist/cli/completion-cli.js +70 -0
- package/dist/cli/completion.js +57 -0
- package/dist/cli/error-output.js +52 -0
- package/dist/cli/executor-onboarding.js +76 -0
- package/dist/cli/flows.js +29 -0
- package/dist/cli/harnesses.js +84 -0
- package/dist/cli/help.js +240 -6
- package/dist/cli/input-preparation.js +54 -5
- package/dist/cli/memory-flow-admission.js +44 -0
- package/dist/cli/memory-init-invocation.js +78 -0
- package/dist/cli/memory-init.js +240 -0
- package/dist/cli/memory-storage-admission.js +53 -0
- package/dist/cli/models.js +39 -0
- package/dist/cli/native-hook-ingress.js +1 -1
- package/dist/cli/operator-profiles.js +61 -0
- package/dist/cli/output-options.js +35 -0
- package/dist/cli/response-file.js +71 -0
- package/dist/cli/run-cli.js +283 -160
- package/dist/cli/setup.js +149 -0
- package/dist/cli.js +54 -2
- package/dist/domain/stage-handler-identities.js +20 -0
- package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
- package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +4 -2
- package/dist/harness-runtime/lib/dd-codex-daemon.mjs +11 -5
- package/dist/harness-runtime/lib/dd-codex.mjs +22 -10
- package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
- package/dist/harness-runtime/lib/dd-droid.mjs +2 -1
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +4 -2
- package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +6 -4
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +9 -9
- package/dist/harness-runtime/lib/delegation-instructions.mjs +5 -3
- package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
- package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
- package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
- package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
- package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
- package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
- package/dist/harness-runtime/lib/opencode-plugin.mjs +2 -0
- package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
- package/dist/runtime/context.js +1 -1
- package/dist/schemas/discovery-result.schema.json +184 -0
- package/dist/schemas/execution-bundle.schema.json +205 -0
- package/dist/schemas/execution-settings.schema.json +162 -0
- package/dist/schemas/flow-descriptor.schema.json +54 -0
- package/dist/schemas/flow-run.schema.json +22 -0
- package/dist/schemas/harness-catalog.schema.json +80 -0
- package/dist/schemas/mb-init-compose-result.schema.json +457 -0
- package/dist/schemas/mb-init-discover-result.schema.json +500 -0
- package/dist/schemas/mb-init-finish-result.schema.json +422 -0
- package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
- package/dist/schemas/mb-init-review-result.schema.json +396 -0
- package/dist/schemas/mb-init-verify-result.schema.json +391 -0
- package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
- package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
- package/dist/schemas/memory-composition-work-result.schema.json +38 -0
- package/dist/schemas/memory-repair-work-result.schema.json +49 -0
- package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
- package/dist/schemas/memory-review-work-result.schema.json +43 -0
- package/dist/schemas/model-catalog.schema.json +153 -0
- package/dist/schemas/profile-settings.schema.json +122 -0
- package/dist/schemas/release-manifest.schema.json +291 -0
- package/dist/schemas/run-engine-binding.schema.json +1 -1
- package/dist/services/check-runner-evidence.js +51 -4
- package/dist/services/cli-operation-classifier.js +8 -47
- package/dist/services/cli-upgrade-allowlist.js +27 -0
- package/dist/services/code-checks.js +387 -34
- package/dist/services/controller-execution.js +88 -0
- package/dist/services/controller-fanout.js +71 -12
- package/dist/services/dashboard.js +8 -2
- package/dist/services/descriptor-coordinator-session.js +35 -0
- package/dist/services/descriptor-root-work.js +53 -0
- package/dist/services/descriptor-run-settlement.js +105 -0
- package/dist/services/descriptor-run-start.js +449 -0
- package/dist/services/descriptor-stage-coordinator.js +197 -0
- package/dist/services/descriptor-stage-settlement.js +222 -0
- package/dist/services/descriptor-stage-start.js +139 -0
- package/dist/services/discovery/agy-discovery.js +2 -0
- package/dist/services/discovery/codex-discovery.js +2 -0
- package/dist/services/discovery/droid-discovery.js +2 -0
- package/dist/services/discovery/grok-discovery.js +2 -0
- package/dist/services/discovery/opencode-discovery.js +2 -0
- package/dist/services/discovery/static.js +31 -0
- package/dist/services/discovery/zcode-discovery.js +2 -0
- package/dist/services/engines.js +39 -22
- package/dist/services/eval-snapshots.js +83 -25
- package/dist/services/execution-bundles.js +263 -0
- package/dist/services/execution-policy.js +20 -16
- package/dist/services/executor-onboarding.js +56 -0
- package/dist/services/external-work-launch.js +91 -11
- package/dist/services/flow-catalog.js +21 -0
- package/dist/services/flow-descriptors.js +82 -0
- package/dist/services/frozen-engine.js +242 -0
- package/dist/services/generic-execution.js +164 -0
- package/dist/services/harness-adapter.js +28 -2
- package/dist/services/harness-discovery.js +29 -0
- package/dist/services/harness-doctor.js +75 -0
- package/dist/services/harness-probe-effects.js +51 -0
- package/dist/services/harness-version-probe.js +100 -0
- package/dist/services/hooks.js +24 -6
- package/dist/services/hybrid-contracts.js +483 -0
- package/dist/services/ids.js +29 -1
- package/dist/services/installation-lock.js +95 -0
- package/dist/services/installed-flow-source.js +183 -0
- package/dist/services/lifecycle-invocations.js +257 -78
- package/dist/services/memory-accepted-composition.js +77 -0
- package/dist/services/memory-baseline-preservation.js +65 -0
- package/dist/services/memory-completed-correction-wave.js +320 -0
- package/dist/services/memory-compose-handler.js +258 -0
- package/dist/services/memory-composition-acceptance.js +199 -0
- package/dist/services/memory-composition-graph.js +134 -0
- package/dist/services/memory-composition-registration.js +146 -0
- package/dist/services/memory-composition-work-custody.js +151 -0
- package/dist/services/memory-composition-work-results.js +96 -0
- package/dist/services/memory-corrected-review-acceptance.js +129 -0
- package/dist/services/memory-corrected-review-batch.js +30 -0
- package/dist/services/memory-corrected-review-findings.js +106 -0
- package/dist/services/memory-corrected-review-inputs.js +210 -0
- package/dist/services/memory-corrected-review-projection.js +78 -0
- package/dist/services/memory-corrected-review-receipt.js +170 -0
- package/dist/services/memory-corrected-review-registration.js +191 -0
- package/dist/services/memory-correction-check-receipt.js +219 -0
- package/dist/services/memory-correction-input-owner.js +6 -0
- package/dist/services/memory-discover-handler.js +104 -0
- package/dist/services/memory-finish-evidence.js +435 -0
- package/dist/services/memory-finish-handler.js +215 -0
- package/dist/services/memory-finish-integration.js +280 -0
- package/dist/services/memory-finish-readiness.js +122 -0
- package/dist/services/memory-git-integration.js +151 -0
- package/dist/services/memory-historical-corrected-review.js +206 -0
- package/dist/services/memory-historical-original-review.js +130 -0
- package/dist/services/memory-historical-repair-registration.js +99 -0
- package/dist/services/memory-historical-second-review.js +128 -0
- package/dist/services/memory-init-bootstrap-readiness.js +210 -0
- package/dist/services/memory-init-contexts.js +89 -0
- package/dist/services/memory-init-controller-start.js +84 -0
- package/dist/services/memory-init-engine-release.js +223 -0
- package/dist/services/memory-init-git-policy.js +136 -0
- package/dist/services/memory-init-lint-capability.js +185 -0
- package/dist/services/memory-init-native-capacity.js +241 -0
- package/dist/services/memory-init-preflight.js +312 -0
- package/dist/services/memory-init-project-bootstrap.js +599 -0
- package/dist/services/memory-init-request-candidate.js +157 -0
- package/dist/services/memory-init-request-input.js +66 -0
- package/dist/services/memory-init-resource-storage.js +125 -0
- package/dist/services/memory-init-run-allocation.js +81 -0
- package/dist/services/memory-init-run-bundle.js +98 -0
- package/dist/services/memory-init-start.js +175 -0
- package/dist/services/memory-init-startup-custody.js +80 -0
- package/dist/services/memory-init-startup-input.js +240 -0
- package/dist/services/memory-init-storage.js +81 -0
- package/dist/services/memory-init-stores.js +359 -0
- package/dist/services/memory-init-worktrunk-capability.js +172 -0
- package/dist/services/memory-layer-publication.js +611 -0
- package/dist/services/memory-layer.js +156 -0
- package/dist/services/memory-lint-config.js +85 -0
- package/dist/services/memory-native-review-copy.js +165 -0
- package/dist/services/memory-normal-flow-entry.js +75 -0
- package/dist/services/memory-ordinary-defaults.js +112 -0
- package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
- package/dist/services/memory-preflight-handler.js +259 -0
- package/dist/services/memory-repair-current-view.js +299 -0
- package/dist/services/memory-repair-document-delta.js +451 -0
- package/dist/services/memory-repair-history.js +491 -0
- package/dist/services/memory-repair-physical-binding.js +312 -0
- package/dist/services/memory-repair-publication-files.js +152 -0
- package/dist/services/memory-repair-publication-intent.js +27 -0
- package/dist/services/memory-repair-publication-plan.js +160 -0
- package/dist/services/memory-repair-publication-source.js +225 -0
- package/dist/services/memory-repair-publication.js +794 -0
- package/dist/services/memory-repair-registration.js +239 -0
- package/dist/services/memory-repair-work-baseline.js +413 -0
- package/dist/services/memory-repair-work-completion.js +97 -0
- package/dist/services/memory-repair-work-custody.js +73 -0
- package/dist/services/memory-repair-work-results.js +89 -0
- package/dist/services/memory-repair-workspace.js +252 -0
- package/dist/services/memory-repair-writer-copy.js +735 -0
- package/dist/services/memory-result-binding.js +173 -0
- package/dist/services/memory-retained-review-authority.js +129 -0
- package/dist/services/memory-retained-review-results.js +70 -0
- package/dist/services/memory-retained-second-baseline.js +102 -0
- package/dist/services/memory-retained-second-repairs.js +156 -0
- package/dist/services/memory-review-acceptance.js +214 -0
- package/dist/services/memory-review-correction-plan.js +171 -0
- package/dist/services/memory-review-handler.js +585 -0
- package/dist/services/memory-review-inputs.js +200 -0
- package/dist/services/memory-review-receipt.js +180 -0
- package/dist/services/memory-review-registration.js +108 -0
- package/dist/services/memory-review-work-custody.js +124 -0
- package/dist/services/memory-review-work-input.js +72 -0
- package/dist/services/memory-review-work-results.js +73 -0
- package/dist/services/memory-second-corrected-review-inputs.js +165 -0
- package/dist/services/memory-second-correction-plan.js +76 -0
- package/dist/services/memory-second-repair-baseline.js +91 -0
- package/dist/services/memory-second-repair-launch.js +614 -0
- package/dist/services/memory-second-repair-registration.js +88 -0
- package/dist/services/memory-second-repair-source.js +187 -0
- package/dist/services/memory-second-review-acceptance.js +115 -0
- package/dist/services/memory-source-observations.js +117 -0
- package/dist/services/memory-stage-dispatch.js +28 -0
- package/dist/services/memory-stage-results.js +199 -0
- package/dist/services/memory-verification-acceptance.js +135 -0
- package/dist/services/memory-verification-checks.js +252 -0
- package/dist/services/memory-verification-receipt.js +159 -0
- package/dist/services/memory-verify-handler.js +135 -0
- package/dist/services/memory-work-result-preparation.js +63 -0
- package/dist/services/model-catalog.js +109 -0
- package/dist/services/model-discovery.js +46 -0
- package/dist/services/operator-profiles.js +236 -0
- package/dist/services/projects.js +17 -2
- package/dist/services/recovery-snapshot-database.js +416 -1
- package/dist/services/release-archive-producer.js +52 -0
- package/dist/services/release-archive.js +143 -0
- package/dist/services/release-cache.js +142 -0
- package/dist/services/release-compatibility.js +18 -0
- package/dist/services/release-download.js +67 -0
- package/dist/services/release-envelope.js +104 -0
- package/dist/services/release-manifest.js +45 -0
- package/dist/services/release-payload.js +114 -0
- package/dist/services/release-producer.js +63 -0
- package/dist/services/release-provenance.js +160 -0
- package/dist/services/release-registry.js +66 -0
- package/dist/services/release-source.js +194 -0
- package/dist/services/repair-intents.js +1 -1
- package/dist/services/review-copy.js +10 -2
- package/dist/services/run-control.js +80 -9
- package/dist/services/run-controller-capture.js +10 -3
- package/dist/services/run-controller-process.js +21 -0
- package/dist/services/run-controller-recovery.js +3 -1
- package/dist/services/run-controller-state.js +1 -1
- package/dist/services/run-controller.js +101 -40
- package/dist/services/run-recovery-guard.js +2 -0
- package/dist/services/run-recovery.js +145 -5
- package/dist/services/run-start-custody.js +177 -0
- package/dist/services/runs.js +319 -25
- package/dist/services/setup.js +377 -0
- package/dist/services/stage-context.js +9 -1
- package/dist/services/stage-handlers.js +74 -0
- package/dist/services/stage-report-renderer.js +63 -0
- package/dist/services/stage-work-graph.js +17 -0
- package/dist/services/vnext-code.js +3 -3
- package/dist/services/vnext-execution-profile.js +2 -2
- package/dist/services/vnext-fanout.js +70 -9
- package/dist/services/vnext-merge.js +8 -3
- package/dist/services/vnext-plan-review.js +6 -4
- package/dist/services/work-registry.js +616 -71
- package/dist/services/workspace-files.js +1 -1
- package/dist/storage/database.js +84 -6
- package/dist/storage/writer-contract.js +11 -7
- package/package.json +13 -3
- package/tools/create-canon-release.mjs +33 -0
- package/tools/produce-hybrid-release.mjs +41 -0
|
@@ -5,6 +5,10 @@ import { AppError, errorRecord } from "../shared/errors.js";
|
|
|
5
5
|
import { registerStoreWriter } from "../storage/writer-contract.js";
|
|
6
6
|
import { managedProcessRuntimeHome } from "./managed-processes.js";
|
|
7
7
|
import { cleanupScopeWriters } from "./scope-writer-cleanup.js";
|
|
8
|
+
import { hybridDigest } from "./hybrid-contracts.js";
|
|
9
|
+
import { readRunStartRequest } from "./run-start-custody.js";
|
|
10
|
+
import { readMemoryInitRunAllocation } from "./memory-init-run-allocation.js";
|
|
11
|
+
import { readMemoryInitStartupInput } from "./memory-init-startup-custody.js";
|
|
8
12
|
/** Export one RUN's relational evidence, never mutate the live authority. */
|
|
9
13
|
export function captureRecoveryDatabase(source, output, projectId, runId, protocolIds = []) {
|
|
10
14
|
source.exec(`VACUUM INTO '${output.replace(/'/g, "''")}'`);
|
|
@@ -21,6 +25,8 @@ export function captureRecoveryDatabase(source, output, projectId, runId, protoc
|
|
|
21
25
|
db.prepare("INSERT INTO capture_protocols VALUES (?)").run(id);
|
|
22
26
|
if (!db.prepare("SELECT 1 FROM runs WHERE (project_id, id) IN (SELECT * FROM capture_scope)").get())
|
|
23
27
|
throw new AppError("snapshot_run_missing", "Recovery export requires the selected RUN", 1);
|
|
28
|
+
assertCapturedBundleAuthority(db, projectId, runId);
|
|
29
|
+
assertCapturedStartAuthority(db, projectId, runId);
|
|
24
30
|
const ownRun = "(project_id, run_id) IN (SELECT * FROM capture_scope)";
|
|
25
31
|
const ownProject = "project_id IN (SELECT project_id FROM capture_scope)";
|
|
26
32
|
const works = `SELECT work_id FROM works WHERE ${ownRun}`;
|
|
@@ -52,13 +58,354 @@ export function captureRecoveryDatabase(source, output, projectId, runId, protoc
|
|
|
52
58
|
merge_servers: "0", merge_sessions: "0", merge_queue: "0", lanes: "0", lane_locks: "0", lane_waiters: "0",
|
|
53
59
|
sqlite_sequence: "0"
|
|
54
60
|
};
|
|
55
|
-
for (const table of ["works", "stage_work_memberships", "repair_intents", "check_receipts", "merge_requests", "flow_run_flag_mutations", "usage", "flow_session_segments", "flow_jobs", "run_recovery_guards", "run_controllers", "run_controls"])
|
|
61
|
+
for (const table of ["works", "stage_work_memberships", "repair_intents", "check_receipts", "merge_requests", "flow_run_flag_mutations", "usage", "flow_session_segments", "flow_jobs", "run_recovery_guards", "run_controllers", "run_controls", "run_bundle_authorities", "run_start_requests"])
|
|
56
62
|
rules[table] = ownRun;
|
|
57
63
|
for (const table of ["plan_bindings", "plan_progress", "worktree_records", "audit_events"])
|
|
58
64
|
rules[table] = `${ownProject} AND protocol_id IN (${protocols})`;
|
|
59
65
|
// Relocation proofs are RUN-owned provenance needed to map unchanged context
|
|
60
66
|
// bytes through subsequent recovery generations, not portable live authority.
|
|
61
67
|
rules.audit_events = `${ownProject} AND (protocol_id IN (${protocols}) OR (event_type = 'flow_run.publication_relocation' AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)))`;
|
|
68
|
+
// Bootstrap precedes RUN/project allocation: some owning receipts have
|
|
69
|
+
// NULL project_id. Select only the captured MB bundle's independently
|
|
70
|
+
// anchored request/roots, never all bootstrap receipts for this project.
|
|
71
|
+
// This preserves bytes; the bootstrap readers still validate the complete
|
|
72
|
+
// release/target/policy/engine/readiness chain before admitting recovery.
|
|
73
|
+
if (db.prepare("SELECT 1 FROM sqlite_schema WHERE type='table' AND name='run_bundle_authorities'").get()) {
|
|
74
|
+
const bootstrapReceipts = `EXISTS (SELECT 1 FROM run_bundle_authorities b JOIN runs r
|
|
75
|
+
ON r.project_id=b.project_id AND r.id=b.run_id
|
|
76
|
+
WHERE (b.project_id,b.run_id) IN (SELECT * FROM capture_scope)
|
|
77
|
+
AND json_extract(r.index_json,'$.execution_bundle.flow_id')='mb-init'
|
|
78
|
+
AND (audit_events.project_id IS NULL OR audit_events.project_id=b.project_id)
|
|
79
|
+
AND (
|
|
80
|
+
(event_type IN ('memory.init_git_policy','memory.init_release_selection','memory.init_startup_input','memory.init_startup_input_intent','memory.init_project_bootstrap_intent',
|
|
81
|
+
'memory.init_project_bootstrap','memory.init_engine_admission','memory.init_engine_bootstrap')
|
|
82
|
+
AND json_extract(payload_json,'$.scope.requestId')=json_extract(b.admission_json,'$.executionScope.requestId')
|
|
83
|
+
AND json_extract(payload_json,'$.scope.projectRoot')=json_extract(b.admission_json,'$.executionScope.projectRoot')
|
|
84
|
+
AND json_extract(payload_json,'$.scope.workspaceRoot')=json_extract(b.admission_json,'$.executionScope.workspace')
|
|
85
|
+
AND (
|
|
86
|
+
(event_type='memory.init_git_policy' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-git-policy@1')
|
|
87
|
+
OR (event_type='memory.init_release_selection' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-release-selection@1')
|
|
88
|
+
OR (audit_events.project_id IS NULL AND event_type='memory.init_startup_input' AND json_extract(payload_json,'$.schema_id') IN ('dd-flow/memory-init-startup-input@1','dd-flow/memory-init-startup-input@2','dd-flow/memory-init-startup-input@3'))
|
|
89
|
+
OR (audit_events.project_id IS NULL AND event_type='memory.init_startup_input_intent' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-startup-input-intent@1')
|
|
90
|
+
OR (event_type='memory.init_project_bootstrap_intent' AND json_extract(payload_json,'$.schema_id') IN
|
|
91
|
+
('dd-flow/memory-init-project-bootstrap-intent@1','dd-flow/memory-init-project-bootstrap-intent@2','dd-flow/memory-init-project-bootstrap-intent@3','dd-flow/memory-init-project-bootstrap-intent@4'))
|
|
92
|
+
OR (event_type='memory.init_project_bootstrap' AND json_extract(payload_json,'$.receipt.schema_id') IN
|
|
93
|
+
('dd-flow/memory-init-project-bootstrap@1','dd-flow/memory-init-project-bootstrap@2','dd-flow/memory-init-project-bootstrap@3','dd-flow/memory-init-project-bootstrap@4'))
|
|
94
|
+
OR (event_type='memory.init_engine_admission' AND json_extract(payload_json,'$.schema_id') IN
|
|
95
|
+
('dd-flow/memory-init-engine-admission@1','dd-flow/memory-init-engine-admission@2'))
|
|
96
|
+
OR (event_type='memory.init_engine_bootstrap' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-engine-bootstrap@1')))
|
|
97
|
+
OR (audit_events.project_id=b.project_id
|
|
98
|
+
AND event_type IN ('memory.init_run_allocation','memory.init_run_allocation_intent')
|
|
99
|
+
AND json_extract(payload_json,'$.run_id')=b.run_id
|
|
100
|
+
AND json_extract(payload_json,'$.scope.requestId')=json_extract(b.admission_json,'$.executionScope.requestId')
|
|
101
|
+
AND json_extract(payload_json,'$.scope.projectRoot')=json_extract(b.admission_json,'$.executionScope.projectRoot')
|
|
102
|
+
AND json_extract(payload_json,'$.scope.workspaceRoot')=json_extract(b.admission_json,'$.executionScope.workspace')
|
|
103
|
+
AND ((event_type='memory.init_run_allocation' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-run-allocation@1')
|
|
104
|
+
OR (event_type='memory.init_run_allocation_intent' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-run-allocation-intent@1')))
|
|
105
|
+
OR (event_type IN ('memory.bootstrap_ready','memory.bootstrap_readiness_intent')
|
|
106
|
+
AND json_extract(payload_json,'$.request_id')=json_extract(b.admission_json,'$.executionScope.requestId')
|
|
107
|
+
AND json_extract(payload_json,'$.project_root')=json_extract(b.admission_json,'$.executionScope.projectRoot')
|
|
108
|
+
AND json_extract(payload_json,'$.workspace_root')=json_extract(b.admission_json,'$.executionScope.workspace')
|
|
109
|
+
AND ((event_type='memory.bootstrap_ready' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-bootstrap-authority@1')
|
|
110
|
+
OR (event_type='memory.bootstrap_readiness_intent' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-bootstrap-readiness-intent@1')))))`;
|
|
111
|
+
rules.audit_events = `(${rules.audit_events}) OR (${bootstrapReceipts})`;
|
|
112
|
+
}
|
|
113
|
+
// Batch and composition registration are portable RUN evidence, not a host lease. Keep their
|
|
114
|
+
// independent receipt alongside the selected Works, never a neighboring
|
|
115
|
+
// RUN's receipt merely because it shares the project or names this RUN.
|
|
116
|
+
const batchReceipt = `event_type IN ('work.batch_registration', 'memory.composition_registration', 'memory.review_registration', 'memory.repair_registration', 'memory.second_repair_registration', 'memory.corrected_review_registration')
|
|
117
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
118
|
+
AND json_extract(payload_json, '$.scope.run_id') IN (SELECT run_id FROM capture_scope)
|
|
119
|
+
AND json_extract(payload_json, '$.scope.project_id') IN (SELECT project_id FROM capture_scope)
|
|
120
|
+
AND json_extract(payload_json, '$.scope.parent_work_id') IN (${works})
|
|
121
|
+
AND json_type(payload_json, '$.work_ids') = 'object'
|
|
122
|
+
AND NOT EXISTS (SELECT 1 FROM json_each(payload_json, '$.work_ids') WHERE value NOT IN (${works}))`;
|
|
123
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${batchReceipt}))`;
|
|
124
|
+
// Preserve independently admitted repair baselines by actual assigned
|
|
125
|
+
// Work/packet identity. Preservation never substitutes for owner admission.
|
|
126
|
+
const repairBaselineReceipt = `event_type = 'memory.repair_work_baseline'
|
|
127
|
+
AND json_extract(payload_json, '$.schema_id') IN ('dd-flow/memory-repair-work-baseline@2', 'dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@4', 'dd-flow/memory-repair-work-baseline@5')
|
|
128
|
+
AND json_extract(payload_json, '$.project_id') = project_id
|
|
129
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
130
|
+
AND EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
|
|
131
|
+
AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
|
|
132
|
+
AND w.work_id=json_extract(audit_events.payload_json, '$.work_id')
|
|
133
|
+
AND json_extract(w.payload_json, '$.kind')='memory-repair'
|
|
134
|
+
AND json_extract(w.payload_json, '$.memory_repair.packet_sha256')=json_extract(audit_events.payload_json, '$.packet_sha256'))`;
|
|
135
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairBaselineReceipt}))`;
|
|
136
|
+
// A consumed dependency/peer view is part of the baseline's history. It
|
|
137
|
+
// predates WorkSession start, so do not require a start receipt here.
|
|
138
|
+
const repairCurrentViewReceipt = `event_type='memory.repair_current_view'
|
|
139
|
+
AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-repair-current-view@1'
|
|
140
|
+
AND json_extract(payload_json,'$.project_id')=project_id
|
|
141
|
+
AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
142
|
+
AND EXISTS (SELECT 1 FROM audit_events b WHERE (${repairBaselineReceipt.replaceAll("audit_events.", "b.")})
|
|
143
|
+
AND b.project_id=audit_events.project_id
|
|
144
|
+
AND json_extract(b.payload_json,'$.schema_id') IN ('dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@5')
|
|
145
|
+
AND json_extract(b.payload_json,'$.run_id')=json_extract(audit_events.payload_json,'$.run_id')
|
|
146
|
+
AND json_extract(b.payload_json,'$.work_id')=json_extract(audit_events.payload_json,'$.work_id')
|
|
147
|
+
AND json_extract(b.payload_json,'$.generation')=json_extract(audit_events.payload_json,'$.generation')
|
|
148
|
+
AND json_extract(b.payload_json,'$.registration_sha256')=json_extract(audit_events.payload_json,'$.registration_sha256')
|
|
149
|
+
AND json_extract(b.payload_json,'$.current_view_sha256')=json_extract(audit_events.payload_json,'$.view_sha256'))`;
|
|
150
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairCurrentViewReceipt}))`;
|
|
151
|
+
const repairCopyReceipt = `event_type IN ('memory.repair_writer_copy_intent', 'memory.repair_writer_copy_build', 'memory.repair_writer_copy_ready')
|
|
152
|
+
AND json_extract(payload_json, '$.schema_id')='dd-flow/memory-repair-writer-copy-intent@1'
|
|
153
|
+
AND json_extract(payload_json, '$.project_id')=project_id
|
|
154
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
155
|
+
AND json_extract(payload_json, '$.work_id') IN (${works})
|
|
156
|
+
AND EXISTS (SELECT 1 FROM audit_events b JOIN works w
|
|
157
|
+
ON w.project_id=b.project_id AND w.run_id=json_extract(b.payload_json, '$.run_id')
|
|
158
|
+
AND w.work_id=json_extract(b.payload_json, '$.work_id')
|
|
159
|
+
WHERE b.project_id=audit_events.project_id AND b.event_type='memory.repair_work_baseline'
|
|
160
|
+
AND json_extract(b.payload_json, '$.schema_id') IN ('dd-flow/memory-repair-work-baseline@2', 'dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@4', 'dd-flow/memory-repair-work-baseline@5')
|
|
161
|
+
AND json_extract(b.payload_json, '$.project_id')=b.project_id
|
|
162
|
+
AND json_extract(b.payload_json, '$.run_id')=json_extract(audit_events.payload_json, '$.run_id')
|
|
163
|
+
AND json_extract(b.payload_json, '$.work_id')=json_extract(audit_events.payload_json, '$.work_id')
|
|
164
|
+
AND json_extract(b.payload_json, '$.generation')=json_extract(audit_events.payload_json, '$.generation')
|
|
165
|
+
AND json_extract(b.payload_json, '$.workspace_root')=json_extract(audit_events.payload_json, '$.source_root')
|
|
166
|
+
AND json_extract(w.payload_json, '$.kind')='memory-repair'
|
|
167
|
+
AND json_extract(w.payload_json, '$.memory_repair.packet_sha256')=json_extract(b.payload_json, '$.packet_sha256'))`;
|
|
168
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairCopyReceipt}))`;
|
|
169
|
+
// Retain start evidence by relational WorkSession/physical Session and
|
|
170
|
+
// baseline generation. Export is preservation, never start admission.
|
|
171
|
+
const repairStartReceipt = `event_type='memory.repair_work_start'
|
|
172
|
+
AND json_extract(payload_json, '$.schema_id')='dd-flow/memory-repair-start@1'
|
|
173
|
+
AND json_extract(payload_json, '$.project_id')=project_id
|
|
174
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
175
|
+
AND EXISTS (SELECT 1 FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id
|
|
176
|
+
JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
|
|
177
|
+
JOIN audit_events b ON b.project_id=w.project_id AND b.event_type='memory.repair_work_baseline'
|
|
178
|
+
WHERE w.project_id=audit_events.project_id AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
|
|
179
|
+
AND w.work_id=json_extract(audit_events.payload_json, '$.work_id')
|
|
180
|
+
AND json_extract(w.payload_json, '$.kind')='memory-repair'
|
|
181
|
+
AND ws.id=json_extract(audit_events.payload_json, '$.work_session_id')
|
|
182
|
+
AND ws.session_id=json_extract(audit_events.payload_json, '$.session_id')
|
|
183
|
+
AND ws.hook_event_id=json_extract(audit_events.payload_json, '$.hook_event_id')
|
|
184
|
+
AND s.harness=json_extract(audit_events.payload_json, '$.harness')
|
|
185
|
+
AND s.provider_session_id=json_extract(audit_events.payload_json, '$.provider_session_id')
|
|
186
|
+
AND json_extract(b.payload_json, '$.schema_id') IN ('dd-flow/memory-repair-work-baseline@2', 'dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@4', 'dd-flow/memory-repair-work-baseline@5')
|
|
187
|
+
AND json_extract(b.payload_json, '$.project_id')=w.project_id
|
|
188
|
+
AND json_extract(b.payload_json, '$.run_id')=w.run_id
|
|
189
|
+
AND json_extract(b.payload_json, '$.work_id')=w.work_id
|
|
190
|
+
AND json_extract(b.payload_json, '$.generation')=json_extract(audit_events.payload_json, '$.generation')
|
|
191
|
+
AND json_extract(b.payload_json, '$.packet_sha256')=json_extract(w.payload_json, '$.memory_repair.packet_sha256'))`;
|
|
192
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairStartReceipt}))`;
|
|
193
|
+
const nativeRepairBinding = `event_type='memory.repair_native_binding'
|
|
194
|
+
AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-repair-native-binding@1'
|
|
195
|
+
AND json_extract(payload_json,'$.project_id')=project_id
|
|
196
|
+
AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
197
|
+
AND EXISTS (SELECT 1 FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id
|
|
198
|
+
JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
|
|
199
|
+
JOIN hook_events he ON he.project_id=w.project_id AND he.event_key=ws.hook_event_id
|
|
200
|
+
WHERE w.project_id=audit_events.project_id AND w.run_id=json_extract(audit_events.payload_json,'$.run_id')
|
|
201
|
+
AND w.work_id=json_extract(audit_events.payload_json,'$.work_id')
|
|
202
|
+
AND json_extract(w.payload_json,'$.kind')='memory-repair'
|
|
203
|
+
AND ws.id=json_extract(audit_events.payload_json,'$.work_session_id')
|
|
204
|
+
AND he.event_key=json_extract(audit_events.payload_json,'$.hook_event_key') AND he.status='claimed'
|
|
205
|
+
AND he.session_id=ws.session_id AND s.provider_session_id=json_extract(audit_events.payload_json,'$.binding.provider_session_id')
|
|
206
|
+
AND he.parent_session_id=json_extract(audit_events.payload_json,'$.parent_session_id'))`;
|
|
207
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${nativeRepairBinding}))`;
|
|
208
|
+
const nativeReviewCopy = `event_type IN ('memory.native_review_copy_intent','memory.native_review_copy_ready')
|
|
209
|
+
AND COALESCE(json_extract(payload_json,'$.run_id'),json_extract(payload_json,'$.intent.run_id')) IN (SELECT run_id FROM capture_scope)
|
|
210
|
+
AND EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
|
|
211
|
+
AND w.run_id=COALESCE(json_extract(audit_events.payload_json,'$.run_id'),json_extract(audit_events.payload_json,'$.intent.run_id'))
|
|
212
|
+
AND w.work_id=COALESCE(json_extract(audit_events.payload_json,'$.work_id'),json_extract(audit_events.payload_json,'$.intent.work_id'))
|
|
213
|
+
AND json_extract(w.payload_json,'$.kind')='memory-review')`;
|
|
214
|
+
const nativeReviewBinding = `event_type='memory.native_review_binding'
|
|
215
|
+
AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
216
|
+
AND EXISTS (SELECT 1 FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id
|
|
217
|
+
JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
|
|
218
|
+
JOIN hook_events he ON he.project_id=w.project_id AND he.event_key=ws.hook_event_id
|
|
219
|
+
WHERE w.project_id=audit_events.project_id AND w.run_id=json_extract(audit_events.payload_json,'$.run_id')
|
|
220
|
+
AND w.work_id=json_extract(audit_events.payload_json,'$.work_id') AND json_extract(w.payload_json,'$.kind')='memory-review'
|
|
221
|
+
AND ws.id=json_extract(audit_events.payload_json,'$.work_session_id') AND he.status='claimed'
|
|
222
|
+
AND he.event_key=json_extract(audit_events.payload_json,'$.hook_event_key') AND he.session_id=ws.session_id
|
|
223
|
+
AND s.provider_session_id=json_extract(audit_events.payload_json,'$.provider_session_id'))`;
|
|
224
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND ((${nativeReviewCopy}) OR (${nativeReviewBinding})))`;
|
|
225
|
+
// Keep publication/settlement evidence only with the selected relational
|
|
226
|
+
// start and baseline. Export preserves bytes, never admits their hashes,
|
|
227
|
+
// physical effects or semantic correctness on restoration.
|
|
228
|
+
const repairPublicationSchemas = [
|
|
229
|
+
["memory.repair_publication_source", "dd-flow/memory-repair-publication-source@1"],
|
|
230
|
+
["memory.repair_publication_intent", "dd-flow/memory-repair-publication-intent@1"],
|
|
231
|
+
["memory.repair_publication_intent", "dd-flow/memory-repair-publication-intent@2"],
|
|
232
|
+
["memory.repair_publication_action_intent", "dd-flow/memory-repair-publication-action-intent@1"],
|
|
233
|
+
["memory.repair_publication_staging_build", "dd-flow/memory-repair-publication-staging@1"],
|
|
234
|
+
["memory.repair_publication_staging_ready", "dd-flow/memory-repair-publication-staging@1"],
|
|
235
|
+
["memory.repair_publication_file_ready", "dd-flow/memory-repair-publication-file-ready@1"],
|
|
236
|
+
["memory.repair_publication_directory_ready", "dd-flow/memory-repair-publication-directory-ready@1"],
|
|
237
|
+
["memory.repair_publication_action_complete", "dd-flow/memory-repair-publication-action-complete@1"],
|
|
238
|
+
["memory.repair_publication_complete", "dd-flow/memory-repair-publication-complete@1"],
|
|
239
|
+
["memory.repair_work_settlement", "dd-flow/memory-repair-work-settlement@1"],
|
|
240
|
+
];
|
|
241
|
+
const repairPublicationReceipt = `(${repairPublicationSchemas.map(([event, schema]) => `(event_type='${event}' AND json_extract(payload_json,'$.schema_id')='${schema}')`).join(" OR ")})
|
|
242
|
+
AND json_extract(payload_json,'$.project_id')=project_id
|
|
243
|
+
AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
244
|
+
AND EXISTS (SELECT 1 FROM audit_events a WHERE (${repairStartReceipt.replaceAll("audit_events.", "a.")})
|
|
245
|
+
AND a.project_id=audit_events.project_id
|
|
246
|
+
AND json_extract(a.payload_json,'$.run_id')=json_extract(audit_events.payload_json,'$.run_id')
|
|
247
|
+
AND json_extract(a.payload_json,'$.work_id')=json_extract(audit_events.payload_json,'$.work_id')
|
|
248
|
+
AND json_extract(a.payload_json,'$.generation')=json_extract(audit_events.payload_json,'$.generation')
|
|
249
|
+
AND json_extract(a.payload_json,'$.work_session_id')=json_extract(audit_events.payload_json,'$.work_session_id'))`;
|
|
250
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairPublicationReceipt}))`;
|
|
251
|
+
const coordinatorReceipt = `event_type = 'stage.coordinator_binding'
|
|
252
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
253
|
+
AND json_extract(payload_json, '$.scope.run_id') = json_extract(payload_json, '$.run_id')
|
|
254
|
+
AND json_extract(payload_json, '$.scope.project_id') = project_id
|
|
255
|
+
AND json_extract(payload_json, '$.work_id') IN (${works})
|
|
256
|
+
AND EXISTS (SELECT 1 FROM work_sessions ws WHERE ws.id = json_extract(payload_json, '$.work_session_id')
|
|
257
|
+
AND ws.work_id = json_extract(payload_json, '$.work_id') AND ws.session_id = json_extract(payload_json, '$.session_id'))
|
|
258
|
+
AND json_extract(payload_json, '$.session_id') IN (${sessions})`;
|
|
259
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${coordinatorReceipt}))`;
|
|
260
|
+
const descriptorRootReceipt = `event_type = 'flow_run.descriptor_root_work'
|
|
261
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
262
|
+
AND json_extract(payload_json, '$.binding.runId') = json_extract(payload_json, '$.run_id')
|
|
263
|
+
AND json_extract(payload_json, '$.binding.projectId') = project_id
|
|
264
|
+
AND json_extract(payload_json, '$.work_id') IN (${works})
|
|
265
|
+
AND EXISTS (SELECT 1 FROM runs r JOIN works w ON w.project_id=r.project_id AND w.run_id=r.id
|
|
266
|
+
WHERE r.project_id=audit_events.project_id AND r.id=json_extract(audit_events.payload_json, '$.run_id')
|
|
267
|
+
AND w.work_id=json_extract(audit_events.payload_json, '$.work_id') AND w.parent_work_id IS NULL
|
|
268
|
+
AND json_extract(r.index_json, '$.root_work_id')=w.work_id)`;
|
|
269
|
+
const descriptorCoordinatorReceipt = `event_type = 'flow_run.descriptor_coordinator'
|
|
270
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
271
|
+
AND json_extract(payload_json, '$.binding.runId') = json_extract(payload_json, '$.run_id')
|
|
272
|
+
AND json_extract(payload_json, '$.binding.projectId') = project_id
|
|
273
|
+
AND json_extract(payload_json, '$.work_id') IN (${works})
|
|
274
|
+
AND EXISTS (SELECT 1 FROM stage_work_memberships m WHERE m.project_id=audit_events.project_id
|
|
275
|
+
AND m.run_id=json_extract(audit_events.payload_json, '$.run_id') AND m.work_id=json_extract(audit_events.payload_json, '$.work_id')
|
|
276
|
+
AND m.stage=json_extract(audit_events.payload_json, '$.stage') AND m.attempt=json_extract(audit_events.payload_json, '$.binding.attempt'))`;
|
|
277
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND ((${descriptorRootReceipt}) OR (${descriptorCoordinatorReceipt})))`;
|
|
278
|
+
const descriptorSettlementReceipt = `event_type = 'flow_run.descriptor_stage_settlement'
|
|
279
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
280
|
+
AND json_extract(payload_json, '$.work_id') IN (${works})
|
|
281
|
+
AND EXISTS (SELECT 1 FROM stage_work_memberships m JOIN work_sessions ws ON ws.work_id=m.work_id
|
|
282
|
+
WHERE m.project_id=audit_events.project_id AND m.run_id=json_extract(audit_events.payload_json, '$.run_id')
|
|
283
|
+
AND m.work_id=json_extract(audit_events.payload_json, '$.work_id') AND m.stage=json_extract(audit_events.payload_json, '$.stage')
|
|
284
|
+
AND m.attempt=json_extract(audit_events.payload_json, '$.binding.attempt')
|
|
285
|
+
AND ws.id=json_extract(audit_events.payload_json, '$.work_session_id'))`;
|
|
286
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${descriptorSettlementReceipt}))`;
|
|
287
|
+
const memoryVerificationReceipt = `event_type = 'memory.verification_acceptance'
|
|
288
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
289
|
+
AND json_extract(payload_json, '$.project_id') = project_id
|
|
290
|
+
AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-verification-acceptance@1'
|
|
291
|
+
AND json_extract(payload_json, '$.stage') = 'verify'
|
|
292
|
+
AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
|
|
293
|
+
WHERE r.project_id=audit_events.project_id AND r.id=json_extract(payload_json, '$.run_id')
|
|
294
|
+
AND json_extract(s.value, '$.stage')='verify' AND json_extract(s.value, '$.status')='done'
|
|
295
|
+
AND json_extract(s.value, '$.attempt')=json_extract(payload_json, '$.attempt')
|
|
296
|
+
AND json_extract(s.value, '$.input_sha256')=json_extract(payload_json, '$.input_sha256')
|
|
297
|
+
AND json_extract(s.value, '$.data_sha256')=json_extract(payload_json, '$.result_sha256'))`;
|
|
298
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryVerificationReceipt}))`;
|
|
299
|
+
// Preservation only, not admission: reconnect independently restores the
|
|
300
|
+
// corrected view, owning policy and exact passed check rows.
|
|
301
|
+
const memoryCorrectionCheckReceipt = `event_type = 'memory.correction_checks'
|
|
302
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
303
|
+
AND json_extract(payload_json, '$.project_id') = project_id
|
|
304
|
+
AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-correction-checks@1'
|
|
305
|
+
AND json_extract(payload_json, '$.wave') IN (1, 2)
|
|
306
|
+
AND json_type(payload_json, '$.checks') = 'array'
|
|
307
|
+
AND json_array_length(payload_json, '$.checks') BETWEEN 1 AND 4096
|
|
308
|
+
AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
|
|
309
|
+
WHERE r.project_id=audit_events.project_id AND r.id=json_extract(payload_json, '$.run_id')
|
|
310
|
+
AND json_extract(s.value, '$.stage')='review'
|
|
311
|
+
AND json_extract(s.value, '$.input_sha256')=json_extract(payload_json, '$.review_input_sha256'))
|
|
312
|
+
AND NOT EXISTS (SELECT 1 FROM json_each(payload_json, '$.checks') c
|
|
313
|
+
WHERE NOT EXISTS (SELECT 1 FROM check_receipts cr WHERE cr.project_id=audit_events.project_id
|
|
314
|
+
AND cr.run_id=json_extract(audit_events.payload_json, '$.run_id') AND cr.id=json_extract(c.value, '$.id')))`;
|
|
315
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryCorrectionCheckReceipt}))`;
|
|
316
|
+
// Retain independently accepted review receipts only for the exact closed
|
|
317
|
+
// Stage and allocated reviewers. This is preservation, not replay admission.
|
|
318
|
+
const memoryReviewReceipt = `((event_type = 'memory.review_acceptance'
|
|
319
|
+
AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-review-acceptance@1'
|
|
320
|
+
AND json_extract(payload_json, '$.wave') = 0)
|
|
321
|
+
OR (event_type = 'memory.corrected_review_acceptance'
|
|
322
|
+
AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-corrected-review-acceptance@1'
|
|
323
|
+
AND (json_extract(payload_json, '$.wave') = 1
|
|
324
|
+
OR (json_extract(payload_json, '$.wave') = 2
|
|
325
|
+
AND json_type(payload_json, '$.first_review_proof_sha256') = 'text'
|
|
326
|
+
AND length(json_extract(payload_json, '$.first_review_proof_sha256')) = 64
|
|
327
|
+
AND json_extract(payload_json, '$.first_review_proof_sha256') NOT GLOB '*[^0-9a-f]*'))))
|
|
328
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
329
|
+
AND json_extract(payload_json, '$.project_id') = project_id
|
|
330
|
+
AND json_extract(payload_json, '$.stage') = 'review'
|
|
331
|
+
AND json_extract(payload_json, '$.registration_scope.project_id') = project_id
|
|
332
|
+
AND json_extract(payload_json, '$.registration_scope.run_id') = json_extract(payload_json, '$.run_id')
|
|
333
|
+
AND json_extract(payload_json, '$.registration_scope.stage') = 'review'
|
|
334
|
+
AND json_extract(payload_json, '$.registration_scope.attempt') = json_extract(payload_json, '$.attempt')
|
|
335
|
+
AND json_extract(payload_json, '$.registration_scope.input_sha256') = json_extract(payload_json, '$.input_sha256')
|
|
336
|
+
AND json_extract(payload_json, '$.registration_scope.parent_work_id') IN (${works})
|
|
337
|
+
AND json_type(payload_json, '$.workers') = 'array'
|
|
338
|
+
AND json_array_length(payload_json, '$.workers') BETWEEN 0 AND 256
|
|
339
|
+
AND (json_extract(payload_json, '$.wave') = 0 OR json_array_length(payload_json, '$.workers') > 0)
|
|
340
|
+
AND NOT EXISTS (SELECT 1 FROM json_each(payload_json, '$.workers') worker
|
|
341
|
+
WHERE NOT EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
|
|
342
|
+
AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
|
|
343
|
+
AND w.work_id=json_extract(worker.value, '$.work_id')))
|
|
344
|
+
AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
|
|
345
|
+
WHERE r.project_id=audit_events.project_id AND r.id=json_extract(payload_json, '$.run_id')
|
|
346
|
+
AND json_extract(s.value, '$.stage')='review' AND json_extract(s.value, '$.status')='done'
|
|
347
|
+
AND json_extract(s.value, '$.attempt')=json_extract(payload_json, '$.attempt')
|
|
348
|
+
AND json_extract(s.value, '$.input_sha256')=json_extract(payload_json, '$.input_sha256')
|
|
349
|
+
AND json_extract(s.value, '$.data_sha256')=json_extract(payload_json, '$.result_sha256'))`;
|
|
350
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryReviewReceipt}))`;
|
|
351
|
+
// Terminal evidence precedes Stage/RUN acceptance. Preserve only the
|
|
352
|
+
// selected MB bundle, exact finish input and independently closed review.
|
|
353
|
+
// Packet bytes remain under the existing Stage packet preservation rule.
|
|
354
|
+
const memoryFinishEvidence = `event_type='memory.finish_evidence'
|
|
355
|
+
AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-finish-evidence@1'
|
|
356
|
+
AND json_extract(payload_json,'$.project_id')=project_id
|
|
357
|
+
AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
358
|
+
AND json_extract(payload_json,'$.stage')='finish'
|
|
359
|
+
AND json_type(payload_json,'$.readiness_sha256')='text'
|
|
360
|
+
AND length(json_extract(payload_json,'$.readiness_sha256'))=64
|
|
361
|
+
AND json_extract(payload_json,'$.readiness_sha256') NOT GLOB '*[^0-9a-f]*'
|
|
362
|
+
AND EXISTS (SELECT 1 FROM runs r,json_each(r.index_json,'$.stage_runs') f,json_each(r.index_json,'$.stage_runs') v
|
|
363
|
+
WHERE r.project_id=audit_events.project_id AND r.id=json_extract(audit_events.payload_json,'$.run_id')
|
|
364
|
+
AND json_extract(r.index_json,'$.execution_bundle.flow_id')='mb-init'
|
|
365
|
+
AND json_extract(r.index_json,'$.execution_bundle.manifest_sha256')=json_extract(audit_events.payload_json,'$.bundle_sha256')
|
|
366
|
+
AND json_extract(f.value,'$.stage')='finish'
|
|
367
|
+
AND json_extract(f.value,'$.attempt')=json_extract(audit_events.payload_json,'$.attempt')
|
|
368
|
+
AND json_extract(f.value,'$.input_sha256')=json_extract(audit_events.payload_json,'$.input_sha256')
|
|
369
|
+
AND json_extract(v.value,'$.stage')='review' AND json_extract(v.value,'$.status')='done'
|
|
370
|
+
AND json_extract(v.value,'$.data_sha256')=json_extract(audit_events.payload_json,'$.review_sha256'))`;
|
|
371
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryFinishEvidence}))`;
|
|
372
|
+
const memoryFinishAcceptance = `event_type='memory.finish_acceptance'
|
|
373
|
+
AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-finish-acceptance@1'
|
|
374
|
+
AND json_extract(payload_json,'$.project_id')=project_id
|
|
375
|
+
AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
376
|
+
AND json_extract(payload_json,'$.stage')='finish'
|
|
377
|
+
AND json_type(payload_json,'$.evidence_sha256')='text'
|
|
378
|
+
AND length(json_extract(payload_json,'$.evidence_sha256'))=64
|
|
379
|
+
AND json_extract(payload_json,'$.evidence_sha256') NOT GLOB '*[^0-9a-f]*'
|
|
380
|
+
AND EXISTS (SELECT 1 FROM runs r,json_each(r.index_json,'$.stage_runs') f
|
|
381
|
+
WHERE r.project_id=audit_events.project_id AND r.id=json_extract(audit_events.payload_json,'$.run_id')
|
|
382
|
+
AND json_extract(r.index_json,'$.execution_bundle.flow_id')='mb-init'
|
|
383
|
+
AND json_extract(r.index_json,'$.execution_bundle.manifest_sha256')=json_extract(audit_events.payload_json,'$.bundle_sha256')
|
|
384
|
+
AND json_extract(f.value,'$.stage')='finish' AND json_extract(f.value,'$.status')='done'
|
|
385
|
+
AND json_extract(f.value,'$.attempt')=json_extract(audit_events.payload_json,'$.attempt')
|
|
386
|
+
AND json_extract(f.value,'$.input_sha256')=json_extract(audit_events.payload_json,'$.input_sha256')
|
|
387
|
+
AND json_extract(f.value,'$.data_schema_id')='dd-flow/mb-init-finish-result@1'
|
|
388
|
+
AND json_extract(f.value,'$.data_sha256')=json_extract(audit_events.payload_json,'$.result_sha256'))`;
|
|
389
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryFinishAcceptance}))`;
|
|
390
|
+
const descriptorRunSettlementReceipt = `event_type = 'flow_run.descriptor_run_settlement'
|
|
391
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
392
|
+
AND EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
|
|
393
|
+
AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
|
|
394
|
+
AND w.work_id=json_extract(audit_events.payload_json, '$.work_id') AND w.parent_work_id IS NULL)`;
|
|
395
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${descriptorRunSettlementReceipt}))`;
|
|
396
|
+
// Exact packet/report bytes remain predecessor and restart custody. A
|
|
397
|
+
// selected RUN's receipts have no protocol_id and must not be discarded.
|
|
398
|
+
const stageReceipt = `event_type IN ('flow_run.stage_packet', 'flow_run.stage_report', 'flow_run.descriptor_stage_start')
|
|
399
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
400
|
+
AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
|
|
401
|
+
WHERE r.project_id = audit_events.project_id AND r.id = json_extract(payload_json, '$.run_id')
|
|
402
|
+
AND json_extract(s.value, '$.stage') = json_extract(payload_json, '$.stage'))`;
|
|
403
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${stageReceipt}))`;
|
|
404
|
+
const startReceipt = `event_type IN ('flow_run.start_request', 'flow_run.start_root_owned', 'flow_run.start_published')
|
|
405
|
+
AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
|
|
406
|
+
AND EXISTS (SELECT 1 FROM runs r WHERE r.project_id = audit_events.project_id AND r.id = json_extract(payload_json, '$.run_id')
|
|
407
|
+
AND json_extract(r.index_json, '$.start_request.request_id') = json_extract(payload_json, '$.request_id'))`;
|
|
408
|
+
rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${startReceipt}))`;
|
|
62
409
|
for (const table of ["run_controller_events", "run_controller_operations"])
|
|
63
410
|
rules[table] = `controller_id IN (SELECT controller_id FROM run_controllers WHERE ${ownRun})`;
|
|
64
411
|
for (const table of ["run_control_admissions", "run_control_stage_admissions", "run_control_operations", "run_control_workers"])
|
|
@@ -104,6 +451,74 @@ export function captureRecoveryDatabase(source, output, projectId, runId, protoc
|
|
|
104
451
|
throw new AppError("snapshot_database_failed", primary instanceof Error ? primary.message : "Snapshot database cleanup failed", 1, { ...(failed ? { cause: errorRecord(primary) } : {}), snapshot_cleanup_errors: cleanup });
|
|
105
452
|
}
|
|
106
453
|
}
|
|
454
|
+
/** Validate retained allocation against the same consistent SQL copy. This
|
|
455
|
+
* preserves evidence only; absolute filesystem/engine paths are not relocated.
|
|
456
|
+
*/
|
|
457
|
+
function assertCapturedStartAuthority(db, projectId, runId) {
|
|
458
|
+
const marker = JSON.parse(db.prepare("SELECT index_json FROM runs WHERE project_id = ? AND id = ?").get(projectId, runId).index_json)?.start_request;
|
|
459
|
+
const hasTable = db.prepare("SELECT 1 FROM sqlite_schema WHERE type = 'table' AND name = 'run_start_requests'").get();
|
|
460
|
+
const row = hasTable ? db.prepare("SELECT request_id FROM run_start_requests WHERE project_id = ? AND run_id = ?").get(projectId, runId) : undefined;
|
|
461
|
+
const audit = db.prepare("SELECT json_extract(payload_json, '$.request_id') AS request_id FROM audit_events WHERE project_id = ? AND event_type = 'flow_run.start_request' AND json_extract(payload_json, '$.run_id') = ? LIMIT 1").get(projectId, runId);
|
|
462
|
+
if (!marker && !row && !audit)
|
|
463
|
+
return;
|
|
464
|
+
if (!marker || !row || !audit || marker.request_id !== row.request_id || row.request_id !== audit.request_id)
|
|
465
|
+
throw new AppError("snapshot_start_authority_invalid", "Captured RUN is missing its independent allocation evidence", 1);
|
|
466
|
+
// Adapt the read-only query surface, never open or migrate another store.
|
|
467
|
+
const context = { db: {
|
|
468
|
+
readSnapshot: (operation) => operation(), // The copied database writer already pins this snapshot.
|
|
469
|
+
get: (sql, parameters = []) => db.prepare(sql).get(...parameters),
|
|
470
|
+
all: (sql, parameters = []) => db.prepare(sql).all(...parameters)
|
|
471
|
+
} };
|
|
472
|
+
const retained = readRunStartRequest(context, projectId, row.request_id);
|
|
473
|
+
if (retained?.payload.initial_index.execution_bundle?.flow_id === "mb-init") {
|
|
474
|
+
const p = retained.payload;
|
|
475
|
+
// This adapter supplies only SQL reads; the reservation/readiness readers
|
|
476
|
+
// must not access a host home or physical engine during capture.
|
|
477
|
+
const allocation = readMemoryInitRunAllocation(context, { requestId: p.request_id, projectRoot: p.project_root, workspaceRoot: p.workspace_root });
|
|
478
|
+
if (!allocation || allocation.project_id !== projectId || allocation.run_id !== runId)
|
|
479
|
+
throw new AppError("snapshot_start_authority_invalid", "Captured memory RUN is missing its request-bound identity reservation", 1);
|
|
480
|
+
if (db.prepare(`SELECT 1 FROM audit_events WHERE event_type IN ('memory.init_startup_input','memory.init_startup_input_intent')
|
|
481
|
+
AND json_extract(payload_json,'$.scope.requestId')=? AND json_extract(payload_json,'$.scope.projectRoot')=? LIMIT 1`).get(p.request_id, p.project_root)) {
|
|
482
|
+
readMemoryInitStartupInput(context, { requestId: p.request_id, projectRoot: p.project_root, workspaceRoot: p.workspace_root });
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/** Check the consistent copied database, not a racy earlier read of the live
|
|
487
|
+
* store. Legacy evidence gains no descriptor or filesystem admission here.
|
|
488
|
+
*/
|
|
489
|
+
function assertCapturedBundleAuthority(db, projectId, runId) {
|
|
490
|
+
const run = db.prepare("SELECT index_json FROM runs WHERE project_id = ? AND id = ?").get(projectId, runId);
|
|
491
|
+
const hasTable = db.prepare("SELECT 1 FROM sqlite_schema WHERE type = 'table' AND name = 'run_bundle_authorities'").get();
|
|
492
|
+
const row = hasTable ? db.prepare("SELECT manifest_sha256, admission_json FROM run_bundle_authorities WHERE project_id = ? AND run_id = ?").get(projectId, runId) : undefined;
|
|
493
|
+
const invalid = () => { throw new AppError("snapshot_bundle_authority_invalid", "Captured RUN bundle anchor and independent authority disagree", 1); };
|
|
494
|
+
let anchor;
|
|
495
|
+
try {
|
|
496
|
+
anchor = JSON.parse(run.index_json)?.execution_bundle;
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
if (row)
|
|
500
|
+
invalid();
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (anchor === undefined) {
|
|
504
|
+
if (row)
|
|
505
|
+
invalid();
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (!anchor || anchor.schema_id !== "dd-flow/run-execution-bundle@1" || !row
|
|
509
|
+
|| [anchor.manifest_sha256, anchor.descriptor_sha256, anchor.admission_sha256].some(value => typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value))
|
|
510
|
+
|| typeof anchor.flow_id !== "string" || !anchor.flow_id || row.manifest_sha256 !== anchor.manifest_sha256
|
|
511
|
+
|| Buffer.byteLength(row.admission_json, "utf8") > 1024 * 1024)
|
|
512
|
+
invalid();
|
|
513
|
+
try {
|
|
514
|
+
const retained = JSON.parse(row.admission_json);
|
|
515
|
+
if (retained.runId !== runId || hybridDigest(retained) !== anchor.admission_sha256)
|
|
516
|
+
invalid();
|
|
517
|
+
}
|
|
518
|
+
catch {
|
|
519
|
+
invalid();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
107
522
|
/** Physical leases are evidence, not authority to resurrect on another host. */
|
|
108
523
|
export function readRecoveryResourceEvidence(resourceHome, projectId, runId, authority) {
|
|
109
524
|
const file = path.join(resourceHome, "runtime.sqlite");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { gzipSync } from "node:zlib";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { AppError } from "../shared/errors.js";
|
|
4
|
+
import { inspectReleaseArchive } from "./release-archive.js";
|
|
5
|
+
/** Deterministic regular-file-only tar/gzip. Extraction admission is also applied
|
|
6
|
+
* to producer output; producing bytes never grants them installation authority.
|
|
7
|
+
*/
|
|
8
|
+
export function produceReleaseArchive(files) {
|
|
9
|
+
const refuse = () => { throw new AppError("release_producer", "Archive production refused", 1, { reason: "invalid_archive_input", effect: "no_effect" }); };
|
|
10
|
+
if (!files.length || files.length > 100_000)
|
|
11
|
+
refuse();
|
|
12
|
+
const chunks = [];
|
|
13
|
+
let expanded = 1024;
|
|
14
|
+
const append = (name, bytes, mode, type) => {
|
|
15
|
+
expanded += 512 + Math.ceil(bytes.length / 512) * 512;
|
|
16
|
+
if (expanded > 512 * 1024 * 1024)
|
|
17
|
+
refuse();
|
|
18
|
+
const header = Buffer.alloc(512);
|
|
19
|
+
header.write(name);
|
|
20
|
+
header.write(mode.toString(8).padStart(7, "0") + "\0", 100);
|
|
21
|
+
header.write("0000000\0", 108);
|
|
22
|
+
header.write("0000000\0", 116);
|
|
23
|
+
header.write(bytes.length.toString(8).padStart(11, "0") + "\0", 124);
|
|
24
|
+
header.write("00000000000\0", 136);
|
|
25
|
+
header.fill(32, 148, 156);
|
|
26
|
+
header[156] = type;
|
|
27
|
+
header.write("ustar\0", 257);
|
|
28
|
+
header.write("00", 263);
|
|
29
|
+
header.write(header.reduce((sum, byte) => sum + byte, 0).toString(8).padStart(6, "0") + "\0 ", 148);
|
|
30
|
+
chunks.push(header, bytes, Buffer.alloc((512 - bytes.length % 512) % 512));
|
|
31
|
+
};
|
|
32
|
+
let index = 0;
|
|
33
|
+
for (const file of [...files].sort((a, b) => Buffer.compare(Buffer.from(a.path), Buffer.from(b.path)))) {
|
|
34
|
+
const length = Buffer.byteLength(file.path);
|
|
35
|
+
if (!length || length > 4096 || !Buffer.isBuffer(file.bytes) || typeof file.executable !== "boolean")
|
|
36
|
+
refuse();
|
|
37
|
+
let name = file.path;
|
|
38
|
+
if (length > 100) {
|
|
39
|
+
const record = `path=${file.path}\n`;
|
|
40
|
+
let size = Buffer.byteLength(record) + 2;
|
|
41
|
+
while (size !== Buffer.byteLength(record) + String(size).length + 1)
|
|
42
|
+
size = Buffer.byteLength(record) + String(size).length + 1;
|
|
43
|
+
append(`PaxHeaders/${index}`, Buffer.from(`${size} ${record}`), 0o644, 120);
|
|
44
|
+
name = `entries/${index}`;
|
|
45
|
+
}
|
|
46
|
+
append(name, file.bytes, file.executable ? 0o755 : 0o644, 48);
|
|
47
|
+
index++;
|
|
48
|
+
}
|
|
49
|
+
const bytes = gzipSync(Buffer.concat([...chunks, Buffer.alloc(1024)]), { level: 9 });
|
|
50
|
+
inspectReleaseArchive({ url: "https://producer.invalid/archive", bytes: bytes.length, sha256: createHash("sha256").update(bytes).digest("hex") }, bytes);
|
|
51
|
+
return bytes;
|
|
52
|
+
}
|