Inventory module recovery ledger adoption
This commit is contained in:
@@ -44,6 +44,10 @@ least one check. The ledger verifies its hash chain before evidence is trusted.
|
||||
This is a platform contract, not an assertion that every existing module
|
||||
operation has adopted it. Module operations with external or multi-resource
|
||||
effects must be migrated to the ledger before claiming these guarantees.
|
||||
The owning-module inventory and adoption state are maintained in
|
||||
[Recovery Ledger Adoption](RECOVERY_LEDGER_ADOPTION.md); CI validates the
|
||||
machine-readable inventory so newly identified boundaries cannot disappear from
|
||||
the backlog silently.
|
||||
|
||||
## Deployment Journal
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Recovery Ledger Adoption
|
||||
|
||||
The Core recovery ledger is a platform primitive, not automatic protection for
|
||||
module-owned effects. The canonical, machine-checked inventory is
|
||||
[`recovery-operation-inventory.json`](recovery-operation-inventory.json).
|
||||
|
||||
## Classification Rules
|
||||
|
||||
- Use `atomic` only when every mutation commits in one database transaction and
|
||||
no external effect occurs.
|
||||
- Use `compensation` when every completed effect has a bounded, verifiable
|
||||
inverse action. A best-effort delete is not proof of compensation.
|
||||
- Use `snapshot_restore` only with fresh, signed backup evidence that covers all
|
||||
affected state services at one recovery point.
|
||||
- Use `forward_recovery` for provider acceptance, queue publication, cursor
|
||||
advancement, and other effects that may be resumable but cannot safely be
|
||||
undone.
|
||||
- Use `irreversible` for approved purge or destruction where no automated
|
||||
recovery is claimed.
|
||||
|
||||
One feature may cross more than one boundary. Module installation is
|
||||
compensatable before schema migration, forward-only after migration starts, and
|
||||
snapshot-restorable for an approved destructive retirement. Mail submission is
|
||||
forward recovery because losing the response after provider acceptance must not
|
||||
cause an automatic resend.
|
||||
|
||||
## Adoption Order
|
||||
|
||||
1. Campaign build is the reference implementation for a database plus object
|
||||
storage operation. Its operation reserves a build-specific object prefix,
|
||||
persists request and precondition evidence before writes, records the final
|
||||
object manifest, and verifies database/object state before success.
|
||||
2. Campaign delivery and Mail provider effects adopt outcome-unknown semantics
|
||||
without weakening their existing provider-specific idempotency records.
|
||||
3. Files applies the same contract to uploads, purge, integrity reconciliation,
|
||||
and writable connector synchronization.
|
||||
4. Connectors, Dataflow, and Workflow Engine consume the contract at their
|
||||
registry/capability boundaries so optional providers remain optional.
|
||||
5. Core module lifecycle uses the ledger in addition to, not instead of, signed
|
||||
deployment and backup evidence.
|
||||
|
||||
Every fenced operation uses a process incarnation and distributed lease. A
|
||||
stale process cannot append a checkpoint or report success. An expired operation
|
||||
is claimed for recovery through an explicit takeover that preserves the prior
|
||||
fence in the checkpoint chain; it is never resumed as a normal retry.
|
||||
|
||||
## Operator Contract
|
||||
|
||||
Ops lists non-terminal and manual-intervention operations. Operators must verify
|
||||
the checkpoint chain before trusting evidence, distinguish `outcome_unknown`
|
||||
from rejection, and use the owning module's documented reconciliation action.
|
||||
No evidence payload may contain credentials or resolved secrets.
|
||||
|
||||
The parent adoption issue remains open until all inventory rows are adopted and
|
||||
the module matrix proves crash, retry, stale-fence, tamper, and optional-module
|
||||
behavior for each consequential path.
|
||||
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"parent_issue": "https://git.add-ideas.de/GovOPlaN/govoplan/issues/36",
|
||||
"operations": [
|
||||
{
|
||||
"id": "campaign.build.publish-artifacts",
|
||||
"repository": "govoplan-campaign",
|
||||
"resources": ["postgresql", "object-storage", "templates-capability", "files-capability"],
|
||||
"mode": "compensation",
|
||||
"fenced": true,
|
||||
"adoption": "reference-implementation",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-campaign/issues/92"
|
||||
},
|
||||
{
|
||||
"id": "campaign.delivery.external-channels",
|
||||
"repository": "govoplan-campaign",
|
||||
"resources": ["postgresql", "queue", "smtp", "imap", "postbox", "print-provider"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-campaign/issues/92"
|
||||
},
|
||||
{
|
||||
"id": "campaign.retention.generated-artifacts",
|
||||
"repository": "govoplan-campaign",
|
||||
"resources": ["postgresql", "object-storage"],
|
||||
"mode": "compensation",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-campaign/issues/92"
|
||||
},
|
||||
{
|
||||
"id": "files.upload.finalize",
|
||||
"repository": "govoplan-files",
|
||||
"resources": ["postgresql", "object-storage", "filesystem-staging"],
|
||||
"mode": "compensation",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-files/issues/41"
|
||||
},
|
||||
{
|
||||
"id": "files.retention.purge",
|
||||
"repository": "govoplan-files",
|
||||
"resources": ["postgresql", "object-storage", "encryption-key-custody"],
|
||||
"mode": "irreversible",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-files/issues/41"
|
||||
},
|
||||
{
|
||||
"id": "files.integrity.reconcile",
|
||||
"repository": "govoplan-files",
|
||||
"resources": ["postgresql", "object-storage"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-files/issues/41"
|
||||
},
|
||||
{
|
||||
"id": "files.connector.write-sync",
|
||||
"repository": "govoplan-files",
|
||||
"resources": ["postgresql", "object-storage", "external-connector"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-files/issues/41"
|
||||
},
|
||||
{
|
||||
"id": "mail.outbox.smtp-submit",
|
||||
"repository": "govoplan-mail",
|
||||
"resources": ["postgresql", "queue", "smtp"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-mail/issues/19"
|
||||
},
|
||||
{
|
||||
"id": "mail.mailbox.imap-mutate",
|
||||
"repository": "govoplan-mail",
|
||||
"resources": ["postgresql", "imap"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-mail/issues/19"
|
||||
},
|
||||
{
|
||||
"id": "mail.mailbox.sync-cursor",
|
||||
"repository": "govoplan-mail",
|
||||
"resources": ["postgresql", "imap", "object-storage"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-mail/issues/19"
|
||||
},
|
||||
{
|
||||
"id": "connectors.sync.read-snapshot",
|
||||
"repository": "govoplan-connectors",
|
||||
"resources": ["postgresql", "external-provider"],
|
||||
"mode": "atomic",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-connectors/issues/15"
|
||||
},
|
||||
{
|
||||
"id": "connectors.sync.external-mutation",
|
||||
"repository": "govoplan-connectors",
|
||||
"resources": ["postgresql", "queue", "external-provider"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-connectors/issues/15"
|
||||
},
|
||||
{
|
||||
"id": "dataflow.run.database-only",
|
||||
"repository": "govoplan-dataflow",
|
||||
"resources": ["postgresql"],
|
||||
"mode": "atomic",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-dataflow/issues/19"
|
||||
},
|
||||
{
|
||||
"id": "dataflow.run.publish-output",
|
||||
"repository": "govoplan-dataflow",
|
||||
"resources": ["postgresql", "queue", "object-storage", "external-sink"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-dataflow/issues/19"
|
||||
},
|
||||
{
|
||||
"id": "workflow-engine.instance.state-transition",
|
||||
"repository": "govoplan-workflow-engine",
|
||||
"resources": ["postgresql"],
|
||||
"mode": "atomic",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-workflow-engine/issues/1"
|
||||
},
|
||||
{
|
||||
"id": "workflow-engine.activity.external-effect",
|
||||
"repository": "govoplan-workflow-engine",
|
||||
"resources": ["postgresql", "queue", "module-capability", "external-provider"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-workflow-engine/issues/1"
|
||||
},
|
||||
{
|
||||
"id": "core.module-lifecycle.pre-migration",
|
||||
"repository": "govoplan-core",
|
||||
"resources": ["postgresql", "package-environment", "webui-bundle", "filesystem"],
|
||||
"mode": "compensation",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-core/issues/281"
|
||||
},
|
||||
{
|
||||
"id": "core.module-lifecycle.post-migration",
|
||||
"repository": "govoplan-core",
|
||||
"resources": ["postgresql", "package-environment", "webui-bundle", "runtime-nodes"],
|
||||
"mode": "forward_recovery",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-core/issues/281"
|
||||
},
|
||||
{
|
||||
"id": "core.module-retirement.destroy-data",
|
||||
"repository": "govoplan-core",
|
||||
"resources": ["postgresql", "object-storage", "package-environment"],
|
||||
"mode": "snapshot_restore",
|
||||
"fenced": true,
|
||||
"adoption": "planned",
|
||||
"issue": "https://git.add-ideas.de/GovOPlaN/govoplan-core/issues/281"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user