Scope: repository state or decisions that admit, deny, hide, narrow, revoke, or expose a user operation or row. Transport-only integrity checks are included when token/session possession is the gate; ordinary workflow booleans such as isRead, job leases, and UI expansion state are excluded. “Authoritative” means the server or PostgreSQL path enforces the decision. “Advisory” means client projection, navigation, or tool exposure is rechecked elsewhere. This is an inventory of the current model, not a proposed replacement.
| name | layer (platform/server/membership/grant/channel/audience) | type | who writes | who reads | what it actually gates | file:line |
|---|---|---|---|---|---|---|
users.account_status |
platform | persisted enum: active, disabled, banned |
Account lifecycle/support execution; GDPR execution sets disabled; fixtures and migrations seed it |
Channel/server calculators, auth/read models, notifications, media, search, moderation | Non-active accounts lose effective membership/channel authority and are omitted from recipient/read projections | database/Schema.ts:378-399; database/SettingsAuthority.ts:18-61; core/permissions/calculateChannelPermissions.ts:217-228; core/permissions/calculateServerPermissions.ts:49-60 |
users.is_staff |
platform | persisted boolean, default false |
No production writer found; creation uses the default; tests/fixtures set it directly | Permission calculators, moderation, profile visibility, media/conference/Cell and agent paths | Platform-wide privileged role: bypasses channel audiences and moderation grants and qualifies for server management, but not account, membership, timeout, ancestry, or lifecycle hard clamps | database/Schema.ts:378-399; core/permissions/calculateChannelPermissions.ts:239-263; core/permissions/calculateServerPermissions.ts:55-73; database/ProfileAuthority.ts:158-197 |
Better Auth emailVerified |
platform | persisted boolean | Better Auth verification flows; GDPR deletion resets it false | No Boja production authority reader found | Currently gates no Boja operation beyond Better Auth’s own authentication lifecycle | database/Schema.ts:275-291; database/SettingsAuthority.ts:45-55 |
Profile is_profile_private, is_deleted |
platform | persisted booleans | Archive finalization/GDPR writes deletion state; no production privacy-toggle writer found | ProfileAuthority, Zero profile predicates, search/presence name visibility |
Self bypasses privacy but not lifecycle; others require active/nondeleted profile and a shared live server. Staff/shared admin may bypass privacy, never lifecycle or blocks | database/Schema.ts:419-468; database/SettingsAuthority.ts:18-61,73-116; core/profilePolicy.ts:1-31; database/ProfileAuthority.ts:111-198 |
Account archive pending_delete_at / recovery_until |
platform | persisted timestamp plus append-only archive_requested, archive_canceled, archive_finalized lifecycle |
Fresh-session archive/cancel routes; one-minute expiry worker and GDPR finalize | Session identity, profile/DM eligibility and finalizer | Setting pending_delete_at immediately hides the profile, denies new DM/profile interaction, revokes sessions and makes ordinary session identity unavailable. Cancellation is allowed only during the 30-day recovery window; expiry finalizes deletion |
core/accountLifecycle.ts:1-19; database/Schema.ts:488-506; server/src/Auth.ts:418-458,642-778; database/SettingsAuthority.ts:73-116; worker/src/accountArchiveWorker.ts:9-33; database/ChannelAuthorization.ts:673-694 |
Custom status cleared_at, expires_at |
audience | persisted nullable timestamps plus derived visibility | Authenticated versioned profile status writer; five-minute expiry worker clears expired rows | Profile/status projections call visibleStatus |
Hides a cleared status or one whose expiry is at or before the reader’s clock; it does not affect profile or channel authority | database/Schema.ts:518-543; database/ProfileAuthority.ts:266-313,330-440; core/profilePolicy.ts:34-47; worker/src/statusExpiryWorker.ts:7-31 |
user_profiles.is_bot |
platform | persisted boolean, default false |
Profile/account provisioning; no ordinary user writer found | Platform support admission | Excludes bot identities from platform-operator support access even if another grant/session row exists; no channel permission effect | database/Schema.ts:419-468; server/src/supportAccess.ts:518-550 |
user_blocks |
platform | directional pair; mutual visibility denial is derived | Authenticated Zero profile block/unblock mutators | Profile authority, Zero profile predicates, presence/search projections | Either direction hides the other profile and retracts presence; self-block is schema-forbidden | database/Schema.ts:401-416; server/src/profile.ts:81-111; database/ProfileAuthority.ts:141-197; core/zeroQueryVisibility.ts:144-170 |
| Better Auth / Zero session validity | platform | signed bearer claims plus matching unexpired session | Better Auth creates/revokes sessions; Zero token minting signs sub/sid |
Zero query and mutation wrappers | A valid bearer and live matching session are prerequisites for every Zero query/mutation; mutation additionally requires a server transaction | server/src/Zero.ts:362-415,916-941,963-980 |
| Browser origin gate | platform | configured trusted-origin set; local HTTP loopback expansion only in development/test | Deployment configuration and request origin | CORS and Better Auth handler | Credentialed browser requests are exposed only to the configured web origin; state-changing Better Auth requests carrying an untrusted Origin receive 403. Preview/production never derive trust from the request | server/src/appMiddleware.ts:5-17; server/src/Auth.ts:214-224,288-305; server/src/authFrontendOrigin.ts:14-69 |
| Fresh-session proof | platform | session age threshold | Better Auth session creation time | Account archive/cancel and other reauthentication-sensitive auth operations | Rejects a privileged account-lifecycle operation when the session is older than ten minutes | server/src/Auth.ts:622-648,743-766 |
platform_operator_grants: role/status/expiry/revocation |
platform | persisted support_agent or ops_admin, lifecycle fields |
Manually provisioned platform-internal process; never tenant-owned | supportAccess.admit, support authority calculator |
Admits platform support only for an active, nonexpired, nonrevoked grant attached to an active human account | database/Schema.ts:3482-3522; server/src/supportAccess.ts:486-568 |
| Better Auth MFA enrollment/verification | platform | twoFactorEnabled, verified factor row and operator mfa_enrolled_at |
Better Auth second-factor setup/verification; verification hook stamps operator enrollment | Operator-session provisioning and support admission | All three must be present before a platform operator counts as MFA-verified; ordinary tenant permissions do not consume them | database/Schema.ts:275-291,354-369,3482-3522; server/src/Auth.ts:328-381; server/src/supportAccess.ts:486-508 |
platform_operator_sessions: MFA/step-up/expiry/revocation |
platform | session-bound timestamps and revocation | Better Auth second-factor verification hook provisions/refreshes proof | supportAccess.admit, support.calculateAuthority |
Requires verified MFA and an active operator session; sensitive operations additionally require a fresh 15-minute step-up | database/Schema.ts:3525-3551; server/src/Auth.ts:341-407; server/src/supportAccess.ts:486-568; core/support.ts:53-61,218-273 |
| Support operation requirements | platform | derived booleans stepUp, opsAdmin per operation |
Static policy function | Every support action admission | Discovery needs only an operator role; refund/comp/session revocation need step-up; reveal/approve/reject/GDPR execution also need ops_admin |
core/support.ts:194-259; server/src/supportAccess.ts:565-587 |
Support approval_required and no-self-approval |
platform | persisted boolean plus action-state machine | actionNeedsApproval on refund currency/amount and comp days; request/decision writers transition state |
Support action execution/approval paths | Large/non-USD refunds and more than 14 comp days require a second operator; requester cannot approve own action; expired approval cannot execute | core/support.ts:19-21,275-293; server/src/createSupportActionOperations.ts:192-256,391-456,609-685; database/Schema.ts:3676-3755 |
Support GDPR legal_hold |
platform | persisted boolean coupled to held status |
No production writer found; tests/external provisioning can set it | Approved GDPR execution | A held privacy request cannot execute deletion and transitions to held; the schema requires held state while true and executed state only while false | database/Schema.ts:3818-3852; server/src/applySupportDatabaseAction.ts:32-110 |
Support email-delivery legal_hold |
platform | persisted boolean, default false |
No production writer found | Hourly retention sweep and support evidence read | Preserves an expired support login-code/claim-link delivery row past retain_until; it does not authorize delivery or target access |
database/Schema.ts:3855-3895; database/db/20260818000000_boj_178_unified_channels/migration.sql:3355-3363; database/SupportRetention.ts:8-21; worker/src/supportRetentionWorker.ts:9-33 |
Audit-event legal_hold |
platform | persisted boolean, default false |
No production writer found | No production retention reader found | Currently gates nothing; retain_until has a two-year minimum but no audit purge path consumes this hold |
database/Schema.ts:3399-3479 |
support_comp_grants |
grant | append-only days and resulting subscription period | Approved support comp execution | Support evidence/relations; subscription period is the operational effect | Records a granted 1–365-day extension after support role, step-up, approval, and no-self-approval gates; the row is evidence, not reusable actor authority | database/Schema.ts:3793-3815; server/src/applySupportDatabaseAction.ts:171-202 |
servers.platform_tier |
platform | persisted enum: validate, creator, scale, operator |
Owner-authorized tier management; schema default is validate |
Billing projections and tier gates | Selects pricing/usage bands and feature capability values; owner command currently accepts only validate/creator | database/Schema.ts:586-605; database/OwnerBillingManagement.ts:159-199; server/src/OwnerBillingManagement.ts:68-80; core/billing.ts:257-303 |
Platform plan billing_state |
platform | append-only active or winding_down event |
Active owner billing path cancels/resumes plan | Owner billing tier changes, billing read model/UI | Winding down blocks tier changes and projects closure/payout-hold state; it is separate from server lifecycle | database/Schema.ts:869-902; database/OwnerBillingManagement.ts:114-243; server/src/BillingReadModels.ts:448-495 |
kyc_states.status |
grant | persisted none, pending, verified, rejected |
No production writer found | No production reader found | Currently gates neither commerce nor payout; payout management never joins KYC | database/Schema.ts:905-927; database/OwnerBillingManagement.ts:244-378 |
tierCapabilities.canCoupons |
platform | static boolean by tier | Core billing table | Coupon creation service | Authoritatively rejects coupon creation below Creator; coupon deactivation is not tier-gated | core/billing.ts:257-303; server/src/ConsoleAffiliates.ts:130-155 |
broadcastMonthlyLimit |
platform | static numeric limit by tier | Core billing table | Authoritative announcement recorder and console projection | Rejects a console announcement after the tier’s UTC-month quota is reached; records usage before transport, which is currently unconfigured | core/billing.ts:257-303; database/EmailManagement.ts:293-363 |
tierCapabilities.canNativeLive |
platform | static boolean; web advisory, server duplicates tier list | Core billing table; server reads platformTier directly |
Channel header and conference go-live command | UI disables native-live controls on Validate; server independently admits only creator/scale/operator rather than consuming this boolean | core/billing.ts:257-303; webapp/src/components/chat/ChannelHeader.tsx:89-99,303-325; database/Conference.ts:1222-1235 |
canCustomDomain, canAutomation, canAdvancedAnalytics |
platform | static booleans by tier | Core billing table | No production consumers found | Currently gate nothing | core/billing.ts:257-303 |
videoStoredMinutes, mauAllowance, aiActions |
platform | static numeric tier limits | Core billing table | Console usage projection | Display usage bands/meters; no operation-level rejection was found | core/billing.ts:257-303; core/consoleUsage.ts:1-40; server/src/ConsoleCommerce.ts:53-130 |
validatedGmvCapMinor / tierCheckoutOutcome |
platform | monetary limit and derived outcome | Core billing policy over GMV/refund facts | Checkout/console projections | Intended to pause new Validate memberships at the cap; no production checkout mutation enforcement was found | core/billing.ts:188-189,327-343; database/ProductManagement.ts:411-423; server/src/ConsoleReadModels.ts:540-544 |
| Capability manifest | platform | static bounded names: server.manage, channel.view, channel.manage, message.send, message.moderate, thread.create, course.view, course.manage, stream.join, stream.start, server.billing.manage |
Source declaration only | Permission route, SDK/agent runtime, mobile display | Defines the maximum capability vocabulary; declaration alone grants nothing and is separate from channel/server calculators | core/permissions/capabilityManifest.ts:3-25; server/src/permissionRoutes.ts:5-8; server/src/AgentConversations.ts:504-546 |
SDK method capability metadata |
platform | Capability or undefined per read/mutation |
SDK manifest and mutation contract maps | Agent allowed-method/tool runtime | Exposes a method only when its method, lens, and capability are present; final DB mutation authority is rechecked separately | sdk/manifest.ts:24-38,78-154,191-271; sdk/mutationContracts.ts:154-169; server/src/manifestToTools.ts:23-75,79-124 |
SDK entity lenses / conversation entity_lens |
audience | owner or member; persisted conversation lens |
Manifest declares accepted lenses; DB derives and stores current lens at conversation creation/load | Agent conversation listing, runtime methods, approval intent checks | Only the conversation owner with active membership may use it; stale owner/member lens is rejected and channel conversations also require current View | sdk/manifest.ts:112-154,191-271; database/Schema.ts:4642-4663; database/AgentConversations.ts:1341-1348,1610-1691,1923-2037 |
| Diagnostic MCP tool allowlist | platform | static 11-name read-only registry with authority labels | Monitor source declaration | Repository MCP tool listing/execution | Exposes only enumerated production diagnostic operations; the current MCP implementation executes only axiom_query and rejects names outside its registry. External bearer/service-account credentials remain the actual provider authority |
monitor/src/mcpPolicy.ts:3-37; scripts/boja-mcp.ts:1-95; monitor/src/axiomQuery.ts:47-61; monitor/src/productionMonitor.ts:170-203 |
| Deployment operator allowlists | platform | configured email allowlists and read-only Kubernetes RBAC/token | Deployment configuration and operator script | Cloudflare Access and Kubernetes API | Admits named operators to preview or K3s dashboard surfaces for 24h or 12h sessions; Headlamp gets get/list/watch and the helper mints a 15-minute viewer token. This is infrastructure access, not tenant authority | deployment/src/resources/k3sDashboardEdge.ts:19-60,82-128; deployment/src/resources/k3sVisibility.ts:45-145; scripts/k3s-dashboard:6-9 |
servers.owner_user_id / derived membership isOwner |
server | nullable FK; calculator boolean derived by equality | Account/server provisioning and community creation; no transfer writer found | Permission calculators, moderation/hierarchy, billing and agent paths | Grants privileged channel authority and server manage; owner/staff, not admin alone, may manage lifecycle |
database/Schema.ts:560-606; database/provisionAccount.ts:88-115; database/ChannelAuthorization.ts:166-205,299-320; core/permissions/calculateServerPermissions.ts:57-73 |
servers.lifecycle_state |
server | persisted enum: active, winding_down, read_only, archived |
Server lifecycle service; channel lifecycle service writes channel state separately | Channel/server calculators, agent/read paths | Winding down removes destructive management; read-only/archived remove ordinary management and writes while preserving owner/staff lifecycle authority | database/Schema.ts:586-605; database/ServerLifecycle.ts:140-199; core/permissions/calculateChannelPermissions.ts:300-321; core/permissions/calculateServerPermissions.ts:61-73 |
servers.is_deleted, servers.is_suspended |
server | persisted booleans | Platform/server lifecycle processes; ordinary tenant management does not write them | Authorization projections, Zero visibility, onboarding/profile/search | Makes the server unavailable before calculator input or row visibility; no role bypasses it | database/Schema.ts:579-584; database/ChannelAuthorization.ts:164-205; core/zeroQueryVisibility.ts:13-23; database/ProfileAuthority.ts:119-140 |
servers.is_public |
server | persisted boolean, default false |
ServerManagement.updateSettings under server manage |
Console projection/UI | Authoring flag says whether anyone can find the community in Discover; no production discovery reader was found | database/Schema.ts:560-571; database/ServerManagement.ts:84-123; webapp/src/features/console/ConsoleDialog.tsx:924-925,1110-1114 |
channels.is_private |
channel | persisted boolean, default false |
No production writer found | No production reader found outside schema/fixtures | Currently gates nothing; community access is audience-based and participant-channel privacy is participant-row based | database/Schema.ts:1060-1087; core/zero-schema/zeroSchemaServers.ts:39-52 |
servers.affiliate_earnings_as_plan_credit |
server | persisted boolean, default false |
Owner-authorized affiliate management command | Affiliate read model | Selects whether Boja affiliate earnings are presented/settled as plan credit; no channel, membership, or referral-admission authority effect | database/Schema.ts:560-579; database/AffiliateManagement.ts:526-540,788-839 |
servers.rated |
server | persisted boolean, default false |
ServerManagement.updateSettings under server manage |
Invite and checkout projections/UI | Mature-content metadata is carried to invite/checkout surfaces; no repository admission/filter enforcement consumer was found | database/Schema.ts:560-571; database/ServerManagement.ts:84-123; database/CommunityOnboarding.ts:790-831; database/ProductManagement.ts:398-423 |
servers.feature_flags |
server | JSON object, default {} |
No production writer found | No production reader found | Currently gates nothing; architecture explicitly treats feature flags separately from permission/entitlement | database/Schema.ts:582-592; docs/architecture/03-permissions.md:81-86 |
servers.authorization_epoch |
server | persisted integer snapshot | Authorization-changing server paths increment it | Agent approval decision/execution rechecks | Invalidates staged agent approval when server authorization changes | database/Schema.ts:590-593; database/AgentConversations.ts:1106-1115,1269-1275,1411-1466 |
Server manage |
server | derived PermissionDecision |
calculateServerPermissions |
Route authorization, server settings, channel creation, billing/read models | Requires active account/membership, staff/owner/admin, and no active timeout; read-only/archived deny it | core/permissions/calculateServerPermissions.ts:48-73; server/src/RouteAuthorization.ts:96-105; database/ServerManagement.ts:84-97; database/ChannelManagement.ts:777-791 |
Server manageDestructive |
server | derived PermissionDecision |
calculateServerPermissions |
Channel archive/delete transitions and web prediction | Same role prerequisite as manage, but denied in winding-down as well as read-only/archived |
core/permissions/calculateServerPermissions.ts:59-73; database/ChannelManagement.ts:540-568; webapp/src/features/permissions/useServerManagement.ts:39-74 |
Server manageLifecycle |
server | derived PermissionDecision |
calculateServerPermissions |
Server lifecycle service and UI projection | Only active, untimed-out owner or staff may change lifecycle; admin alone is denied; survives read-only/archived | core/permissions/calculateServerPermissions.ts:61-73; database/ServerLifecycle.ts:140-147 |
server_memberships.status |
membership | persisted enum: active, suspended, banned, left; core maps non-active to suspended |
Onboarding/invite and member management; ban/unban/cancel change it | Nearly all server/channel authorities and recipient projections | Active is prerequisite for server/channel authority; non-active states deny and are omitted from recipient/admission projections | database/Schema.ts:1012-1039; database/MemberManagement.ts:395-444,788-818; database/CommunityOnboarding.ts:922-1000; core/permissions/calculateChannelPermissions.ts:225-228 |
server_memberships.is_admin |
membership | persisted boolean, default false |
Account/bootstrap provisioning inserts it; no production promotion/demotion writer found | Calculators, moderation, hierarchy, conference/Cell | Server-local privileged role: bypasses audiences/mod grants and gets manage, but not manageLifecycle; timeout/status/lifecycle still constrain it |
database/Schema.ts:1012-1039; database/provisionAccount.ts:69-115; core/permissions/calculateChannelPermissions.ts:239-263; core/permissions/calculateServerPermissions.ts:57-73 |
server_memberships.timeout_until |
membership | nullable timestamp; active exactly while timeoutUntil > now |
Moderation timeout/lift-timeout path | Channel/server calculators, moderation, conference/Cell | Only View survives an active timeout; all server management and other channel actions are denied | database/Schema.ts:1021-1026; database/Moderation.ts:1370-1468; core/permissions/calculateChannelPermissions.ts:294-298; core/permissions/calculateServerPermissions.ts:59-60 |
server_memberships.can_rejoin |
membership | persisted boolean, default true |
Ban/cancel set it; unban restores it | Community invite/redemption eligibility | Controls whether a former member may re-enter; does not itself authorize current channel access | database/Schema.ts:1021-1027; database/MemberManagement.ts:395-444,459-515,788-818; database/CommunityOnboarding.ts:922-958 |
| Server invite token lifecycle | membership | hashed credential plus active/revoked, intended email, expiry, max_uses/use_count |
Server manager issues/revokes; redemption increments count | Invite preview/redemption | Authoritatively creates active membership only for a matching high-entropy token, active available server/account, eligible former member, capacity, expiry, and intended email; failures collapse to non-enumerating outcomes | database/Schema.ts:802-862; database/CommunityOnboarding.ts:680-850,851-1043 |
Entitlement validity: is_active, validity window, revoked_at |
grant | persisted booleans/timestamps plus Zero validity projection | Subscription/purchase/admin/reward flows; product deletion and ban revoke; validity worker updates sync projection | Channel audience calculator/Zero visibility and media playback | Product atoms count only while active, in validFrom <= now < validUntil, and unrevoked; product/channel/media access disappears on revocation |
database/Schema.ts:4202-4248; core/permissions/calculateChannelPermissions.ts:230-238; core/zeroQueryVisibility.ts:38-49; server/src/MediaProgress.ts:109-157 |
| Billing subscription status and pause/cancel windows | grant | persisted active, past_due, grace, canceled, ended plus period/pause/cancel timestamps |
Member billing and console member-management paths | Product/member projections, email recipients, agent subscription lens | Shapes active/canceling/paused membership commerce state and recipient eligibility; channel access is enforced through membership and entitlements rather than this status directly | database/Schema.ts:3352-3404; database/MemberBillingManagement.ts:43-76,198-257; database/ProductManagement.ts:148-186,325-330; database/EmailManagement.ts:108-131 |
Payment method is_active, is_default |
grant | persisted booleans with one-active-default uniqueness | Member billing add/remove/default commands | Membership resume, media checkout, billing read/UI | Only active methods are selectable; resume requires an active method and media checkout charges the active default. Removing a default can require promoting another method first | database/Schema.ts:2977-3000; database/MemberBillingManagement.ts:146-193,269-363,364-455; database/MediaCommerce.ts:270-288 |
Payout destination active |
grant | persisted boolean with one-active-per-server uniqueness | Owner payout destination/method commands | Owner billing read model and payout configuration | Selects the server’s current destination and speed; setting one deactivates the others. No verified-KYC prerequisite is enforced | database/Schema.ts:3129-3168; database/OwnerBillingManagement.ts:244-378; server/src/BillingReadModels.ts:420-440 |
| Media purchase | grant | durable item/rail purchase row | Media checkout after membership, target, price, ledger and payment checks | Playback/progress and library projection | Unlocks its item or rail independently of product entitlement | database/Schema.ts:2572-2610; database/MediaCommerce.ts:119-231,334-365; server/src/MediaProgress.ts:93-106 |
| Media access mode and product atoms | grant | rail all or products, optional item override, product join rows |
Owner-authorized media management validates active products and rewrites access | Playback/progress and library projection | Item access overrides rail access; all admits active members, while products requires purchase or matching valid entitlement |
database/Schema.ts:2383-2489; database/MediaManagement.ts:568-610; server/src/MediaProgress.ts:74-157; core/mediaDerivations.ts:85-107 |
products.is_active |
grant | persisted boolean | Product lifecycle; deletion sets false and revokes matching entitlements | Audience/media configuration and active product projections | Inactive products cannot be newly selected for audience/media access; deletion removes entitlement-based access | database/Schema.ts:2615-2618; database/ProductManagement.ts:518-521,600-633; database/ChannelManagement.ts:272-275,357-359; database/MediaManagement.ts:193-211 |
products.checkout_enabled |
grant | persisted boolean | Owner-authorized product create/update/toggle; deletion forces false | Console/public-checkout projections | Controls sellable presentation; does not revoke existing entitlement. A public checkout server enforcement consumer was not located | database/Schema.ts:2615-2618; database/ProductManagement.ts:307-309,648-685,762-847; webapp/src/features/console/CheckoutPreview.tsx:19-22 |
products.cap |
grant | nullable positive integer | Owner product create/update | Checkout/read-model UI | Computes remaining seats and disables sold-out selection in web checkout preview; no server checkout mutation cap enforcement was found | database/Schema.ts:2605-2624; database/ProductManagement.ts:386-399,761-847; webapp/src/features/console/CheckoutPreview.tsx:199-238 |
plans.is_active |
grant | persisted boolean, default true |
Product/plan lifecycle | Checkout/read-model selection and plan updates | Only active plans are selected or updated as the current sellable plan; no separate channel/media authority effect | database/Schema.ts:2792-2811; database/ProductManagement.ts:296-299,761-835 |
Affiliate program enabled, mode, invitation, accepted terms |
grant | persisted boolean/enum plus invitation and acceptance rows | Owner-authorized affiliate configuration/invite; member terms acceptance | Referral/link issuance and attribution | Actor needs active membership; disabled program denies; invited mode additionally requires invite; attribution requires affiliate terms acceptance and forbids self-referral | database/Schema.ts:2814-2875; database/AffiliateManagement.ts:93-125,178-225,328-360 |
Coupon active, ends_at, max_redemptions |
grant | persisted boolean/timestamp/nullable cap | Owner coupon create/deactivate; redemption flow appends uses | Checkout/read models and coupon binding | Active is checked when binding a referral coupon; checkout projection treats inactive, expired, or capped coupons as unavailable. Full ends/cap enforcement at a public checkout mutation was not found | database/Schema.ts:2897-2939,3093-3135; database/AffiliateManagement.ts:183-199,369-474; database/ProductManagement.ts:416-448 |
member_mod_grants.capability |
grant | persisted enum: moderate, delete, timeout, ban |
Console member promote/set-capability/demote service | ChannelAuthorization, Moderation, hierarchy, agent tool projection | Four independent delegated actions; capability row does not create server admin/staff authority | database/Schema.ts:2707-2738; database/MemberManagement.ts:517-539,618-648,731-787; database/ChannelAuthorization.ts:90-104 |
member_mod_grants.granted |
grant | persisted boolean, default false |
Promote writes only moderate=true; capability command toggles delete/timeout/ban; demote deletes all rows |
Calculator, moderation/hierarchy, console projection | Effective on/off switch; a stored false row does not authorize | database/Schema.ts:2719; database/MemberManagement.ts:623-640,731-778; core/permissions/calculateChannelPermissions.ts:247-255 |
member_mod_grants.max_duration_seconds |
grant | nullable positive integer | No production writer found; production promote/toggle omit it; fixtures set it | Moderation action loader/executor | Caps delegated timeout duration; owner/staff/admin are treated as unbounded | database/Schema.ts:2720-2733; database/Moderation.ts:211-268,890-968,1385-1402 |
member_mod_grants.max_message_age_seconds |
grant | nullable positive integer | No production writer found; production promote/toggle omit it; fixtures set it | Moderation queue/action/executor | Caps age of messages a delegated deleter may remove/redact; owner/staff/admin are unbounded | database/Schema.ts:2721-2738; database/Moderation.ts:156-201,936-951,1003-1009,1203-1251 |
| Channel audiences | audience | one persisted everyone or products row for each of view, send, conf, attach, react, threadStart, threadReply |
Channel create/set-permissions replaces rows and product joins; Zero wrapper passes actor to DB service | Channel calculator, Zero visibility, web prediction | Nonprivileged action admission. products needs intersection with valid entitlements; missing/malformed rows deny |
core/permissions/audience.ts:3-35; database/Schema.ts:2627-2667; database/ChannelManagement.ts:269-343; core/permissions/calculateChannelPermissions.ts:230-275 |
channel_audience_products.product_id |
audience | persisted product atoms | Channel permission writer, after validating active products | Authorization/Zero and denial projection | Narrows an action to matching entitled products; empty products means staff/owner/admin-only, never Everyone | database/Schema.ts:2651-2667; database/ChannelManagement.ts:288-327; core/zeroQueryVisibility.ts:34-53; docs/architecture/03-permissions.md:14-17,57-61 |
Channel presets: open, readonly, premium, staff |
audience | authoring shorthand, never persisted | Create/edit UI/mutator expands preset | Audience editor and channel creation | staff is all empty product audiences, not a role or audience kind; readonly leaves View/React open; premium selects the first product |
core/permissions/audience.ts:20-23,82-105; docs/architecture/03-permissions.md:14-17; database/Schema.ts:2627-2667 |
Day-7 email day7_flow_enabled |
server | persisted nullable boolean constrained to the day7 template |
Server-manager console email command | Console template read/UI only | Advertises whether the day-7 member email flow is on, but no production sender/worker consumes it; currently gates no delivery | database/Schema.ts:930-959; database/EmailManagement.ts:365-436; webapp/src/features/console/EmailsSection.tsx:68-91 |
| Channel/thread lifecycle and deletion | channel | persisted active, winding_down, read_only, or archived plus deletion flags |
Channel management archive/restore/delete and thread lifecycle paths | Calculator, Zero visibility, route/search/read paths | Deleted targets are unavailable; archived rows are hidden by ordinary Zero reads; read-only/archived channel or thread preserves View but denies every other channel permission | core/permissions/calculateChannelPermissions.ts:24,277-321; core/zeroQueryVisibility.ts:10-12,56,79-87; database/ChannelManagement.ts:540-591 |
| Thread audiences | audience | optional persisted everyone/products for attach, react, threadReply |
Set-thread-audiences command rewrites rows/products | Channel calculator and Zero/thread UI | Overrides those three actions only; absent override inherits parent audience; parent View remains the ceiling | core/permissions/calculateChannelPermissions.ts:22,277-292; database/Schema.ts:2669-2706; database/ChannelManagement.ts:1207-1229 |
Channel view |
channel | derived PermissionDecision |
Calculator from audience/entitlements/privilege | All channel reads, Zero row visibility, realtime/search/media/notifications | Read ceiling for every other action. Staff/owner/admin bypass audience only; account/membership/server/channel hard clamps still apply | core/permissions/calculateChannelPermissions.ts:217-246; core/zeroQueryVisibility.ts:4-89; server/src/RouteAuthorization.ts:52-73 |
Channel send |
channel | derived decision | Calculator from send audience; thread aliases threadReply |
Message send/typing/Cell publish and composer | Creates messages/realtime publish; active timeout or read-only/archive removes it | core/permissions/calculateChannelPermissions.ts:243-298,303-321; server/src/cells/CellAuth.ts:65-111; webapp/src/components/chat/Composer.tsx:304-329,573-609 |
Channel conf |
channel | derived decision | Calculator from conf audience; not applicable to threads | Conference visibility/admission | Requires ordinary View plus conf audience; threads are denied as action-not-applicable | core/permissions/calculateChannelPermissions.ts:270-292; core/zeroQueryVisibility.ts:91-102; database/Conference.ts:111-127 |
Channel attach |
channel | derived decision | Calculator from attach or thread override | Attachment/message edit/upload UI and server mutators | Adds/edits attachments in the channel; client check is advisory and server authorization remains authoritative | core/permissions/calculateChannelPermissions.ts:270-287; webapp/src/components/chat/MessageRow.tsx:193-197; server/src/Zero.ts:518-534 |
Channel react |
channel | derived decision | Calculator from react or thread override | Reaction mutators/UI | Adds/removes reactions; hard clamps can only narrow it | core/permissions/calculateChannelPermissions.ts:270-287,294-321; webapp/src/components/chat/MessageRow.tsx:191-200 |
Channel threadStart |
channel | derived decision | Calculator from thread-start audience | Thread creation UI/mutator | Starts a thread from a non-thread channel; denied as not applicable inside a thread | core/permissions/calculateChannelPermissions.ts:270-292; webapp/src/components/chat/MessageRow.tsx:191-200,354-391 |
Channel threadReply |
channel | derived decision | Calculator from channel or thread override | Thread composer/realtime | Sends a thread reply; on thread targets it is also the send decision |
core/permissions/calculateChannelPermissions.ts:277-292; webapp/src/components/chat/ThreadPanel.tsx:59-80,125-145 |
Channel editOwn, deleteOwn |
channel | derived decisions | Calculator maps own-message operations to send audience | Message/attachment server authorization and UI | Edit/delete actor’s own message; non-owner edit is null and non-owner delete falls through to moderation delete |
core/permissions/calculateChannelPermissions.ts:264-268; core/permissions/calculateMessagePermissions.ts:3-15; server/src/Zero.ts:483-516 |
Channel moderate |
grant | derived decision | Calculator from privilege or granted moderate row |
Queue/navigation, moderation action loading, agent moderation tool exposure | Opens moderation surface and is prerequisite for action-specific delete/timeout/ban; not sufficient by itself for those actions | core/permissions/calculateChannelPermissions.ts:247-255; database/Moderation.ts:823-889,890-914; server/src/AgentConversations.ts:164-234 |
Channel delete |
grant | derived independent decision | Calculator from privilege or granted delete row |
Message moderation loader/executor | Deletes another member’s message only after moderate, hierarchy and message-age checks |
core/permissions/calculateChannelPermissions.ts:247-255; database/Moderation.ts:211-268,924-951,1203-1251 |
Channel timeout |
grant | derived independent decision | Calculator from privilege or granted timeout row |
Timeout/lift-timeout loader/executor | Changes membership timeout only after moderate, hierarchy, target-state and max-duration checks |
core/permissions/calculateChannelPermissions.ts:247-255; database/Moderation.ts:924-951,1370-1468 |
Channel ban |
grant | derived independent decision | Calculator from privilege or granted ban row |
Ban/unban loader/executor | Changes membership ban state only after moderate, hierarchy and target-state checks; only owner path may pair refund |
core/permissions/calculateChannelPermissions.ts:247-255; database/Moderation.ts:924-968; database/MemberManagement.ts:156-184,395-444 |
Channel manage |
channel | derived decision | Calculator from staff/owner/admin privilege | Route authorization and channel setting/permission operations | Non-destructive channel administration; server/channel read-only or archived states deny it | core/permissions/calculateChannelPermissions.ts:258-263,300-321; server/src/RouteAuthorization.ts:75-94; database/ChannelManagement.ts:145-185 |
Channel manageDestructive |
channel | derived decision | Calculator from staff/owner/admin privilege | Move/archive/delete and destructive moderation path | Destructive channel changes; winding-down denies it before read-only/archive clamps | core/permissions/calculateChannelPermissions.ts:261-263,300-321; database/ChannelManagement.ts:540-568,993-1008; database/Moderation.ts:674-678 |
| Moderation hierarchy | grant | derived rank: staff > owner > admin > moderator > member | DB derives role/granted-moderate facts | Every moderation/member-management target check | Actor cannot enforce against self or owner and must strictly outrank target; action capability is checked separately | core/moderation.ts:98-124; database/decideMemberHierarchy.ts:16-31,52-90 |
| Web channel/server permission prediction | channel | advisory recomputation of channel decisions and server manage family from synced Zero context |
Client derives from account, membership, audience, entitlement, grant, lifecycle, and a one-second clock | Composer, realtime mode, message actions, sidebar and management controls | Hides/disables controls and chooses publish versus subscribe; every mutation/token/API path rechecks authority server-side | webapp/src/features/permissions/useChannelPermissions.ts:1-183; webapp/src/features/permissions/useServerManagement.ts:1-81; webapp/src/components/chat/Composer.tsx:304-317,573-609; webapp/src/components/shell/AppSidebar.tsx:36-80,189-249 |
Console member allowedActions |
membership | projected array: ban, unban, refund, pause, resume, cancel | Console read model derives hierarchy, membership, refund and subscription state | Members console UI | Shows only contextually plausible controls; DB member-management commands independently recheck server authority, hierarchy and state | core/consoleMembers.ts:24-36; server/src/ConsoleReadModels.ts:749-820; webapp/src/features/console/MembersSection.tsx:288-368 |
Console moderatorCaps projection |
grant | projected delete/timeout/ban booleans plus optimistic granted |
Read model derives stored grants; console writes through member-management API | Moderation console checkboxes | Displays/toggles grant rows; no Zero path exists and final capability use is rechecked by moderation services | server/src/ConsoleReadModels.ts:812-820; webapp/src/features/console/ModerationSection.tsx:25-29,160-184; database/MemberManagement.ts:731-787 |
hasModerationAuthority |
grant | derived async boolean; no stored writer | Reporter-free scan of active memberships/roles/grants plus calculator | Moderation navigation and queue load | Availability only: true if any live channel has effective moderate; actual operation rechecks action grant, hierarchy, limits and target state |
database/Moderation.ts:822-889,970-978; server/src/Moderation.ts:56-60 |
| Zero channel row visibility | audience | reactive ZQL predicate | Derived from persisted account/server/membership/participant/audience/product/entitlement state | Nearly all channel/message/thread/media/home queries and server visible-ID query | Community visibility requires active account/member and owner/staff or audience entitlement; DMs require an active participant; threads require visible parent and live root | core/zeroQueryVisibility.ts:4-89; core/zeroQueries.ts:261-307,539-576,755-789; server/src/Zero.ts:916-941 |
Participant-channel membership (role, left_at) |
membership | persisted owner or member plus nullable departure |
DM/group/self creation and participant lifecycle | Zero visibility, DM send/read, search and notifications | Role identifies conversation owner but does not grant server privilege; only rows with no left_at admit participant-channel visibility or send/read operations |
database/Schema.ts:1135-1157; core/zeroQueryVisibility.ts:66-77,215-230; server/src/Zero.ts:684-720; server/src/dm.ts:134-148 |
Participant hidden_at / hidden_after_sort_id |
membership | per-viewer nullable visibility cursor | Authenticated DM hide/unhide Zero mutator | Direct-message list and notification recipient filter | Hides a conversation until a newer message appears and suppresses notification candidacy while hidden; does not revoke channel participation | database/Schema.ts:1148-1151; server/src/dm.ts:286-321; webapp/src/features/direct-messages/directMessages.ts:54-60; database/Notifications.ts:165-196 |
Participant is_muted |
membership | persisted boolean, default false |
DM creation writes false; no mutation/read consumer found | No production consumer found | Currently gates nothing | database/Schema.ts:1135-1151; server/src/dm.ts:134-148 |
| Zero profile visibility | audience | candidate predicate plus server-only mutual-block predicate | Derived from profile/account/shared-membership/block state | Profile/activity/presence/search queries | Self is visible; others require active/nondeleted shared-server profile, privacy exception, and no block. Client IVM candidate cannot express the final NOT EXISTS block check |
core/zeroQueryVisibility.ts:104-185; database/ProfileAuthority.ts:111-198 |
| Zero mutator operation authorization | channel | authenticated server-only wrapper plus per-operation DB decision | Wrapper supplies actor; each DB service recalculates authority in the transaction | All registered Zero mutators | Client optimistic writes are advisory. Server verifies session/location and then View/send/ownership/manage/action permission before committing | server/src/Zero.ts:362-386,436-516,657-720; core/zeroMutators.ts:11-28 |
| Console member/grant path | membership | authenticated route plus transactional DB service | Console routes call ConsoleMemberManagement; DB MemberManagement writes membership/grants |
Console only; no Zero grant/admin writer found | Route wrapper proves signed-in identity only; DB service authoritatively checks server-manage/channel-ban authority and hierarchy before ban/refund/pause/cancel/promote/demote/capability writes | server/src/consoleRoute.ts:17-67; server/src/ConsoleMemberManagement.ts:26-111; database/MemberManagement.ts:140-184,517-787 |
| Channel-management Zero path | channel | authenticated Zero conductor into authoritative DB service | Web/client invokes Zero; server passes actor to ChannelManagement |
Channel create/edit/move/archive/restore/delete/audience writers | Unlike member grants, channel management is Zero-reachable; authoritative DB service uses server/channel manage or manageDestructive, revision and lifecycle checks |
server/src/channelManagement.ts:14-139; database/ChannelManagement.ts:145-185,540-568,777-791,993-1011 |
| Route authorization | channel | 404-style view, channel-manager, server-manager, owner gates |
Derived on each request | HTTP/API handlers | View accepts community calculator or participant channel; manager uses channel/server manage; owner route requires active server ownership |
server/src/RouteAuthorization.ts:52-123 |
| Conference admission/visibility | channel | authoritative View+Conf decision and participant revocation | Conference/channel commands and authorization state | Conference load/admit and Cell token mint | Hidden/denied channel cannot admit; revoked participant cannot load; livestream marker additionally must be upcoming/live and unexpired | database/Conference.ts:111-127,275-341,718-743 |
| Conference role/moderation | grant | host/listener/participant/staff role plus enforced mute/revision | Admission, host and moderation commands | Conference provider/Cell/client | Only current host may remotely mute; target must be admitted and cannot be the host; Cell token embeds derived role and enforced mute | database/Conference.ts:342-379,395-457,718-743; server/src/cells/CellAuth.ts:156-238 |
| Cell publish/subscribe/presence token | channel | signed operation-scoped token | CellAuth after authoritative checks | Celld realtime plane | Channel publish requires send, subscribe requires view; presence subscribe requires profile visibility; conference token requires admitted call/membership authority |
server/src/cells/CellAuth.ts:65-154,156-238 |
| CellD connection and ingress claims | channel | short-lived HMAC JWT with issuer, audience, time, subject/session, cell allowlist, mode; ingress adds exact scope and cell | Server CellAuth/CellIngress; push worker mints presence-read ingress claims |
CellD WebSocket, roster, metrics and revoke ingress | Possession is the realtime-plane gate: connection token must name the exact cell; internal token must match metrics:read, presence:read, or revoke and exact cell. CellD does not synchronously recheck Better Auth or PostgreSQL |
server/src/cells/CellAuth.ts:57-224; server/src/cells/CellIngress.ts:28-66; worker/src/pushLive.ts:91-116; cells/src/main.ts:39-65,184-290,509-601 |
| CellD session/authorization revocation | channel | session id or monotonic epoch/revision carried in socket attachment and revoke projection | Auth/session, channel/server lifecycle and conference paths publish revocations | CellD closes stale sockets and applies newer conference authority/mute revisions | Narrows token lifetime asynchronously: matching session or stale epoch sockets close; conference role/mute updates apply only when revision increases | database/Schema.ts:1198-1258; cells/src/main.ts:66-81,612-636,791-893; cells/src/socketAttachment.ts:371-392; server/src/cells/CellIngress.ts:189-250 |
| Attachment readability/cancellation | channel | compound channel/participant/emoji/owner and readiness gate | Attachment, message, channel and emoji lifecycle; owner cancellation | Download/URL/cancel endpoints | Read requires view/participant, approved emoji, or unlinked ownership; cancel requires owner, nondeleted, unused attachment. Ingest download instead trusts an unexpired operation token | server/src/files/Attachments.ts:280-380,383-431 |
message_revisions.is_restricted |
audience | persisted boolean on historical evidence, default false |
No production writer sets true; moderation inserts ordinary redaction revisions | Moderation redaction/evidence path | Prevents already-restricted revision content from being selected/redacted again; currently reachable only through externally/fixture-provisioned true rows | database/Schema.ts:2115-2135; database/Moderation.ts:506-539 |
attachments.legal_hold |
platform | persisted boolean, default false |
No production writer found; tests set directly | Moderation redaction cleanup | A held attachment is excluded from detachment/deletion when messages are redacted; it does not itself grant attachment readability | database/Schema.ts:2219-2273; database/Moderation.ts:568-593 |
| Search ACL and reload | channel | visible-channel ID set plus final DB recheck | Active membership/participant and ChannelAuthorization projections | Meilisearch filtering/result assembly | Empty ACL hard-denies; results are dropped after current nondeleted membership/participant/View recheck; hidden profile names are masked, not the hit | server/src/SearchService.ts:137-150,238-307,309-421 |
| Notification scope/recipient visibility | audience | channel/server scope authorization and recipient filter | User scope setting; message notification projector | Notification rows, unread and push jobs | Scope write needs View or active server membership; recipients must remain active and authorized channel viewers/participants; actor excluded | server/src/notifications.ts:113-171; database/Notifications.ts:75-224 |
| Notification user/kind/scope preferences | audience | user booleans; per-kind enabled/sound; nearest-scope default, all, mentions, nothing |
Authenticated Zero setting mutators; scoped writes require View or active server membership | Push preparation and web desktop delivery; home projection reads badge flag | Suppresses delivery by kind/scope or while viewing, removes sound, and hides the home badge count. Preferences do not authorize notification source rows | database/Schema.ts:4283-4359; core/notifications.ts:69-99,115-168; server/src/notifications.ts:101-211; database/Push.ts:319-398,579-585; webapp/src/features/home/useHomeProjection.ts:10-39 |
channel_read_states.notification_preference |
audience | persisted default, all, mentions, nothing |
DM creation writes the default; no production update writer found | No production delivery reader found | Currently gates nothing. The live thread/channel notification UI writes separate notification_scope_settings, not this column |
database/Schema.ts:2187-2215; server/src/dm.ts:134-159,227-252; server/src/notifications.ts:142-211 |
| Push source/subscription authorization | audience | final source recheck plus subscription permission_state, session and revocation fields |
Notification/message lifecycle, push registration, session reconciliation/provider failure | Push preparation/delivery | Suppresses inactive/self/deleted/stale/unauthorized sources; sends only through matching unexpired sessions and granted, nonrevoked subscriptions. Provider permission-denied changes the stored state to denied |
database/Schema.ts:4361-4407; database/Push.ts:275-330,578-614,981-1102,1160-1190 |
| Media playback/progress access | membership | compound authoritative grant | Media/product/purchase/entitlement/member writers | Playback URL/progress recorder | Requires active account/membership and live hosted item; admits staff/admin, all-access content, purchase, or current unrevoked entitlement | server/src/MediaProgress.ts:42-167,141-211 |
| Agent allowed tools/methods | grant | ephemeral method/capability sets | Runtime derives from lens, privilege and current moderation grants | Model tool exposure and per-call wrapper | Advisory exposure only: privileged/mod-granted actor sees matching operations; DB staging/execution remains authoritative | server/src/AgentConversations.ts:164-234,504-546; server/src/manifestToTools.ts:69-75,100-124 |
| Agent approval authority snapshot | server | persisted actor/conversation/tool/status, authorization epoch, target/tool versions, expiry and canonical-args hash | Approval-intent creation; decision/execution transitions | Approval endpoint and execution claim | Prevents actor/lens/membership changes, permission epoch changes, target edits, retired tools, expiry, or argument tampering between proposal and execution | database/Schema.ts:4762-4847; database/AgentConversations.ts:1023-1189,1191-1317,1391-1489,2176-2248 |
| Agent tool-card/status projection | server | frozen JSON/status booleans | Intent/event projection | History/UI | Presents approval/output state only; never substitutes for DB authority rechecks | core/agent.ts:7-20,300-386; database/AgentConversations.ts:80-107,1244-1317,1483-1487,1606-1613 |
| Economy eligibility interval | membership | persisted half-open membership eligibility interval | Membership/economy lifecycle projection | Economy fact ingestion | Credits an economy fact only when the user was eligible at the authoritative occurrence time; delayed facts before a later leave/ban remain valid | database/Schema.ts:1622-1650; database/Economy.ts:100-125 |
| Economy badge grant revocation | grant | persisted grant with revoked_at and reason |
Economy goal/badge reconciliation | Self badge Zero query and UI | Retains revoked badge evidence and renders it struck through; it affects badge presentation, not channel or economy-operation authority | database/Schema.ts:1900-1943; database/Economy.ts:181-285; core/zeroQueries.ts:998-1010; webapp/src/features/economy/EconomyPointsCard.tsx:70-82 |
| Checkout claim token lifecycle | grant | hashed single-use credential with expiry, consumed/revoked/replacement state | Support resend-claim execution issues/replaces tokens | No production redemption consumer found | Intended to gate account claim for a completed unclaimed checkout, but currently only issuance/replacement exists; no repository path consumes it | database/Schema.ts:3898-3932; server/src/applySupportDatabaseAction.ts:335-363 |
Billing webhook is_verified |
platform | persisted boolean | No production writer found | No production reader found | Currently gates nothing; unlike the conference webhook, no billing webhook verification/processing path was found | database/Schema.ts:3333-3349 |
| Conference webhook signature | platform | HMAC signature plus five-minute timestamp freshness | Daily provider signs; server verifies raw delivered bytes | Conference event ingestion | Rejects an actual event with missing, malformed, stale, or non-constant-time-matching credentials before applying it. The exact inert registration probe is intentionally accepted unsigned and changes no durable state | server/src/confWebhook.ts:126-162,415-447 |
- BOJ-237 confirmed: no production writer sets
max_duration_secondsormax_message_age_seconds; promote and capability-toggle commands leave both null. The bounded grant fields exist and are enforced only when data is externally/fixture-provisioned. - BOJ-232 context:
staffis not an audience kind and does not mean “moderators.” It expands to empty product audiences, so effective access is staff/owner/admin privilege. A moderator with onlymoderatecannot enter a staff-preset room unless another audience admits them. - No production writer was found for
users.is_staff, server-owner transfer, membership-admin promotion/demotion, profile privacy, KYC, any legal-hold field, restricted message revisions, or attachment legal holds. Owner/admin creation occurs in provisioning; staff/operator provisioning and the currently-readable true-only fields are external/manual. - No Zero writer exists for platform staff, membership admin, member moderation grants, or their caps. Member/grant changes are console/API-to-database paths. Channel/thread audience changes are Zero-reachable but reauthorized transactionally.
servers.feature_flagshas no production writer or reader.servers.is_publichas an authoritative settings writer and UI meaning, but no repository discovery consumer was found.canCustomDomain,canAutomation, andcanAdvancedAnalyticsare unconsumed.videoStoredMinutes,mauAllowance, andaiActionsare meters, not enforcement;broadcastMonthlyLimitis enforced on announcement recording.canNativeLiveis duplicated as a direct tier check on the server rather than shared. Validated-GMV checkout denial is calculated/projected but not wired to a production checkout mutation.thread.create,stream.join, andstream.startare capability-manifest names without SDK method metadata.message.moderatemetadata and member grant vocabulary (moderate,delete,timeout,ban) remain separate mappings.permissionErrors.raisehas tests but no production caller. Callers currently use direct decisions and local error adapters.- Attachment ingest download trusts possession of an unexpired asset-operation token and does not re-evaluate actor/channel authority. Livestream marker visibility is enforced, but no separate provider/CDN playback permission evaluator was found.
- No product permission evaluator was found in
mobile/src; worker product authorization is absent except for a signed worker-to-Celld presence service token. Web permission checks are advisory and server paths recheck. - Agent
allowedTools,allowedMethods, and runtime capabilities are ephemeral derived projections. Intentexpiredis enforced at decision/claim time; no proactive expiry worker was found. - Schema/state without a complete production path:
channels.is_private,channel_participants.is_muted,channel_read_states.notification_preference, KYC status, billing webhookis_verified, and checkout claim tokens have no production consumer; day-7 flow and server feature flags have no delivery/feature consumer. Restricted message revisions and attachment/support legal holds have production readers but no production writer setting them true; audit-event legal hold has neither. - Mobile is a shell: it displays static capability names but has no network, Zero-mutator, or product-permission consumer. Deployment/MCP gates are separate platform-operator controls, not tenant roles.
- Searches covered
core/,database/,server/,sdk/,webapp/,mobile/,worker/,scripts/, schema/migrations, Zero schemas/queries/mutators, console routes, runtime token issuers, and direct consumers of the named fields and decisions. Test-only writers were not reported as production writers.