Files
IronStorage/AGENTS.md
Chili Palmer b93ae852e0
Some checks failed
Dependency security audit / rustsec (push) Has been cancelled
Reuse native macOS Git credentials
2026-08-26 18:53:55 +02:00

93 lines
4.6 KiB
Markdown

# Repository instructions
## Architecture boundary
`crates/storage` owns all password-store behavior and all objects stored in or
derived from a password-store repository. This includes filesystem layout,
`.gpg-id` handling, GPG-compatible encryption and key handling, Git,
synchronization, conflict handling, entry parsing, password generation, OTP,
QR payloads, server/application identities, HTTPS Git credentials, and
secure-secret-storage orchestration. Git remotes are typed HTTPS or optional
SSH endpoints; reject local, helper, executable, and unknown transports before
entering Git transport code. Builds without the `ssh` feature must still parse
SSH endpoints and return a typed unsupported-transport error before connection
or repository mutation. When a password-store repository contains Git remotes,
those names and URLs are authoritative; use application configuration only as
the fallback for a repository without remotes.
The SSH feature must keep its algorithm allowlist, strict known-host checking,
single configured identity, bounded channel/diagnostic limits, and ambiguous
push outcome rules in `crates/storage`. The in-process SSH configuration reader
may honor only the connection directives `Host`, `HostName`, `User`, `Port`,
and `IdentityFile`. Do not add `Include`, `Match`, proxy commands, password or
keyboard-interactive authentication, host-key bypasses, or frontend transport
policy.
The CLI, Ratatui, Iced, Swift, SwiftUI, AutoFill, and watchOS code may collect
input, invoke the Rust API, and present Rust-provided state. They must not
duplicate storage rules, derive domain state from display strings, or directly
read or mutate a password-store repository.
Application code must not launch external processes. Do not invoke `pass`,
`git`, `gpg`, shell commands, or helper executables. Use pure Rust libraries.
Use FFI only where an operating-system API has no feasible Rust interface,
such as Apple authentication and secure-storage APIs; keep domain decisions in
`crates/storage`.
Keep project crates free of `unsafe` Rust. Isolate any unavoidable future FFI
implementation in the smallest platform-specific module and document its
safety contract.
## Compatibility
Compatibility means the upstream `pass` repository format and observable
behavior, including `pass-otp`; IronStorage must not introduce a competing
on-disk format. Prove new behavior with fixtures usable by both upstream tools
and `crates/storage` without executing those tools at application runtime.
## Required checks
Run these from the repository root before committing:
```sh
cargo fmt --all -- --check
RUSTFLAGS="-D warnings" cargo check --workspace --all-targets
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
```
For Apple project changes, also run `xcodegen generate` from `apple/` and build
the affected simulator targets.
### Updating the Simulator app
Treat the booted simulator and its app container as persistent test state. To
update IronStorage, build for that simulator and install the new `.app` over
the existing installation with `xcrun simctl install <device-udid> <app-path>`.
Keep the same device UDID and bundle identifier.
Do not uninstall IronStorage, erase or recreate the simulator, reset its
keychain, install app-data packages, or delete its app container during an app
update. Those are destructive reset operations, not update steps, and can
remove preferences, repositories, credentials, and biometric enrollment state.
### Simulator biometric validation
For initial setup only, select **Features > Face ID > Enrolled** before enabling
Biometric Unlock in the iPhone app. The user must then enable Biometric Unlock
and enter the GPG passphrase once so the protected passphrase is enrolled.
For normal validation, do not toggle **Enrolled** again. Tap the entry's
**Unlock** control first so an authentication request is active, then select
**Features > Face ID > Matching Face** and verify the app changes from locked to
unlocked. A matching face presented before **Unlock** does nothing. Use
**Non-matching Face** to test rejection without changing enrollment.
Apple's `biometryCurrentSet` access control invalidates a protected Keychain
item when Face ID is re-enrolled. Clearing or toggling **Enrolled** is therefore
a destructive negative test, not part of the normal unlock sequence. Only do it
when the issue explicitly requires changed-enrollment coverage and the user is
available to enter the GPG passphrase again. When deliberately returning to a
manual baseline, disable Biometric Unlock in IronStorage while the protected
record is still valid, then clear **Enrolled**.