Admin invite + user CLI (schema, store, subcommands) #4

Open
opened 2026-05-14 23:17:15 +02:00 by arne · 0 comments
Owner

Parent

#2

What to build

The admin-only operational surface, runnable on the host. Adds invite and user cobra subcommand trees. chat-posta invite create --name X mints a 24h one-shot invite code; invite list and invite revoke <code> cover lifecycle. user list and user delete <name|id> cover off-boarding. Schema for invites and users tables lands with migrations. The users table holds the columns required for signup (server_url, credential_id, credential_public_key, prf_salt, token_ciphertext, token_nonce) but is empty until Slice 3 lands.

Acceptance criteria

  • chat-posta invite create --name "Marcus" prints a registration URL using the configured base URL
  • Invite codes are at least 128 bits of crypto/rand entropy, base64url-encoded
  • chat-posta invite list shows outstanding invites (short code, name, created-at, expires-at)
  • chat-posta invite list --consumed shows consumed invites
  • chat-posta invite revoke <code> removes an outstanding invite; errors if already consumed
  • Invites expire 24h after creation; expired excluded from list-outstanding by default
  • chat-posta user list shows users (id, name, server URL, created-at, last-seen-at)
  • chat-posta user delete <name|id> deletes the user row
  • Schema migrations apply cleanly to a fresh SQLite and are idempotent on re-run
  • Unit tests in internal/store cover invite + user CRUD, uniqueness constraints, expiry semantics, atomic consumption

Blocked by

## Parent #2 ## What to build The admin-only operational surface, runnable on the host. Adds `invite` and `user` cobra subcommand trees. `chat-posta invite create --name X` mints a 24h one-shot invite code; `invite list` and `invite revoke <code>` cover lifecycle. `user list` and `user delete <name|id>` cover off-boarding. Schema for `invites` and `users` tables lands with migrations. The `users` table holds the columns required for signup (`server_url`, `credential_id`, `credential_public_key`, `prf_salt`, `token_ciphertext`, `token_nonce`) but is empty until Slice 3 lands. ## Acceptance criteria - [ ] `chat-posta invite create --name "Marcus"` prints a registration URL using the configured base URL - [ ] Invite codes are at least 128 bits of `crypto/rand` entropy, base64url-encoded - [ ] `chat-posta invite list` shows outstanding invites (short code, name, created-at, expires-at) - [ ] `chat-posta invite list --consumed` shows consumed invites - [ ] `chat-posta invite revoke <code>` removes an outstanding invite; errors if already consumed - [ ] Invites expire 24h after creation; expired excluded from list-outstanding by default - [ ] `chat-posta user list` shows users (id, name, server URL, created-at, last-seen-at) - [ ] `chat-posta user delete <name|id>` deletes the user row - [ ] Schema migrations apply cleanly to a fresh SQLite and are idempotent on re-run - [ ] Unit tests in `internal/store` cover invite + user CRUD, uniqueness constraints, expiry semantics, atomic consumption ## Blocked by - #3
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
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
posta/chat#4
No description provided.