Records that the key-ring move leaves older ciphertext unreadable

Starting both hosts after U2 fails to decrypt a stored slave API key: the
row was encrypted under the old file-based key ring, and the database key
ring holds a different, freshly generated key. The key ring working
correctly is exactly why the old key is not found.

U2 moved the ring without a path for ciphertext that predates it. Confirmed
with the user that nothing is deployed yet, so no migration ships and the
first deploy meets an empty database. ASM-08 records the condition and makes
it blocking for U6 if it ever stops holding.

Also notes that the master lets the CryptographicException escape while the
slave catches it and reports "master API key rejected" instead — the
ambiguity U4's event was designed around, showing up on day one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HHoJpxYXzHACSQguHrC5fw
This commit is contained in:
2026-07-28 11:58:19 +02:00
co-authored by Claude Opus 5
parent 8e79a72340
commit 980dc80701
2 changed files with 35 additions and 2 deletions
@@ -335,6 +335,7 @@ DEV-01…04 are **pre-existing or cost-driven** and none is introduced by this f
| ASM-05 | The existing Umami instance at `analytics.slpsoftware.nl` remains available and its script origin can be added to the CSP. | FR-16, FR-18. | Umami setup gains host work, as in the reference project. |
| ASM-06 | One Sentry project with environment tags is acceptable for both backend and frontend events of this CMS. | D-19. | Split into more projects; only configuration changes. |
| ASM-07 | Existing Gitea secrets for the Pi (`PI_MAIN_*` in the reference project) can be reused or replicated for this repository. | FR-02. | New secrets are created; documented in FR-23. |
| ASM-08 | **No environment holds API keys encrypted under the old file-based key ring.** Confirmed by the user on 2026-07-28: the CMS is not deployed anywhere yet, so the first deploy of U2 meets an empty database. U2 therefore ships **no** one-time re-encryption path for pre-existing ciphertext. | U2 moved the Data Protection key ring from the filesystem into the database. Ciphertext written under the old ring cannot be decrypted by the new one — it fails with `The key {id} was not found in the key ring`. Observed locally on 2026-07-28 against rows written before U2, and resolved by deleting and re-registering. | **U6 must not deploy** until either the affected rows are cleared and the instances re-registered, or U2 gains a migration that reads the old ring as a fallback and re-encrypts. This is a silent, destructive failure of master/slave communication — exactly the class NFR-02 exists to prevent. |
---
@@ -353,9 +354,9 @@ DEV-01…04 are **pre-existing or cost-driven** and none is introduced by this f
This feature turns a manually deployed modular-monolith CMS into one with an automated, auditable pipeline, on hosting where nothing can be configured server-side.
**24 functional requirements, 10 non-functional requirements, 32 traced decisions, 7 assumptions, 2 remaining open items, 4 documented security deviations.**
**24 functional requirements, 10 non-functional requirements, 32 traced decisions, 8 assumptions, 2 remaining open items, 4 documented security deviations.**
*(FR-24 added and OPEN-02 closed at Application Design on 2026-07-27. OPEN-01 closed at NFR Design on 2026-07-28.)*
*(FR-24 added and OPEN-02 closed at Application Design on 2026-07-27. OPEN-01 closed at NFR Design on 2026-07-28. ASM-08 added on 2026-07-28 after the key-ring migration gap surfaced in local testing.)*
The three requirements that carry the most risk if implemented carelessly: