Shared Auth for Applied AI Labs went from exploration to validated reference in one evening — chroma-decks is the first end-to-end install
Earlier this month an exploration in this tree argued that every AI product under ai-labs needs its own auth story but none of them is at the scale that justifies Auth0/Clerk pricing. The doc proposed ~800 lines of owned auth, a libSQL-backed session model, OAuth via the small `arctic` library, an opaque cross-app `lossless_id`, and a stub seam for future rollup. It estimated three sessions of work plus a package extraction. Tonight the first real install landed — in chroma-decks, greenfield, with the four 'Session-2 additions' from the spec baked in from day one. The pattern is validated against a real-world app, the cross-app organization-naming convention is locked into the exploration as binding policy for every AI product in this tree, and the next AI product that needs auth (memopop-ai, augment-it) installs from a 6-phase template that took ~3 hours to produce on a greenfield codebase.
Why Care?
ai-labs is the home for AI experiments graduating into real products. memopop-ai (multi-agent investment-memo orchestration), dididecks-ai (slide-deck operating system for fundraise materials), augment-it (just arriving), and a small army of supporting packages, studies, and scripts — each of these eventually needs to know who's logged in. The instinct of every reasonable team in 2026 is to pick an auth-as-a-service vendor and move on; Clerk, Auth0, WorkOS, Stytch all want to sell us a turnkey product.
We can't afford their pricing tiers, and more importantly we'd rather understand the ~800 lines of code that gate access to a fundraise deck than depend on 80,000 lines we can't read on a flight. The Shared-Auth-for-Applied-AI-Labs exploration earlier this month laid out the cost / control tradeoff and proposed a shape: per-app libSQL databases, shared TypeScript primitives, OAuth-via-arctic for the small set of providers we need (GitHub first, Google Workspace second), an opaque UUIDv7 lossless_id that joins a person across every Lossless app on email match, and an auth_events_outbox audit table in every app that a future ingester rolls up into one cross-app view.
The exploration proposed three sessions of work to get there. Tonight's session collapsed most of that into a single evening by taking a sharp detour: instead of grinding the four "Session 2 additions" into calmstorm-decks (which would have validated the pattern against existing code), we installed the entire surface greenfield into chroma-decks (which had no auth code at all), with the four additions baked into the initial schema. Three hours of execution. The exploration goes from speculative doc to validated reference.
The organization-naming convention also locked tonight, and this matters at the ai-labs tier specifically because it's a cross-app decision: every AI product in this tree will use the same Organization.id = canonical email domain shape so that a future rollup ingester can join trychroma.com (or any other client domain) across memopop-ai + dididecks-ai + augment-it + whatever lands next. The decision is in the exploration now, binding for every app that installs the pattern.
What's New?
At the ai-labs / shared-auth / cross-app tier:
Shared-Auth-for-Applied-AI-Labs.md gained a new subsection — "Organization naming convention — domain-as-id". Locks the rule:
Organization.idis the org's canonical email domain (lossless.group,trychroma.com,calmstormvc.com);Organization.slugis the human handle. Every Lossless AI app seeds two orgs on first boot:lossless.group(the operating-team org) plus{client-domain}. Personal-email signups bucket asid = "personal". Multi-domain firms get analiasescolumn when first encountered (not v1). Subdomains strip to apex.The exploration's three-session plan now has an empirical reference. The first install happened in chroma-decks rather than calmstorm-decks (greenfield was cleaner than migration). The exploration's structure stands — Session 1 inventory of calmstorm is still relevant; the spec for the eventual
lossless-auth-corepackage extraction is still the next document to write — but the working code is now a thing we can point to instead of a thing we're imagining.calmstorm-decks gained
app_slugparity in a small standalone commit, so the two consumer decks now stamp the same cross-app rollup dimension on everyAuthEventrow. The future rollup ingester will pull from both decks and group byapp_slugto answer "which app generated this event."The exploration's open-ideas list got one item promoted out and one new follow-up added. Promoted out (now locked policy): "stub the seam now, build the ingester later" → realized as the
lossless_idUUIDv7 +app_slugcolumns in both decks. New follow-up named: "auto-attachsuperuserMembership when an OAuth callback yields a@lossless.groupemail" — small change in any app's OAuth callback; saves manual admin work for the operating team across every Lossless AI product.
The bet, validated
The exploration's bet was that ~800 LOC of owned auth code would be enough to ship across the three apps (memopop, dididecks, augment-it) without ever needing to pay for an auth vendor. Tonight's chroma install is ~1,800 LOC including the UI + OAuth callback + chroma-themed /access page — somewhat over the 800-line budget the exploration named, but well under the implied threshold where "we should have used Clerk" becomes a real concern. The breakdown:
chroma-decks/db/config.ts 231 LOC (10 tables)
chroma-decks/src/middleware.ts 162 LOC
chroma-decks/src/lib/auth/*.ts ~400 LOC (5 files)
chroma-decks/src/pages/access/* ~500 LOC (3 files, includes UI)
chroma-decks/src/pages/api/access/* ~270 LOC (3 endpoints)
chroma-decks/src/pages/access/oauth/github/* ~280 LOC (start + callback)The ~800-LOC figure from the exploration was about the library-extractable core — the part that would eventually live in lossless-auth-core. The UI surface and the consumer-side route wiring legitimately add LOC on top of the core. The next consumer (memopop's API surface, or augment-it whenever it lands) reuses the core and only re-implements its own UI; that's where the LOC budget tightens.
What this enables
memopop-ai installs the same pattern when it stops being a Tauri-only app. The Python sidecar already reads the same Session table the TypeScript side writes (the exploration's Section-2 design). When memopop's orchestrator graduates to a web-served API surface, the chroma plan template is what it follows.
augment-it doesn't have to figure out auth from scratch. The 6-phase plan in chroma-decks (
context-v/plans/Install-Auth-Surface-from-Calmstorm-Pattern.md) is the template. Augment-it's first commit can reference it.Cross-app rollup is finally a real future and not a hand-wave. Every event in calmstorm + chroma now carries an
app_slug; every Identity carries alossless_id; every Organization is keyed by canonical email domain. The ingester is still unbuilt, but the schema seam is real on disk.The eventual
lossless-auth-corepackage extraction has two empirical consumers. Calmstorm has the original implementation; chroma has the greenfield install with the four additions baked in. The extraction trigger is most likely: a third consumer arrives (memopop, augment-it) and the cookie-name / role-enum drift between the two existing implementations starts being painful at the install-template tier.
What's still loose at this tier
memopop-ai hasn't yet adopted any of this. Its Tauri shell uses the OS keychain for refresh tokens and its Python sidecar validates sessions via the shared table — that part of the exploration's design is in good shape — but the formal pattern doesn't install there yet because the surface (Tauri + Python sidecar) is different from the web-Astro pattern chroma exercises. When memopop's orchestrator becomes a web-served API, that's the trigger.
lossless-auth-corepackage not yet extracted. Per the exploration's three-session plan, extraction is Session 3. With two empirical consumers now (calmstorm + chroma), the extraction is closer; it's gated on a third-consumer arrival or visible drift between the two existing implementations.The Python companion package (
lossless-auth-py) named in the exploration doesn't exist yet. It will when memopop's Python sidecar consumes the shared session table from a non-Tauri runtime context.The
@lossless.groupsuperuser fast-path is in the open-ideas list; will land when a Lossless teammate other than Mike first authenticates against any app.
Related — going deeper
The deck-operating-system tier (dididecks-ai): 2026-05-17_06.md — what this means for the two client decks and the shell that hosts them; the two prerender-bypass shell patches that benefit every future deck consumer.
The specific install (chroma-decks): chroma-decks 2026-05-17_01.md — phase-by-phase account, commit chain, the messy middle.
The exploration itself: Shared-Auth-for-Applied-AI-Labs.md.
The Session-1 audit that named the four additions: Calmstorm-Auth-Inventory.md.
