Skip to content

006 credential broker laptop push#35

Open
pofallon wants to merge 6 commits into
mainfrom
006-credential-broker-laptop-push
Open

006 credential broker laptop push#35
pofallon wants to merge 6 commits into
mainfrom
006-credential-broker-laptop-push

Conversation

@pofallon
Copy link
Copy Markdown
Contributor

  • docs(spec): add 006 credential broker (laptop-push model)
  • docs(spec): lock in Phase 0 decisions — pyrage + TOFU
  • docs(spec): pivot 006 from laptop-push to sidecar-devcontainer-push
  • Add broker-managed vault sidecar

pofallon and others added 6 commits May 30, 2026 13:13
Supersedes 005, which was implemented in PR #32 and closed without merge
once end-to-end testing on a real Proxmox container surfaced the
architectural mismatch: the bootstrap-token-on-instance design carries
a residual on-disk credential that contradicts the supply-chain threat
model the broker was built to defend against.

The new design: laptop encrypts a project-scoped secret bundle (age,
X25519 + ChaCha20-Poly1305) and pushes to the instance over SSH;
broker decrypts in memory via systemd-credentials (TPM2 → host-key →
plaintext-mode-0600 fallback ladder); devcontainers fetch via the
existing per-project Unix socket protocol with manifest allowlist
enforcement.

- spec.md: requirements, threat model, removed-from-005 list,
  architecture diagram, cross-cutting decisions
- plan.md: phased implementation (5 phases, ~3 weeks), what stays
  (~60%) / what goes (~30%) / what's new (~10%), open questions

Cross-repo: paired with remo-broker spec 002 (in flight via separate
PR) which supersedes that repo's 001-broker-daemon spec.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Q8 (age library): pyrage (Python binding around the Rust age crate).
  No user-side age install required; in-process; typed errors; testable.
- Q10 (first-contact trust model): TOFU. Pin silently on first contact
  (during remo create, SSH layer is already trusted); warn loudly on
  subsequent changes; provide remo {provider} repin <instance> to
  acknowledge legitimate rebuilds. Matches SSH host-key UX. Optional
  --strict-pin flag deferred until demand.

Q11 (per-project vs single global encrypted blob) remains open as a
Phase 2 implementation decision.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Second pivot in two days. The first 006 redesign (2026-05-30, laptop
pushes age-encrypted blob over SSH) was cleaner than 005 but still
keyed on the laptop being the source of truth, which doesn't match
remo's actual deployment (single-instance, not fleet). Moving the
source-of-truth into a dedicated sidecar devcontainer on the same LXC
eliminates the entire encryption-in-transit + pubkey-trust apparatus
while improving the multi-device-access story.

Architecture: each remo instance gets a dedicated _remo-vault sidecar
devcontainer alongside project devcontainers. The sidecar owns the
OAuth flows (gh / aws / claude login etc.) and holds the encrypted-
at-rest fnox storage. An inotify watcher in the sidecar pushes
plaintext to the broker over a local Unix socket whenever fnox state
changes. Broker becomes purely in-memory (no on-disk blob, no
LoadCredentialEncrypted). Project devcontainers get secrets via env
var injection (default) or tmpfs file materialization (opt-in via
manifest's new fetch_as directive). The manifest at .remo/manifest.toml
is bind-mounted read-only into project devcontainers — a malicious
dep cannot rewrite its own allowlist.

What disappears compared to the first 006 draft:
  - remo push-creds CLI command (push is local now, not from laptop)
  - remo {provider} repin (no pubkey to pin)
  - core/encrypted_blob.py, core/instance_keys.py
  - core/broker_admin.py NDJSON-over-SSH transport
  - age / pyrage dependency
  - /var/lib/remo-broker/secrets.enc on-disk blob
  - TOFU pubkey trust model decision

What's new:
  - Ansible roles: vault_devcontainer_install, vault_decryption_key_setup
  - Sidecar devcontainer image (debian-slim + gh/aws/claude/fnox + helpers)
  - remo-vault-watcher (inotify daemon in sidecar)
  - Helper scripts: remo-list-creds, remo-test-project, remo-vend-status,
    remo-reload
  - Devcontainer feature: remo/secrets-feature (project-side entrypoint
    helper that reads manifest, fetches from broker, injects env/file)
  - Manifest schema extension: fetch_as = "env" | "file" per secret
  - Read-only bind-mount of manifest into project devcontainers

Laptop CLI: unchanged. No new commands. All credential management
happens via remo shell -> _remo-vault picker entry.

Estimate down from ~3 weeks to ~2 weeks of focused work.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant