Add durable reconciliation decisions
This commit is contained in:
@@ -200,7 +200,12 @@ DOCUMENTATION = (
|
||||
"Every graph node declares typed inputs, configuration, output schema, and validation rules. "
|
||||
"Source nodes pin inline content or governed Datasource references; combine, filter, transform, "
|
||||
"quality, reconciliation, reusable-subflow, and output nodes remain explicit in the canonical graph. "
|
||||
"Reconciliation rows expose stable key hashes, explicit before/after values, and input hashes. A separate decision-table input can annotate exact matches, invalidate changed inputs, and report orphaned decisions without silently rewriting business data. "
|
||||
"Reconciliation rows expose stable key hashes, explicit before/after values, and input hashes. The "
|
||||
"review dialog records accept, reject, correct, or defer decisions in tenant-owned immutable decision "
|
||||
"sets. Their current projection is a fingerprinted Dataflow source; every superseded revision retains "
|
||||
"the actor, reason, exact input hash, time, and optional correction. A reconcile.decisions node can "
|
||||
"annotate exact matches, invalidate changed inputs, and report orphaned decisions without silently "
|
||||
"rewriting business data. "
|
||||
"Expressions use the typed Dataflow expression language and never execute arbitrary host or database "
|
||||
"code. Selecting a node may request a bounded intermediate preview; preview rows are transient, "
|
||||
"privacy-filtered for the actor, and are not retained as run output. SQL editing compiles into the same "
|
||||
@@ -218,6 +223,7 @@ DOCUMENTATION = (
|
||||
"dataflow.field.expression",
|
||||
"dataflow.field.schema",
|
||||
"dataflow.action.preview-node",
|
||||
"dataflow.action.review-decisions",
|
||||
],
|
||||
},
|
||||
),
|
||||
@@ -232,6 +238,8 @@ DOCUMENTATION = (
|
||||
"the revision and authorization grant, then re-evaluate authority for every delivery. Runs create "
|
||||
"durable command and recovery evidence. Publishing creates a governed Datasource materialization, and "
|
||||
"environment promotion changes which immutable revision is eligible for staging or production runs. "
|
||||
"Recording a reconciliation decision uses optimistic concurrency and appends an immutable revision; "
|
||||
"it never mutates the reviewed business row. "
|
||||
"Deletion prevents future use while retained run, deployment, lineage, audit, and recovery evidence "
|
||||
"continues under its retention policy."
|
||||
),
|
||||
@@ -247,12 +255,14 @@ DOCUMENTATION = (
|
||||
"dataflow.action.save",
|
||||
"dataflow.action.derive",
|
||||
"dataflow.action.trigger",
|
||||
"dataflow.action.record-decision",
|
||||
"dataflow.action.delete",
|
||||
],
|
||||
"consequence_classes": {
|
||||
"save_revision": "Appends an immutable pipeline definition revision.",
|
||||
"derive_copy": "Creates a separately governed copy pinned to the source revision and hash.",
|
||||
"configure_trigger": "Creates or changes an automation command with revision and authorization evidence.",
|
||||
"record_decision": "Appends an actor-attributed immutable decision revision against an exact input hash.",
|
||||
"delete_pipeline": "Prevents future use while retained evidence remains governed.",
|
||||
},
|
||||
},
|
||||
@@ -362,6 +372,22 @@ def _tenant_summary(session, tenant_id: str) -> dict[str, int]:
|
||||
)
|
||||
.count()
|
||||
),
|
||||
"dataflow_reconciliation_decision_sets": (
|
||||
session.query(dataflow_models.DataflowReconciliationDecisionSet)
|
||||
.filter(
|
||||
dataflow_models.DataflowReconciliationDecisionSet.tenant_id
|
||||
== tenant_id
|
||||
)
|
||||
.count()
|
||||
),
|
||||
"dataflow_reconciliation_decisions": (
|
||||
session.query(dataflow_models.DataflowReconciliationDecision)
|
||||
.filter(
|
||||
dataflow_models.DataflowReconciliationDecision.tenant_id
|
||||
== tenant_id
|
||||
)
|
||||
.count()
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -532,6 +558,14 @@ manifest = ModuleManifest(
|
||||
parent_id="dataflow.page",
|
||||
order=50,
|
||||
),
|
||||
ViewSurface(
|
||||
id="dataflow.decisions",
|
||||
module_id=MODULE_ID,
|
||||
kind="action",
|
||||
label="Reconciliation decisions",
|
||||
parent_id="dataflow.results",
|
||||
order=55,
|
||||
),
|
||||
ViewSurface(
|
||||
id="dataflow.triggers",
|
||||
module_id=MODULE_ID,
|
||||
@@ -580,6 +614,8 @@ manifest = ModuleManifest(
|
||||
script_location=str(Path(__file__).with_name("migrations") / "versions"),
|
||||
retirement_supported=True,
|
||||
retirement_provider=drop_table_retirement_provider(
|
||||
dataflow_models.DataflowReconciliationDecision,
|
||||
dataflow_models.DataflowReconciliationDecisionSet,
|
||||
dataflow_models.DataflowTriggerDelivery,
|
||||
dataflow_models.DataflowTrigger,
|
||||
dataflow_models.DataflowRun,
|
||||
@@ -597,6 +633,8 @@ manifest = ModuleManifest(
|
||||
persistent_table_uninstall_guard(
|
||||
dataflow_models.DataflowPipeline,
|
||||
dataflow_models.DataflowPipelineRevision,
|
||||
dataflow_models.DataflowReconciliationDecisionSet,
|
||||
dataflow_models.DataflowReconciliationDecision,
|
||||
dataflow_models.DataflowPipelineDeployment,
|
||||
dataflow_models.DataflowRun,
|
||||
dataflow_models.DataflowTrigger,
|
||||
@@ -614,7 +652,13 @@ manifest = ModuleManifest(
|
||||
known_limits=(
|
||||
"Execution adapters do not yet cover every declared node family.",
|
||||
),
|
||||
owned_concepts=("dataflow definition", "dataflow revision", "dataflow run", "transformation graph"),
|
||||
owned_concepts=(
|
||||
"dataflow definition",
|
||||
"dataflow revision",
|
||||
"dataflow run",
|
||||
"reconciliation decision set",
|
||||
"transformation graph",
|
||||
),
|
||||
non_owned_concepts=("datasource binding", "connector transport", "report presentation", "workflow task"),
|
||||
recovery_docs=("README.md", "docs/DURABLE_RUN_RECOVERY.md"),
|
||||
security_docs=("README.md",),
|
||||
|
||||
Reference in New Issue
Block a user