feat(auth): env-side AI-seat marker via sys_user.ai_access + resolveCtx synthesis#2327
Merged
Conversation
…imple AI-seat model) The env DB (Turso) is single-org and has only sys_user — so the AI seat is best modeled as a boolean on the user, not a permission set. Add `ai_access` as a better-auth additionalField (rides on the session user) and have resolveCtx synthesize the `ai_seat` capability when it is true. The existing per-agent gate (evaluateAgentAccess → requires ai_seat), catalog filter, and frontend are unchanged — they now admit a user via the field with NO permission-set grant. ADDITIVE: the permission-set path still works (a user can get ai_seat from either source), so there is no regression while the rest of the simplification (have the entitlement layer SET the field + retire the permission-set seed/junction/cap- middleware + repoint the management UI) lands. Built clean (plugin-auth + hono). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…not a better-auth additionalField)
sys_user is a better-auth-MANAGED table and better-auth SELECTs explicit columns.
Declaring ai_access as a better-auth additionalField (my first cut) would make
getSession query a column that may not exist on every env yet → broken auth on
deploy. Safe-by-construction instead:
• drop the additionalField (better-auth stays oblivious to the column);
• own ai_access on the objectql SysUser object def → provisioned by boot
schema-sync, and editable as a normal field (the management UI is a checkbox);
• resolveCtx reads it via a GUARDED system query (.catch → []), so a missing
column / failed read can only NO-OP — never break auth.
Built clean (platform-objects + plugin-auth + plugin-hono-server). Amends the
prior additionalField approach on this branch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 1 of the simplified per-user AI-seat gate (pairs with cloud
feat/ai-seat-simple-model; both must land together + cloud bumps.framework-sha).What: the env DB (Turso) is single-org with only
sys_user, so the AI seat is a boolean on the user — not a permission set.resolveCtxsynthesizes theai_seatcapability fromsys_user.ai_access, so the existing per-agent gate (evaluateAgentAccess→ requiresai_seat), catalog filter, and frontend are UNCHANGED — only the seat's source moves to a user field.Safe-by-construction (the important bit):
ai_accessis NOT a better-auth additionalField.sys_useris better-auth-managed and better-auth SELECTs explicit columns, so an additionalField would makegetSessionquery a column that may not exist on every env yet → broken auth on deploy. Instead:SysUserobject def (provisioned by boot schema-sync; also makes it an editable field — the management UI is just a checkbox);resolveCtxreads it via a GUARDED system query (.catch → []), so a missing column / failed read can only NO-OP — never break auth;Dormant by default: nothing sets
ai_accessuntil the cloudOS_CLOUD_AI_SEAT_MODE(defaultoff) flips to provision/enforce, or a licensed objectos-ee mounts the AiSeatPlugin.Built clean (platform-objects + plugin-auth + plugin-hono-server). Cap logic unit-verified in the cloud half (24 tests). Browser-level E2E deferred (env blocker) — merging per explicit owner decision given the safe-by-construction design.
🤖 Generated with Claude Code