Files
chanora/poc/secure-storage-spike/VERIFICATION.md
T
EdisonJwa 50c95b61ad feat(poc/storage): add secure-storage spike (Linux)
Proof-of-concept proving the secure-storage exit criterion from
docs/architecture/proof-of-concept-plan.md §2:
  "Secret write/read/delete works through platform secure storage."

Implements a typed SecretStorageRepository trait per ADR-006
(SecureStore + per-platform adapters) and a Linux adapter (the only
adapter in PoC scope) that supports both equivalent Linux backends
per SysRS-053/SysRS-162: Secret Service (libsecret) and kernel
keyutils.

The audit test suite covers:
  SS-AUD-001  identity secret absent from local DB (raw file scan)
  SS-AUD-002  server password absent from local DB
  SS-AUD-003  secrets absent from logs (Secret newtype redaction)
  SS-AUD-005  failure returns safe typed error (NotFound)
  SS-AUD-006  delete removes entry
  SS-TC-003   Linux round-trip set/get/delete

Verified on 2026-05-13 against the local keyutils backend (cargo
test runs need 'keyctl session -' to provide a valid session
keyring under non-interactive shells, documented in the spike
README). The CLI driver additionally observed a real locked
gnome-keyring collection and exercised the typed-error → fallback
path live.

Surfaced finding for the decision register: DEC-013 does not pin
a Linux secure-storage backend policy. Both Secret Service and
keyutils are 'equivalent' per the requirements; production code
needs an owner ruling.

Out of scope: Windows DPAPI, macOS/iOS Keychain, Android Keystore,
SS-AUD-004 (covered by diagnostics-redaction spike), SS-AUD-007/008
(process / migration items).

Authority: PoC plan §2, ADR-006, SDD-078, SRS-091..095,
SysRS-158..162.
Not product code; not promoted into chanora_storage.
2026-05-14 12:26:23 +08:00

4.5 KiB

Verification record — secure-storage-spike

Result

PASS. The PoC exit criterion (from docs/architecture/proof-of-concept-plan.md §2: "Secret write/read/delete works through platform secure storage") is met on Linux through the kernel keyutils backend, with a documented Secret Service path verified manually via the CLI driver.

Environment

Field Value
Date 2026-05-13
Host OS Linux (Arch, kernel 7.0.5-arch1-1, x86_64)
Rust toolchain stable 1.95.0
Backend (tests) kernel keyutils (linux-native, add_key(2) / request_key(2))
Backend (CLI) tried Secret Service first; fell back to keyutils because the default Secret Service collection was locked (no graphical login)
keyring crate 3.6.3 (sync-secret-service, linux-native, crypto-rust)
linux-keyutils 0.2.5
rusqlite 0.32.1 (bundled)

Reproduction

keyctl session - cargo test --tests
keyctl session - cargo run --bin secure-storage-cli

Test run

running 6 tests
test ss_aud_003_secret_values_not_in_logs ... ok
test ss_aud_006_delete_removes_entry ... ok
test ss_aud_001_identity_secret_absent_from_local_db ... ok
test ss_aud_002_server_password_absent_from_local_db ... ok
test ss_aud_005_safe_error_on_missing_entry ... ok
test ss_tc_003_round_trip_linux ... ok

test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured;
                 0 filtered out; finished in 0.00s

CLI run

INFO spike: Secret Service unavailable (Platform secure storage failure:
            DBus error: Cannot create an item in a locked collection);
            falling back to keyutils
INFO spike: writing secret identity.primary
INFO spike: reading back
INFO spike: round-trip OK (48 bytes)
INFO spike: deleting
INFO spike: post-delete read correctly returned NotFound
OK — Linux Secret Service round-trip verified.

This CLI output also evidences SS-AUD-005 in practice: a locked Secret Service collection produced a typed Backend error containing no secret material, which the caller could then route to the fallback adapter rather than propagating the raw D-Bus message to the user.

Audit-check coverage

Check Mapped test(s) Result
SS-AUD-001 (Identity secret absent from local DB) ss_aud_001_identity_secret_absent_from_local_db PASS — raw SQLite file scanned for plaintext; only the lookup name appears.
SS-AUD-002 (Server password absent from local DB) ss_aud_002_server_password_absent_from_local_db PASS — same scan, distinct plaintext marker.
SS-AUD-003 (Secret values not in logs) ss_aud_003_secret_values_not_in_logs PASS — captured tracing output contains <redacted> markers; never contains the plaintext.
SS-AUD-005 (Failure → safe error) ss_aud_005_safe_error_on_missing_entry + CLI fallback path PASS — NotFound is the typed Display, no leakage.
SS-AUD-006 (Delete removes entry) ss_aud_006_delete_removes_entry PASS — second delete returns NotFound, not silent success.
SS-TC-003 (Linux round-trip) ss_tc_003_round_trip_linux PASS — set/get equality + delete + post-delete NotFound.

What this spike does NOT validate

  • SS-AUD-004 (diagnostic export redaction) — diagnostics-redaction-spike.
  • SS-AUD-007 (per-platform documentation completeness).
  • SS-AUD-008 (migration / import safety).
  • SS-TC-001 (Windows DPAPI / Credential Manager).
  • SS-TC-002 (macOS Keychain).
  • SS-TC-004 (Android Keystore).
  • SS-TC-005 (iOS Keychain).
  • Concurrent access from multiple threads / processes.
  • Long-lived persistence behaviour across reboots (keyutils backend is session-scoped by design).
  • Behaviour under a locked or absent Secret Service collection in production (mitigation strategy is shown but not policy).

Notable observations

  • The kernel keyutils session keyring is inherited from the calling process; non-interactive shells can present an expired _ses keyring. The wrapping keyctl session - is the documented workaround and is universal on Linux. Production code on a graphical session inherits a valid session from PAM and does not need it.
  • gnome-keyring on this host was running but the default collection was locked because no graphical login had occurred. The CLI's Secret-Service-first / keyutils-fallback path observed exactly this condition and reacted correctly, doubling as live evidence for SS-AUD-005.
  • The Secret newtype's Debug formatter prints Secret(<N bytes redacted>) and Display prints <redacted>. The SS-AUD-003 test exercises both representations.