Implement insert and edit sessions (#7)
This commit is contained in:
52
docs/write-domains.md
Normal file
52
docs/write-domains.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Insert and edit domains
|
||||
|
||||
`VaultWriter` in `crates/storage` owns insertion, edit concurrency, recipient
|
||||
selection, encryption, repository mutation, rollback, and commit intent.
|
||||
Frontends collect input and overwrite decisions but cannot write an encrypted
|
||||
entry directly.
|
||||
|
||||
## Insert
|
||||
|
||||
`InsertContent` has distinct constructors for hidden confirmed input, echoed
|
||||
single-line input, and exact multiline bytes. Hidden values must match their
|
||||
confirmation; both single-line modes reject empty values and embedded line
|
||||
breaks. Multiline input preserves every byte and may be empty. The content mode
|
||||
must equal the parsed `InsertRequest`, preventing an adapter from silently
|
||||
changing stdin semantics.
|
||||
|
||||
An existing entry requires either `--force` or an explicit allow decision. A
|
||||
decline returns before recipient resolution or encryption. The nearest signed
|
||||
or unsigned recipient policy is resolved for the destination, plaintext is
|
||||
consumed by embedded OpenPGP encryption, and repository replacement is atomic.
|
||||
The storage commit boundary is invoked only afterward with the compatible
|
||||
`Add given password ...` intent. Commit failure restores the exact old
|
||||
ciphertext or removes a newly created entry and its empty parent directories.
|
||||
|
||||
## Edit sessions
|
||||
|
||||
Beginning a session snapshots the original encrypted bytes and decrypts an
|
||||
existing entry into redacted `SecretBytes`; a missing entry starts with empty
|
||||
contents so `pass edit` can create it. Finishing consumes replacement
|
||||
`SecretBytes`. Unchanged content returns without encryption or commit. Before
|
||||
writing, storage compares current encrypted bytes with the snapshot (or checks
|
||||
that a new path is still absent), so concurrent replacement, removal, or
|
||||
creation is rejected without overwriting the other writer.
|
||||
|
||||
Successful replacement uses the destination's current recipient policy and
|
||||
records compatible editor commit intent. A commit error restores the prior
|
||||
state. Rollback failure retains both the commit and repository errors.
|
||||
|
||||
## CLI editor boundary
|
||||
|
||||
Editor precedence remains TOML configuration, `VISUAL`, `EDITOR`, then `vim`,
|
||||
with the program and arguments parsed without a shell. The CLI adapter converts
|
||||
that value to one `EditorInvocation` for a narrowly injected `EditorHost`;
|
||||
storage, TUI, GUI, iOS, and watchOS never receive executable information and
|
||||
continue to use the in-process replacement API.
|
||||
|
||||
Before invoking the host, the CLI creates a mode-0600 plaintext file inside a
|
||||
private temporary directory. Linux prefers `/dev/shm` when available; native
|
||||
temporary storage is the fallback. The file is never inside the vault. A saved
|
||||
file is bounded before reading. Saved, cancelled, failed, and host-error paths
|
||||
all overwrite the file with zeros, truncate and sync it, remove it, and finally
|
||||
drop the private directory. Returned replacement bytes remain zeroizing.
|
||||
Reference in New Issue
Block a user