Implement safe password-store repository core (#3)
This commit is contained in:
35
docs/repository-core.md
Normal file
35
docs/repository-core.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Password-store repository core
|
||||
|
||||
`crates/storage::repository` maps logical entry names directly to the upstream
|
||||
password-store layout: `team/service` is stored as `team/service.gpg` and no
|
||||
IronStorage-specific metadata is added. Discovery inventories ordinary
|
||||
directories, encrypted entries, `.gpg-id`, `.gpg-id.sig`, auxiliary regular
|
||||
files, and `.git` directory boundaries. Git contents are not mistaken for
|
||||
password-store objects, and the innermost boundary applies to a nested entry.
|
||||
|
||||
Logical paths are relative component sequences. Absolute paths, `.` and `..`,
|
||||
empty entry paths, and entry paths with a trailing slash are rejected before
|
||||
filesystem access. A trailing slash in display-path resolution explicitly
|
||||
selects a directory. If both `name.gpg` and `name/` exist, the unadorned name is
|
||||
reported as ambiguous and mutations through the collision are rejected.
|
||||
|
||||
The repository is opened as a capability-scoped directory. All subsequent
|
||||
discovery, reads, temporary files, renames, and cleanup remain relative to that
|
||||
handle. Symlinks are rejected, and the capability layer prevents a raced link
|
||||
from escaping the selected vault. FIFOs, sockets, devices, and other special
|
||||
file types are also rejected; unrelated regular files remain visible as
|
||||
auxiliary repository objects.
|
||||
|
||||
Encrypted replacements are written to a temporary file in the destination
|
||||
directory, assigned private permissions on Unix, flushed to stable storage,
|
||||
atomically renamed over the destination, and followed by a directory sync.
|
||||
Before the rename, any error leaves the old entry intact and removes newly
|
||||
created empty directories. After the rename, the only possible observable
|
||||
state is the complete new entry; an interrupted directory sync is reported as
|
||||
durability-uncertain rather than pretending that rollback occurred. Empty
|
||||
ancestor cleanup uses directory-only removal and therefore stops at the store
|
||||
root, content, or a recipient-policy boundary.
|
||||
|
||||
Decrypted bytes use `SecretBytes`, which takes ownership without an additional
|
||||
copy, redacts `Debug`, exposes data only through explicit methods, and zeroes
|
||||
its allocation on drop.
|
||||
Reference in New Issue
Block a user