feat(cli): address team vaults as <project> <env> (#109)

`teams push|pull|grant` took a single `<vault>` name, so a team holding
more than one project had to encode both halves by hand and hope
everyone spelled it the same way. They now take `<project> <env>` and
join them into the `project/env` vault name.

The split lives entirely in the CLI — vaultName()/splitVaultName() are
the only things that know about it, and the server still stores one
opaque vault name — so there's no migration. Both halves reject a "/"
so the join stays unambiguous and the split is a true inverse.

`teams vaults` now breaks the name back into project/env columns,
falling back to the raw name for vaults created before the convention.
Those legacy vaults are no longer addressable (their names don't
contain a slash), so resolveVaultId() lists what the team actually has
instead of just saying "not found" — better than silently retargeting a
push, which in a secrets tool would write to the wrong vault.

Note push/pull carry two different "env"s: the `<env>` positional is
the environment half of the address, `--env` is the local .env path.
Verified commander keeps them separate.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-07-30 11:39:22 -07:00 committed by GitHub
parent 7c9796ae51
commit ca182bc057
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 130 additions and 23 deletions

View file

@ -183,15 +183,16 @@ re-wraps (seals) it to the new member's public key. The private key lives only i
logicsrc login
# Owner: create a team, push a local .env into an encrypted vault, invite people.
# A vault is addressed as <project> <env>, stored as the vault name project/env.
logicsrc teams create acme --name "Acme Inc"
logicsrc teams push acme prod --env .env # encrypt + upload
logicsrc teams push acme web prod --env .env # encrypt + upload
logicsrc teams invite acme teammate@example.com # emails an accept link
# Teammate: accept, then get granted, then pull + decrypt locally.
logicsrc login
logicsrc teams accept <token-from-email>
# …an existing member runs: logicsrc teams grant acme prod teammate@example.com
logicsrc teams pull acme prod --env .env # download + decrypt
# …an existing member runs: logicsrc teams grant acme web prod teammate@example.com
logicsrc teams pull acme web prod --env .env # download + decrypt
# Inspect / manage
logicsrc teams list