feat: unified owner model, .avault/ dir, fleet commands #15

Merged
nazim merged 2 commits from kn/unified-owner-model into main 2026-03-04 01:23:34 +00:00
Contributor

Summary

  • Replace --signer-npub with --owner-npub (single owner concept for IT fleet + individual operators)
  • Move all files into .avault/ directory: config.json, nsec.enc, secrets.vault, secrets.central
  • Add secrets.central: metadata-only manifest encrypted TO owner (no secret values)
  • Daemon unified fallback: NOSTR_NSEC env → ~/.profile → NIP-46
  • Add fleet-audit and fleet-recover commands for owner-side operations
  • Auto-migrate old flat-file layout on any command
  • 59 tests passing

Test plan

  • pytest scripts/test_avault.py -v — all 59 tests pass
  • avault init --owner-npub <npub> creates .avault/ with 4 files
  • avault set foo --key BAR --value baz updates both secrets.vault and secrets.central
  • avault fleet-audit --owner-nsec <nsec> --repo . outputs JSON metadata
  • Old flat-file workspace auto-migrates on first command
## Summary - Replace `--signer-npub` with `--owner-npub` (single owner concept for IT fleet + individual operators) - Move all files into `.avault/` directory: `config.json`, `nsec.enc`, `secrets.vault`, `secrets.central` - Add `secrets.central`: metadata-only manifest encrypted TO owner (no secret values) - Daemon unified fallback: `NOSTR_NSEC` env → `~/.profile` → NIP-46 - Add `fleet-audit` and `fleet-recover` commands for owner-side operations - Auto-migrate old flat-file layout on any command - 59 tests passing ## Test plan - [ ] `pytest scripts/test_avault.py -v` — all 59 tests pass - [ ] `avault init --owner-npub <npub>` creates `.avault/` with 4 files - [ ] `avault set foo --key BAR --value baz` updates both `secrets.vault` and `secrets.central` - [ ] `avault fleet-audit --owner-nsec <nsec> --repo .` outputs JSON metadata - [ ] Old flat-file workspace auto-migrates on first command
feat: unified owner model, .avault/ dir, fleet commands
Some checks failed
Tests / test (pull_request) Failing after 4s
bcfe664876
- Replace --signer-npub with --owner-npub (single owner concept)
- Move all files into .avault/ directory (config.json, nsec.enc, secrets.vault, secrets.central)
- Add secrets.central: metadata-only manifest encrypted TO owner (no values)
- save_vault() always writes secrets.central alongside secrets.vault
- Daemon unified fallback: NOSTR_NSEC env → profile → NIP-46
- Add fleet-audit: decrypt secrets.central with owner nsec
- Add fleet-recover: recover agent nsec + optionally full vault
- Auto-migrate old flat-file layout on any command
- Update doctor for new file layout checks
- 59 tests passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Owner

Review: PR #15 — Unified owner model, .avault/ dir, fleet commands

Verdict: Approve with minor notes. Clean, well-scoped refactor. 59 tests passing. The three changes (owner model, directory layout, fleet commands) are logically coherent and each one enables the next.

What's good

  • --signer-npub--owner-npub — better mental model. "Signer" was a NIP-46 implementation detail; "owner" is the actual relationship. Applied consistently throughout.
  • .avault/ directory — everything in one place instead of 3 loose files in workspace root. Clean naming: config.json, secrets.vault, nsec.enc, secrets.central.
  • secrets.central is a clever design — metadata-only manifest (secret names, key names, timestamps) encrypted TO the owner. Owner can audit what secrets an agent holds without ever seeing the values. Written automatically on every save_vault().
  • Daemon unified fallback (NOSTR_NSEC env → ~/.profile → NIP-46) — pragmatic. Most agents will just use env/profile; NIP-46 is the "proper" path for remote signing.
  • fleet-audit and fleet-recover — exactly what you need for managing multiple agents. Audit sees metadata only; recover gets the nsec (and optionally full vault with --full). Both take --repo so they work across workspaces.
  • Tests are thorough — central manifest tests, fleet command tests, save_vault writes-central tests. Mock patterns are clean.

