32 lines
2.1 KiB
Markdown
32 lines
2.1 KiB
Markdown
# Deferred items — Phase 10
|
|
|
|
Out-of-scope discoveries found while executing this phase. Logged, not fixed.
|
|
|
|
## From 10-01 (KEY-01 / F-01)
|
|
|
|
**Flaky test: `credentials::operations::tests::test_list_credentials_no_filter`**
|
|
|
|
- Discovered: 2026-08-02, during the post-plan full-suite run (`cargo test -p archipelago`).
|
|
- Symptom: `called Result::unwrap() on an Err value: UTF-8 credentials / invalid utf-8 sequence
|
|
of 1 bytes from index 3`.
|
|
- Root cause (read, not fixed): `credentials/store.rs:29` sniffs the FIRST BYTE of the stored
|
|
blob for `[` or `{` to distinguish a plaintext-JSON legacy store from the encrypted binary
|
|
one. When the encrypted ciphertext happens to begin with `0x5B` or `0x7B` — about a 1-in-128
|
|
chance per run — the encrypted store is misread as plaintext and `String::from_utf8` fails.
|
|
This is a real bug in the migration sniffing, not just a test problem: a real node whose
|
|
credential ciphertext starts with one of those bytes cannot load its credentials.
|
|
- Why deferred: unrelated to KEY-01, different subsystem, untouched by this plan
|
|
(`git status` shows `credentials/` unmodified). Fixing it means adding a format marker or
|
|
version header to the store, which is an envelope change.
|
|
- Suggested fix: prepend an explicit magic/version byte on write and branch on that, keeping the
|
|
first-byte sniff only as the legacy fallback.
|
|
- **RESOLVED 2026-08-02** — fixed along the suggested lines, with one improvement. Writes are now
|
|
prefixed with a fixed `ARCHYCRED1` marker, which cannot collide with a random nonce. Legacy
|
|
unmarked files are detected by *successful AEAD decryption* rather than by a byte sniff: a
|
|
Poly1305 tag that verifies under the node key is a cryptographic discriminator (~2^-128 false
|
|
positive), strictly stronger than the structural sniff the fallback would have kept. Plaintext
|
|
JSON stays the last resort, and an undecodable file now errors instead of silently becoming an
|
|
empty store that the next save would overwrite. Legacy files upgrade on write, never on read.
|
|
Regression tests drive the collision deterministically via an explicit nonce (`0x5B`/`0x7B`)
|
|
instead of waiting on the 1-in-128 draw.
|