Files
slp-modular-cms/aidlc-docs/features/gitea-deployment-workflow/construction/plans/u2-data-durability-functional-design-plan.md
T
SluijsensandClaude Opus 5 5f3eda2680 Makes a redeploy safe for the key ring and the schema
Nothing here is visible in normal operation. Its whole purpose is that
swapping the release directory on deploy cannot silently destroy state.

Data Protection secures the API keys that authenticate master/slave
communication. Two separate defaults would each have destroyed them:
keys are held on the filesystem, which a release swap discards, and the
application discriminator is derived from the content root path, which
changes with every release directory — so even keys stored in a database
would have stopped being derivable. Keys now live in
ApplicationDbContext and the discriminator is a fixed constant.

Losing them produces no error. It produces stored keys that no longer
decrypt, which presents as an apparent network fault between a Master
and its slaves and is easily misdiagnosed. That is also why the tests
assert the resulting configuration rather than the registration: the
XmlRepository must be the EF one and the discriminator must be the
constant, plus a round-trip proving a value encrypted before a deploy is
readable after one. A test that only checked "Data Protection is
registered" would have passed in the broken case too.

Both modules previously called AddDataProtection() themselves. Module
registration runs after the host's, so those calls re-registered the
configuration chain and would have overridden the persistent store while
IDataProtector still resolved. They are removed, with a comment at each
site — the deletion otherwise looks like a regression. Each module's own
test project now guards against it being reintroduced.

ApplicationDbContext also migrates itself at startup. Deploy targets
offer no CLI, so migrations cannot be a manual step on the server.
Failures are classified rather than treated alike: a connection failure
means the database is not up yet, normal when the app and the database
start together after a reboot, and is retried with backoff; a migration
failure means something is broken and fails at once. Either way the
process does not start, which is what makes the liveness health check
trustworthy — an application that cannot reach its schema never answers
/health, so monitoring goes red instead of reporting a healthy instance
that cannot serve a request.

The cost of migrating without a human gate is that migrations must stay
forward-compatible and non-destructive, since rollback is "redeploy the
previous release". The new migration is purely additive.

Also wires this and the preceding hosting commit into both hosts, as
they touch the same lines of Program.cs.

Two constraints are enforced by documentation rather than code, and
belong in the deployment instructions: the key table must never be
pruned, and only one instance may migrate a given database at a time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
2026-07-28 00:00:45 +02:00

1.8 KiB

Functional Design Plan — U2 Data Durability

Unit: U2 Data Durability Round: R1 (with U1 Hosting & Serving) Requirements: FR-11, FR-12 Components: C-05, C-06, C-07, U2 portion of C-16


Step 1: Analyze unit context

  • Read the U2 definition from unit-of-work.md
  • Read the requirement assignment from unit-of-work-story-map.md
  • Read the carried-in design items — § 5.1 duplicate registration conflict, explicit application discriminator

Step 2: Design the Data Protection key ring

  • Define the key-storage entity and its owning context
  • Define the application-discriminator source and stability guarantee
  • Define key encryption at rest
  • Define key lifetime and rotation behaviour
  • Define the registration-order rule that resolves the duplicate-registration conflict

Step 3: Design startup migration behaviour

  • Define which contexts migrate and in what order
  • Define failure behaviour and what is logged before failing
  • Define behaviour when the database is temporarily unreachable at startup
  • Define behaviour when a migration is applied concurrently by two starting instances

Step 4: Define business rules

  • Enumerate key-ring durability rules
  • Enumerate migration rules
  • Identify error and edge-case scenarios

Step 5: Design verification approach

  • Define how "the persistent key store survives module registration" is asserted
  • Define how discriminator stability across a content-root change is asserted

Step 6: Generate artifacts

  • Generate business-logic-model.md
  • Generate business-rules.md
  • Generate domain-entities.md
  • Validate all diagrams against the Mermaid standards
  • Verify Security Baseline compliance for this unit's design