Identity & token CLI #2
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
posta/server#2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What to build
Operator CLI for managing identities in the multi-tenant daemon. Atomic manifest rewrites (tmpfile + fsync + rename), Ed25519 keypair generation, per-identity DB initialization with migrations applied.
--print-tokenflag onidentity addis the bootstrap escape hatch — skips the invite flow and prints anmst_…directly. For everyone else, invites are created in #4.Existing
token *subcommands take a new required--slugflag to scope to one identity'sauth_tokenstable.Mutating commands print a "restart the daemon to load" hint rather than auto-firing the restart (Q8 of design grill).
Acceptance criteria
posta-server identity add --slug=X --url=Y --name=Z [--print-token]generates keys, creates DB, runs migrations, atomically rewrites manifestposta-server identity listreads manifest + verifies per-identity directory layoutposta-server identity remove --slug=Xdrops manifest entry, leaves data on disk (soft delete)posta-server identity purge --slug=X --yesremoves manifest entry AND deletes/var/lib/posta/<slug>/; supports--dry-runposta-server token create|list|revoke --slug=Xslug-scoped variants of existing commands[a-z0-9-]+only; reject anything else at write timeBlocked by
Agent Brief
Category: enhancement
Summary: Add operator CLI for managing multi-tenant identities and rework the existing
token *subcommands to be slug-scoped.Blocked by: #1 (the multi-tenant daemon skeleton must land first; this issue mutates the same manifest the daemon reads).
Current behavior:
There is no
identitysubcommand. Thetoken create|list|revokesubcommands take--configand--dbflags and operate on a single SQLite database — implicitly the only identity. There is no concept of multiple identities, no manifest mutation flow, no keypair generation outside of one-shot bootstrap, and no slug-based addressing.Desired behavior:
A new
identitysubcommand tree manages the lifecycle of identities in the manifest written by #1. Each mutation rewrites the manifest atomically. Thetokensubcommands become slug-scoped and operate against the per-identity database derived from the manifest. No mutating command restarts the daemon; instead each prints a clear "restart the daemon to load this change" hint. A bootstrap escape hatch lets the first identity be created without an invite (invites land in #4).Manifest mutation semantics:
Every command that writes the manifest must do so atomically: write to a temp file in the same directory,
fsyncthe temp file, thenrenameover the destination. A crash mid-write must never leave the manifest truncated, partially-written, or missing.Slug validation:
Slugs match
^[a-z0-9-]+$. Reject anything else at write time with a clear error. Slug collisions (a slug already present in the manifest) are a write-time error too.Per-identity layout (convention, not configured):
For an identity with
slug = "X", the daemon and CLI both expect:/var/lib/posta/X/keys.json/var/lib/posta/X/inbox.dbThe CLI creates these paths on
identity addand only deletes them onidentity purge.Key interfaces:
posta-server identity add --slug=X --url=Y --name=Z [--print-token] [--manifest=path]keys.json.--print-token: also mints and prints anmst_…bearer token (bootstrap escape hatch — skips the invite flow, suitable for the first identity on a fresh install).posta-server identity list [--manifest=path]posta-server identity remove --slug=X [--manifest=path]/var/lib/posta/X/on disk (soft delete).posta-server identity purge --slug=X --yes [--dry-run] [--manifest=path]/var/lib/posta/X/recursively. Requires--yesto proceed. With--dry-run, prints what would be removed and exits without touching anything.posta-server token create|list|revoke --slug=X [--manifest=path] [other existing flags]--slugvia the manifest. The legacy--dband--configflags are removed./etc/posta/identities.tomleverywhere;--manifestoverrides.Acceptance criteria:
identity addgenerates Ed25519 keys, creates the DB, runs migrations, and atomically rewrites the manifest in a single command.identity add --print-tokenadditionally mints and prints a bearer token in the same invocation.identity listreads the manifest and surfaces any per-identity directory drift without mutating state.identity removedrops the manifest entry and leaves the data directory untouched.identity purge --yesdrops the manifest entry and deletes the data directory; without--yesit refuses; with--dry-runit prints intent without acting.token create|list|revoke --slug=Xscope to the named identity'sauth_tokenstable; running them without--slugfails with a clear error.--dband--configflags are gone fromtoken *;--manifestis available with default/etc/posta/identities.toml.^[a-z0-9-]+$is enforced at write time; invalid slugs produce a clear error.purge --dry-run; manifest atomicity (truncate after rename should still leave a valid manifest).Out of scope:
identity add --print-token.slug/urlshape established by #1.