You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #507 (PR #514, outer-volume scope shipped).
#507 added store_relay_config / get_relay_config / get_relay_config_or_default to HiddenStorage for the outer volume only. On a hidden-active session the current shipped behavior is:
get_relay_config returns Ok(None).
get_relay_config_or_default returns a fresh default.
store_relay_config errors with KeepError::NotImplemented.
Decision: Option (2) — hidden-active serve is interactive-only
We will not persist pre-grants on the hidden volume. keep nip46 grant (and the other grant-mutating subcommands) are rejected outright on a hidden-active session, and the only supported hidden-volume serve mode is interactive approval. Rationale:
Blast radius vs. benefit. The hidden volume is a single flat encrypted blob ([encrypted length][encrypted bincode Vec][random padding]), not a redb database. Persisting relay configs there means changing the serialized payload to a { keys, relay_configs } struct. load_hidden_records swallows deserialize errors and returns Ok(Vec::new()), so a naive format change would make an existing hidden vault silently appear to have lost every key. Safe implementation requires a versioned blob format + migration on the most unrecoverable data we hold. Not worth it for a non-blocking use case.
The real use case is already shipped.NIP-46 pre-grant CLI also works on hidden-vault serve paths #507's model is "outer-vault bunker with hidden vault available for real keys" — the bunker runs on the outer volume; the hidden vault holds real keys for interactive use. Nobody is blocked by the lack of hidden-active pre-grants.
Tension with the deniability goal. Pre-grants exist to enable unattended/headless operation. A long-lived headless daemon bound to the hidden identity (hidden password resident in memory, hidden-identity relay traffic) is itself a behavioral side channel that undermines plausible deniability. Option (1) would encourage the one usage pattern that most weakens the threat model.
When this decision should be revisited
If a concrete product requirement emerges for an unattended headless bunker running directly on the hidden volume (not the outer one). At that point implement option (1) with an explicit blob format-version byte and a migration path — never a bare struct swap.
Scope (option 2)
Reject keep nip46 grant / revoke / auto-approve on a hidden-active session with a clear, intentional error message (not a generic failure). Current KeepError::NotImplemented on store_relay_config is the enforcement point; surface a user-facing message that says hidden-volume grants are unsupported and that hidden-volume serve is interactive-only.
get_relay_config → Ok(None) and get_relay_config_or_default → default on hidden-active sessions remain the contract (so cmd_serve_hidden degrades to interactive cleanly with no outer leak).
Document the supported hidden-volume serve mode (interactive only) in the relevant CLI/serve docs or help text.
Acceptance
Decision recorded (this issue): option (2).
Hidden-active grant/revoke/auto-approve produce a clear "hidden-volume grants unsupported; serve is interactive-only" message rather than a generic error.
Test: hidden-active store_relay_config is refused and nothing lands in the outer volume blob (already covered by relay_config_returns_none_on_hidden_volume; extend with the CLI-surfaced message if a CLI seam exists).
Doc note covering the interactive-only constraint.
(Option (1)'s hidden-blob on-disk layout is explicitly out of scope under this decision; it is the "revisit" path above.)
Follow-up to #507 (PR #514, outer-volume scope shipped).
#507 added
store_relay_config/get_relay_config/get_relay_config_or_defaulttoHiddenStoragefor the outer volume only. On a hidden-active session the current shipped behavior is:get_relay_configreturnsOk(None).get_relay_config_or_defaultreturns a fresh default.store_relay_configerrors withKeepError::NotImplemented.Decision: Option (2) — hidden-active serve is interactive-only
We will not persist pre-grants on the hidden volume.
keep nip46 grant(and the other grant-mutating subcommands) are rejected outright on a hidden-active session, and the only supported hidden-volume serve mode is interactive approval. Rationale:[encrypted length][encrypted bincodeVec][random padding]), not a redb database. Persisting relay configs there means changing the serialized payload to a{ keys, relay_configs }struct.load_hidden_recordsswallows deserialize errors and returnsOk(Vec::new()), so a naive format change would make an existing hidden vault silently appear to have lost every key. Safe implementation requires a versioned blob format + migration on the most unrecoverable data we hold. Not worth it for a non-blocking use case.When this decision should be revisited
If a concrete product requirement emerges for an unattended headless bunker running directly on the hidden volume (not the outer one). At that point implement option (1) with an explicit blob format-version byte and a migration path — never a bare struct swap.
Scope (option 2)
keep nip46 grant/revoke/auto-approveon a hidden-active session with a clear, intentional error message (not a generic failure). CurrentKeepError::NotImplementedonstore_relay_configis the enforcement point; surface a user-facing message that says hidden-volume grants are unsupported and that hidden-volume serve is interactive-only.get_relay_config→Ok(None)andget_relay_config_or_default→ default on hidden-active sessions remain the contract (socmd_serve_hiddendegrades to interactive cleanly with no outer leak).Acceptance
grant/revoke/auto-approveproduce a clear "hidden-volume grants unsupported; serve is interactive-only" message rather than a generic error.store_relay_configis refused and nothing lands in the outer volume blob (already covered byrelay_config_returns_none_on_hidden_volume; extend with the CLI-surfaced message if a CLI seam exists).(Option (1)'s hidden-blob on-disk layout is explicitly out of scope under this decision; it is the "revisit" path above.)
Related
rotate-password,rotate-data-key,frost refreshsecurity-critical mutations #438 — umbrella for hidden-vault security-critical mutations (this is a sub-issue).