36 lines
2.1 KiB
Markdown
36 lines
2.1 KiB
Markdown
# 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.
|