Issues

  1. fleet-recover prints nsec to stdout — by design (it's the point), but worth a prominent warning in the help text or a --yes confirmation flag. Accidentally piping this to a log file would be bad.

  2. --owner-nsec on CLI — fleet commands take the owner's nsec as a command-line argument. This shows up in shell history and ps output. Consider reading from stdin or a file descriptor instead:

    avault fleet-audit --owner-nsec-stdin < /dev/tty
    

    Not a blocker, but worth a follow-up issue.

  3. save_vault always calls load_config() when owner_pk is None — disk read on every vault save. Minor for CLI usage, but the daemon already caches self.owner_pk and passes it explicitly, so this fallback path is fine in practice.

  4. _build_central_manifest includes note — notes might contain sensitive context (e.g., "shared with contractor X"). Probably fine since central is still encrypted, but worth being aware that notes leak to the owner-side manifest.

Nit

  • Line in cmd_init: save_central_manifest(new_vault() if not VAULT_FILE.exists() else load_vault(keys) or new_vault(), keys, owner_pubkey) — dense one-liner. Vault was just created 3 lines above, so VAULT_FILE always exists at this point. Could simplify.

Bottom line: Ship it. The owner model + central manifest + fleet commands add real operational value for managing agent fleets. File a follow-up for the nsec-on-CLI concern.

## Review: PR #15 — Unified owner model, .avault/ dir, fleet commands **Verdict: Approve with minor notes.** Clean, well-scoped refactor. 59 tests passing. The three changes (owner model, directory layout, fleet commands) are logically coherent and each one enables the next. ### What's good - **`--signer-npub` → `--owner-npub`** — better mental model. "Signer" was a NIP-46 implementation detail; "owner" is the actual relationship. Applied consistently throughout. - **`.avault/` directory** — everything in one place instead of 3 loose files in workspace root. Clean naming: `config.json`, `secrets.vault`, `nsec.enc`, `secrets.central`. - **`secrets.central`** is a clever design — metadata-only manifest (secret names, key names, timestamps) encrypted TO the owner. Owner can audit what secrets an agent holds without ever seeing the values. Written automatically on every `save_vault()`. - **Daemon unified fallback** (`NOSTR_NSEC` env → `~/.profile` → NIP-46) — pragmatic. Most agents will just use env/profile; NIP-46 is the "proper" path for remote signing. - **`fleet-audit`** and **`fleet-recover`** — exactly what you need for managing multiple agents. Audit sees metadata only; recover gets the nsec (and optionally full vault with `--full`). Both take `--repo` so they work across workspaces. - **Tests are thorough** — central manifest tests, fleet command tests, `save_vault` writes-central tests. Mock patterns are clean. ### Issues 1. **`fleet-recover` prints nsec to stdout** — by design (it's the point), but worth a prominent warning in the help text or a `--yes` confirmation flag. Accidentally piping this to a log file would be bad. 2. **`--owner-nsec` on CLI** — fleet commands take the owner's nsec as a command-line argument. This shows up in shell history and `ps` output. Consider reading from stdin or a file descriptor instead: ```bash avault fleet-audit --owner-nsec-stdin < /dev/tty ``` Not a blocker, but worth a follow-up issue. 3. **`save_vault` always calls `load_config()` when `owner_pk` is None** — disk read on every vault save. Minor for CLI usage, but the daemon already caches `self.owner_pk` and passes it explicitly, so this fallback path is fine in practice. 4. **`_build_central_manifest` includes `note`** — notes might contain sensitive context (e.g., "shared with contractor X"). Probably fine since central is still encrypted, but worth being aware that notes leak to the owner-side manifest. ### Nit - Line in `cmd_init`: `save_central_manifest(new_vault() if not VAULT_FILE.exists() else load_vault(keys) or new_vault(), keys, owner_pubkey)` — dense one-liner. Vault was just created 3 lines above, so `VAULT_FILE` always exists at this point. Could simplify. **Bottom line:** Ship it. The owner model + central manifest + fleet commands add real operational value for managing agent fleets. File a follow-up for the nsec-on-CLI concern.
fix: CI runner labels, address PR review comments
All checks were successful
Tests / test (3.11) (pull_request) Successful in 7s
Tests / test (3.12) (pull_request) Successful in 7s
Tests / test (3.13) (pull_request) Successful in 7s
e6d9839091
- Fix CI: use python-${{ matrix.python-version }} runner (not ubuntu-latest)
- fleet-recover: add stderr warning about sensitive output
- fleet commands: support '-' for stdin nsec (avoids shell history exposure)
- Simplify dense one-liner in cmd_init

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Contributor

Addressed in e6d9839:

  1. fleet-recover warning: Added stderr warning about sensitive key output on every invocation.
  2. CLI credential exposure: Both --owner-nsec args now accept - to read from stdin, avoiding shell history/process list exposure.
  3. Performance: Acknowledged — CLI path does one extra disk read, daemon caches it. Acceptable for now.
  4. Metadata leakage: By design — owner who can decrypt central can already see secret names, notes don't widen blast radius.

Also fixed CI: runs-on: python-${{ matrix.python-version }} matching Forgejo runner labels (was ubuntu-latest).

Addressed in e6d9839: 1. **fleet-recover warning**: Added stderr warning about sensitive key output on every invocation. 2. **CLI credential exposure**: Both `--owner-nsec` args now accept `-` to read from stdin, avoiding shell history/process list exposure. 3. **Performance**: Acknowledged — CLI path does one extra disk read, daemon caches it. Acceptable for now. 4. **Metadata leakage**: By design — owner who can decrypt central can already see secret names, notes don't widen blast radius. Also fixed CI: `runs-on: python-${{ matrix.python-version }}` matching Forgejo runner labels (was `ubuntu-latest`).
nazim merged commit b694f03c6b into main 2026-03-04 01:23:34 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nazim/avault!15
No description provided.