# AC — Second-member onboarding (Demimonde admin invites) ## Goal Get a **second** human into an existing org — invited by an admin (Quinn-as-Demimonde-admin) rather than walking in cold — from invitation to a working CocotteAI seat in under 5 minutes, with the org's context, templates, and shared scaffolding pre-filling everything the new member would otherwise have to discover. The defining contrast: D is the cold first-run for a stranger (the org doesn't exist yet); Y is a cross-org stranger discovering Demimonde on the open marketplace; **AC is the warm path** — admin already trusts the invitee, the org already exists, and most of the persona-seed work has been done at the org level and merely needs to be **inherited, distinguished, and where appropriate overridden**. ## Designer skim - **Headline UX**: Admin pulls up the W3 roster drawer → "Invite" → role picker (Member / Viewer) → composer for email + optional iMessage (routed through Demimonde-owned channel, never the admin's personal number). Invitee receives a warm splash that names the org and the admin, taps through SSO device-link (same component as D1), then lands in a **pre-filled** persona-seed interview where org-template defaults occupy the chip slots and the composer. Invitee can accept-as-is, edit, or fully override. Voice register working throughout (operational, not cold-stranger hearth); the splash gets one slightly warmer line for first-impression. - **Key invariant vs D**: persona is **not blank**. Org has already established voice register, off-limits, surface roster, autonomy posture. Invitee inherits these as **defaults**, sees them visually distinguished from anything they personalize, and can opt into copying admin's curated content / contacts / blocklist for a first-week scaffold. - **Pair-with**: [`persona-seed-interview.screen.md`](./persona-seed-interview.screen.md) (the underlying screen, in pre-filled mode); [`D-onboarding.brief.md`](./D-onboarding.brief.md) (cold counterpart); [`W-org-overlay.brief.md`](./W-org-overlay.brief.md) §W3 roster, §W2 mixed-scope, §W5 voice shift. - **Blocking Qs**: AC-Q1 default role, AC-Q2 invite expiry default. ## Constraints - **Org context exists before invitee opens the app.** Demimonde's persona, off-limits, surface roster, content guidelines, and admin-curated blocklist are already in `platform.db` with `org_id=demimonde`. The invitee's first session reads these as inherited templates, not as a blank slate. - **Persona-seed is pre-filled with org-template defaults.** Every D-screen question lands with org-derived values in the chips and composer. Invitee taps Continue to accept, edits to refine, or clears to override entirely. - **Org-shared facets vs personal facets are visually distinguished.** Org-inherited values render with a small `org` tag-glyph + a slightly muted background tint (per W4's subtle background-material shift). Anything the invitee writes themselves loses the tag and reads as personal. - **Invite delivery uses Demimonde-routed channels only** — never the admin's personal Proton, personal iMessage, or personal handle. Email comes from `invites@demimonde.cocotte.maison`; iMessage (if enabled) comes from the Demimonde mac-sync queue per `~/Code/@applications/@mac-sync/`. This keeps the admin's identity boundary clean (per W9 privacy invariants). - **Default role is decided at invite time**, not at signup. Admin picks Member or Viewer; invitee cannot upgrade themselves. (See AC-Q1.) - **SSO device-link reuses D1 unchanged.** The auth flow is auth-provider-agnostic; what differs is what loads *after* device-link. - **First-time mixed-scope explainer fires once per invitee**, the first time Quinn-2 sees a context chip with both personal and org options (per W §W2). - **Admin notifications routed through brief C** — the admin gets a working-register receipt when invitee completes onboarding; this is a normal `agent_actions` row, audit-visible. ## States to design 1. AC1a — Roster drawer, admin's "Invite" affordance (idle). 2. AC1b — Role picker sheet (Member / Viewer + role description). 3. AC1c — Invite composer (recipient email, optional iMessage toggle, optional personal note from admin). 4. AC1d — Invite-sent confirmation; pending-invites strip in roster drawer. 5. AC2a — Invitee's email inbox preview (the wild-copy of the invitation message). 6. AC2b — Optional iMessage preview (Demimonde-routed channel). 7. AC2c — Invitee splash (warm hearth-leaning; names admin + org). 8. AC3 — SSO device-link (reuses D1 states; no new design). 9. AC4a — Pre-filled persona-seed Q1 (voice register chip pre-selected from org template, with `org` glyph). 10. AC4b — Pre-filled persona-seed Q2 (off-limits inherited from org; "Add your own" affordance below inherited rows). 11. AC4c — Pre-filled persona-seed Q3–Q6 (surface roster, autonomy posture, quiet hours — all org-derived). 12. AC4d — Override gesture (long-press an org-tagged row → "Make personal" → tag drops, row becomes editable). 13. AC4e — Persona summary review (org-inherited vs personal items rendered in two grouped sections). 14. AC5 — First-time mixed-scope explainer card (one-shot; dismisses on tap-acknowledge). 15. AC6a — Admin's "first member completed onboarding" notification (working register). 16. AC6b — Admin's audit-shadow view of invitee's first vigil (read-only, scoped to org-shared work per W7 admin audit). 17. AC7a — First-week scaffolding offer (admin-side: "Share your curated content / contacts / blocklist with new member?"). 18. AC7b — Invitee-side acceptance of admin's scaffold (each scaffold-type independently toggleable). 19. AC7c — Drift indicator (subtle, in audit drawer) — shows when invitee's persona has drifted from the org template enough to no longer count as "inherited". 20. AC error states — invite expired · invitee already has CocotteAI account under different SSO · admin removed role mid-onboarding · org membership cap hit. ## AC1 — Admin sends invite Reached from `Settings → S1 → Demimonde row → Org roster (W3) → Invite +` button. **Role picker sheet:** ``` Invite to Demimonde Role ● Member Own work + org-shared work. Cannot see other members' personal work. Can act on shared prospects, drafts, surfaces. ○ Viewer Read-only on org-shared work. Useful for contractors, accountants, oversight. (Admin requires admin to set — not selectable here.) ``` **Composer:** - Recipient email (required). - iMessage toggle — "Also send via iMessage (Demimonde channel)" with hint "Sent from invites@demimonde, not your personal number." - Optional admin note — free text, ~280 chars, woven into the wild-copy invitation. - Send button → emits `agent_actions` row `action_type='org_invite_sent'`, scope `org_id=demimonde`. After send, the row lands in a **Pending invites** strip at the top of the roster drawer with status (sent · opened · linked · completed · expired). Admin can revoke from this strip. ## AC2 — Invitee receives invite Email arrives from `invites@demimonde.cocotte.maison`. Optional iMessage arrives from the Demimonde-routed channel via mac-sync's send-queue. Both include the same one-time link. Tapping the link opens CocotteAI on a phone that has the app (App Store deep-link if not). Splash is warmer than D's splash — names the admin and the org explicitly, because the invitee already trusts both. ## AC3 — Invitee SSO device-link Identical to D1. QR / code → trusted-device scan → JWT → Keychain. The only difference is that on link-success, the user record is **created with an existing `org_memberships` row** (role from AC1, status `pending_seed`). No additional invitee action. ## AC4 — Modified persona-seed (the key difference from D) Same screen as `persona-seed-interview.screen.md`, same 8 questions, same chip + composer layout — but every question lands with org-template values **pre-selected** and visually tagged. **Pre-fill behavior per question:** | # | Question | Pre-fill source | Override path | |---|---|---|---| | 1 | Voice register | Org's `personas.voice_register` template | Long-press chip → Make personal → edit | | 2 | Off-limits phrases | Org's `safety_blocklist` entries (org-scoped only) | Add personal rows below the org rows; cannot delete org rows | | 3 | Brands operated | Org-managed surfaces appear pre-checked + tagged; invitee adds personal surfaces alongside | Tap an org-tagged surface → see "managed by Demimonde" detail; cannot uncheck | | 4 | Tours / travel posture | Org's `tours.config` default lead-times | Override per-personal-trip; org defaults remain for org-organized tours | | 5 | Autonomy comfort | Org's per-specialist `policy` rows | Invitee dials their own initial threshold, but it cannot exceed org cap (admin sets ceiling) | | 6 | Quiet hours | None inherited (always personal) | Invitee answers from scratch — this is a personal-only setting | | 7 | Coop membership | Org's coop participation status shown as context (read-only); invitee not auto-enrolled at personal level | Personal-coop opt-in is a separate personal decision | | 8 | Anything else | None inherited | Free-text personal seed only | **Visual distinction:** org-tagged rows render with a 12pt `org` glyph at row-leading + a 4% background tint of `--surface-org-overlay`. Personal rows render at default `--surface-base`. The persona drawer (B5) inherits the same two-tier rendering post-onboarding. **Override gesture:** long-press any org-tagged row → action sheet with "Make personal" (drops tag, row becomes editable) and "Why is this org-managed?" (opens an explainer sheet showing which admin set it + when). Q2 off-limits is a special case — invitee can **add** personal entries but **cannot remove** org-enforced ones (per K's hard-edge guarantee). **Summary review (AC4e):** rather than D's flat summary, AC4e splits into two stacked sections: ``` Inherited from Demimonde · Voice: editorial · slightly literary · Off-limits: 4 phrases · 2 topics · Surfaces: OF, X, Tryst (org-managed) · Tour lead-time: 14 days minimum Personal additions · Off-limits: 1 phrase (you added) · Surfaces: IG (your handle) · Quiet hours: 11pm – 8am ``` Save → writes `personas` row with `inherited_from_org=true` flag, plus standard `agent_actions` row. ## AC5 — First-time mixed-scope explainer First time the invitee sees the context chip on chat-home post-onboarding, a one-shot card slides in: > Two contexts, one app. **Personal** is your work — your journal, your persona, your prospects. **Demimonde** is the org's work — shared content, shared prospects, org-wide audit. Tap the chip up top any time. Cocotte shifts her voice slightly when you're in org mode so you'll hear the switch, not just see it. Dismissable; logged once per user so it doesn't repeat. Per W §W2. ## AC6 — Admin approval / completion confirmation When invitee finishes AC4e save: - Admin receives a push (working register) per brief C: "Quinn-2 finished setting up in Demimonde. Roster updated." - Admin's audit drawer (brief I, scoped to `org_id=demimonde`) gets the `org_invite_completed` row. - Admin can tap the row → lands in roster drawer, pending-invites strip is gone, invitee is now in the active-members list with role + last-active. - Admin can opt to **see invitee's first vigil** (read-only on org-shared work per W9) from a "View first vigil" affordance on the just-completed row. No admin **approval** gate is required to complete onboarding — admin's act of inviting is the approval. (See AC-Q3 for whether admin can preview the persona mid-seed.) ## AC7 — First-week scaffolding After AC6, admin gets a one-time follow-up card: > Demimonde scaffolding — want to share your curated content / contacts / blocklist with Quinn-2's first week? She can copy and drift, or skip. Three independent toggles: - **Content** — admin's recent approved drafts, posting cadence, asset library refs (read-only references; she can copy into her own). - **Contacts** — admin's prospects flagged as org-shareable (per W6 cross-context handoff semantics; admin picks which). - **Blocklist** — admin's personal blocklist offered as a starting set; invitee accepts per-row. On invitee side, each accepted scaffold-type seeds her workspace with **copies**, not references — she can drift freely. Audit row records what was copied and when, so drift is observable (AC7c). ## In-the-wild copy **Invitation email** (working register, slightly warm — first impression of the org, not the brand): > Subject: Quinn invited you to Demimonde > > Demimonde is the back-office where your work gets tended to. Quinn set you up as a Member — own work, org-shared work, room to drift. The phone link below opens CocotteAI on your device and finishes the setup in about five minutes. > > Open CocotteAI → > > One-time link. Expires in 7 days. Sent on behalf of Demimonde, not from Quinn's personal address. **Invitation iMessage** (working, compact): > Demimonde invite from Quinn. Open CocotteAI: [link]. Expires in 7 days. **Invitee splash** (hearth, dialed slightly warmer — strongest first-impression moment): > Welcome. Quinn set the kitchen up for you. Sign in to finish — Demimonde's already in good order, you just need a seat. **Persona-seed Q1 opener** (working — invitee is reviewing, not creating from scratch): > Demimonde already has a house voice — editorial, slightly literary. Keep it for yours, or set your own underneath. **Override prompt** (working — long-press → Make personal): > Make this personal? Demimonde's value stays in the org; yours becomes the override Cocotte uses when she's writing as you. **Persona summary review header** (working): > Two sections — what Demimonde brings, what you brought. Save and start, or rework either side. **Admin completion notification** (working — operational receipt): > Quinn-2 is set up in Demimonde. Persona inherited from the org with 1 personal off-limit and IG as a personal surface. Roster's updated. **Admin first-vigil view header** (working): > Quinn-2's first vigil — org-shared work only. Drafts and replies she ran under personal stay personal. **First-week scaffolding offer** (working): > Demimonde scaffolding — share your curated content, contacts, or blocklist with Quinn-2's first week? She can copy and drift, or skip. ## Out of scope - **Cross-org invite** — a stranger discovering Demimonde on the open marketplace and asking to join, or a member of another org being cross-invited. That's Y territory (`Y-cross-org-marketplace.brief.md` when written). AC assumes the invitee has no prior CocotteAI org affiliation. - **Admin removing a member** — W3 roster drawer territory. AC ends at successful onboarding. - **Role escalation** (Member → Admin) — settings / roster drawer, governed by W3 + an admin-promotion flow not yet briefed. - **Bulk invite** (>1 person at a time) — current brief assumes one-at-a-time, matching W's small-org assumption (Demimonde = Quinn + maybe one staff at P5). Bulk is a later brief. - **Re-invite after expiry** — handled by AC1 again from scratch with the same composer; not a distinct flow. - **Org-side billing impact of new seat** — deferred to platform-admin brief. - **Member-initiated departure** — separate flow; touches V data-portability + W roster + audit-shadow handoff. ## Open questions - **AC-Q1** Default role on the AC1b picker — Member or Viewer? Lean: **Member**, since Viewer is the conservative-but-rare case (contractors, oversight) and Demimonde's near-term invitees are operational staff. Admin overrides if needed. `[blocking]` - **AC-Q2** Invite expiry default — 7 days, 14 days, or 30? Lean: **7 days** for tighter security boundary; admin can re-invite trivially. Auto-expired invites still leave an audit row. `[blocking]` - **AC-Q3** Admin visibility into invitee's persona — sees during AC4 mid-seed (real-time, can suggest edits) or only post-completion (privacy-respecting, invitee owns her seed)? Lean: **only post-completion** — protects invitee's autonomy even though she's joining the org. Admin can suggest edits in chat later if needed. `[blocking]` - **AC-Q4** Should AC7 scaffolding offer fire automatically or be on-demand from admin? Lean: **automatic one-shot card 24h post-completion**, dismissible — captures the moment when admin is most willing to share without nagging. `[nice-to-have]` - **AC-Q5** When invitee long-presses an org-tagged off-limits row (Q2), should "Make personal" be allowed? Lean: **no** — org-enforced off-limits are a hard floor per K; invitee can *add* personal restrictions but cannot loosen org rules. UI should explain rather than offer the gesture. `[exploratory]` ## Related - [D — Onboarding](./D-onboarding.brief.md) — the cold first-run; AC inherits D1 SSO device-link verbatim and modifies D2 persona-seed. - [W — Org overlay](./W-org-overlay.brief.md) — W3 roster drawer is AC's entry point; W2 mixed-scope explainer fires in AC5; W5 voice shift is what AC5 hints at; W6 cross-context handoff is how AC7 contact-scaffolding is structured. - [S — Settings IA](./S-settings-ia.brief.md) §S1 — org switcher / roster entry point. - [`persona-seed-interview.screen.md`](./persona-seed-interview.screen.md) — the screen this brief modifies into "pre-filled mode." - [C — Notifications](./C-notifications.brief.md) — admin's completion push routes through C. - [I — Audit-trust-replay](./I-audit-trust-replay.brief.md) — every AC step emits `agent_actions` rows; admin's first-vigil view is a scoped audit drawer. - [K — Safety / blocklist](./K-safety-blocklist.brief.md) — Q2 inheritance + org-floor invariant. - **Y — Cross-org marketplace** (future brief) — contrasted: Y is the stranger path, AC is the admin-invited path. Same screen output (a working CocotteAI seat) via fundamentally different trust assumptions.