arizuko › concepts › onboarding
A new user arrives. The onbod daemon decides whether they get in, which group they land in, and how their identity binds to one canonical sub. Three entry paths feed it: invite tokens, the admission queue, and the second-JID auto-link.
An operator mints a token with the CLI:
arizuko invite <instance> create <target_glob> [--max-uses N] [--expires DURATION]
arizuko invite <instance> list [--issued-by SUB]
arizuko invite <instance> revoke <token>
The token is a row in the invites table (owned by onbod). target_glob picks which group the redeemer lands in — for example corp/eng/* or a specific folder. --max-uses defaults to 1; --expires is a Go duration like 72h. Omit it and the token never expires.
The recipient opens the link, picks an OAuth provider (GitHub, Google, Discord, Telegram widget — whichever the instance has configured), and onbod writes an auth_users row keyed by the returned sub. See auth for what a sub is and how linking works.
When ONBOARDING_ENABLED=1, a new JID that hits the instance without an invite doesn’t go straight into a group. onbod sends an auth link via gated’s outbound API and writes the user into the queue.
The queue is gated by ONBOARDING_GATES — a list of rules like github-org=kronael, google-domain=example.com, or a catch-all. Each gate carries an optional daily limit. The admitFromQueue loop runs roughly every 60 seconds, counts admissions in the current day, and promotes queued users to approved until the gate’s limit is hit.
Queued users see their position on /onboard, which auto-refreshes every 30 seconds. Operators approve manually through dashd or by adjusting gate config.
Once a user is approved (via invite or queue), onbod calls container.SetupGroup(cfg, folder, prototype). That function is the only correct way to create a group — never mkdir a folder under groups/ by hand.
It creates the group directory plus logs/, copies the prototype tree if one is configured (ONBOARDING_PROTOTYPE), then runs seedGroupDir:
.claude/skills/ — every directory under ant/skills/ with a valid name is copied in. See skills..claude/CLAUDE.md — copied from ant/CLAUDE.md..claude/.claude.json — seeded with a per-folder user id (sha256 of arizuko:<folder>).node user can write.Skipping SetupGroup produces a folder the agent can’t use: no skills, no settings, wrong ownership. Everything onbod does for a brand-new user funnels through this one call.
A user who already has a world and shows up on a second platform — same human, new JID — doesn’t re-onboard. onbod detects the existing canonical sub via the OAuth callback and links the new JID to the existing world. No queue, no new group.
Invite tokens enforce max_uses at redemption: the UsedCount column increments, and RevokeInvite marks them dead. Expired tokens (expires_at < now) are refused with an error. Gate daily limits reset on UTC day boundaries — the queue counts admissions whose queued_at falls in the current day.
How identity becomes a signed header that downstream daemons trust: auth. What skills land in a freshly-seeded group: skills. Full token model, planned /v1/invites REST surface, and the cross-daemon flow: onbod/README.md. Spec: specs/5/1-auth-standalone.md.