Felt Faction iOS app v7 — auth + gating + vision-test context

Writing Search related

Brainstormed 2026-06-16. User picked option A (scope the v1 plan as

a tasks list), shared vision-test calibration context, and added a

new v1 feature: auth + gating (invite-only, personal access

token, then Sign in with Apple / Google).

Decisions (locked in by user, this round)

  1. Scope the v1 plan as a tasks list now (option A). The 1-week

vision spike as task 0 was the alternative; the user picked the full-scope path. With the vision-test context below, the spike is deferred / not required.

  1. Vision will work — "I've done some testing before." Calibration

signal: the spike I proposed (50 photos + Claude Sonnet Vision + accuracy/latency data) is nice to have, not required. Trust prior testing. Ship to v1 with server-side vision. Iterate during the build, not before.

  1. Auth + gating is a v1 feature (NEW). The iOS app must support

sign-up and login. Gated by a personal access token issued by admins. Once the token is accepted, the user can sign in with Apple or Google. The token is the invitation; OAuth is the identity.

The auth + gating design

User said:

"we need a sign up and login proceedure too. it also needs to be

gated so anyone just can't go in and create an account. some

personalised access token or something, once they put that in it

allows the user to sign in with apple or google etc."

The flow

  1. Admin generates an invite. Connor or Nathan opens the admin

panel (web or iOS), creates a personal access token for an invitee. The token is bound to a name / email / role (VIP, High Roller, Walk-in).

  1. Invitee receives the token via Telegram, iMessage, in-person,

or whatever. The token is a long, single-use string (e.g., felt_8a2f9c4b7e1d).

  1. Invitee opens the iOS app. First screen: "Welcome to Felt

Faction. Enter your invitation."

  1. Invitee enters the token. App validates against Supabase.

The token is is_used = false, not expired, and bound to the invitee.

  1. App shows Sign in with Apple / Google buttons. Two options

for the OAuth identity layer.

  1. Invitee picks an OAuth provider. Standard Apple/Google flow.
  2. OAuth completes. Supabase creates or links the member

account.

  1. Token is marked is_used = true and claimed_by_id is set

to the new user's ID. The member is in.

  1. First-time onboarding. Welcome screen, season context,

Briefing explainer, claim seat for the next session.

The data model

The web app's members table already has an invite_key column. The iOS app uses the same pattern, with these refinements:

-- New invites table (or extend existing)
CREATE TABLE invites (
  id UUID PRIMARY KEY,
  key TEXT UNIQUE NOT NULL,           -- felt_xxxxxxxxxxxx
  member_name_placeholder TEXT,       -- "Olivia"
  tier TEXT,                           -- 'vip', 'high_roller', 'walk_in'
  is_used BOOLEAN DEFAULT FALSE,
  claimed_by_id UUID REFERENCES members(id),
  expires_at TIMESTAMP,                -- 7 days default
  created_by_id UUID REFERENCES members(id),  -- the admin
  created_at TIMESTAMP DEFAULT NOW()
);

-- RLS: only unused, unexpired invites are readable by the app
ALTER TABLE invites ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Public can validate unused invites" ON invites
  FOR SELECT USING (is_used = FALSE AND (expires_at IS NULL OR expires_at > NOW()));

Sign in with Apple vs Google

Both supported, in priority order:

App Store requirement for apps that offer third-party SSO

The web app currently uses Google OAuth. The iOS app extends to both, with Apple as the default.

Why this works

possible. The OAuth flow can't even start.

No one can re-use it.

expire if not used.

generated it. The invite trail is in the database.

identity; the token is the authorization. They serve different purposes.

Edge cases

manually voided.

like a password. Time-limit mitigates the risk.

new "re-bind" token. Member enters it, re-authenticates with the new provider.

re-authenticates.

The vision-test calibration

User said: "I think the vision will work fine—I've done some testing before."

This is a calibration signal I should record. The 1-week vision spike I proposed (50 photos + Claude Sonnet Vision + accuracy/latency data) is nice to have, not required. Trust prior testing. Ship to v1 with server-side vision, iterate during the build.

This is a meaningful scope reduction. The spike was task 0 in my earlier cuts; now it's deferred to "do it if/when we have time, not as a blocker." v1 ships with vision integrated.

v1 cut (v7 update)

Adding auth as a v1 feature:

  1. Glance (Widget + Live Activity, phone-only)
  2. Claim Your Seat from Lock Screen
  3. Quick Settle (Face ID, Taptic, big numbers)
  4. Native push for Briefing
  5. Buy-in flow (+ rebuy accumulator, draws from net worth)
  6. Cashout with chip photo (per-member)
  7. Self-attest / audit (admin override)
  8. Push notification lifecycle
  9. Felty's voice (system personality)
  10. The Bank (loans at zero, steep interest, auto-debit)
  11. Live settlement board (Felty-narrated, debt column with

"X left until Y breaks even")

  1. Chip set registration via settings (saved presets)
  2. Admin settings page (season length, starting chip allocation,

economy params)

  1. Auth + gating (NEW) — invite token, Sign in with Apple +

Google, RLS policies, audit trail

v1 = 14 features. ~10-12 weeks still holds.

What v1 looks like end-to-end (with auth)

  1. Admin generates invite: Connor opens admin panel, creates

token for new member. Member receives via Telegram.

  1. Member opens iOS app: Welcome screen, "Enter your

invitation."

  1. Member enters token: App validates, shows Sign in with

Apple / Google.

  1. Member signs in: OAuth flow completes. Member is in.
  2. Member sees The Briefing: Pre-session intel drops 48h

before the next session. Member claims a seat.

  1. Session night: Push notifications drive the lifecycle.

Members play. Felty narrates the Bank, the rake, the Phoenix.

  1. Settle: Live settlement board resolves. Self-attest.

Photos auto-delete. Vault recap.

  1. Season end: Awards surface. New season starts.

See also

v6 (customizable seasons, watch app deferred). Superseded by v7 for the auth + gating addition and the vision-test context; v6's technical primitives (admin settings page, deferred watch app, customizable season length) are still valid.

Published and managed by TARS, an AI co-author built on Nathan's gbrain.