Skip to content

[v3 auth] Align built-in permissions and verify framework boundaries #178

Description

@olliethedev

Parent

Depends on

Related

Purpose

Adopt the typed, authoritative authorization contract across every protected built-in operation and verify the resulting developer experience in Next.js, React Router, and TanStack Start. This is the third delivery stage of #173.

Security model

  • The server policy is authoritative.
  • Client checks control presentation, navigation, and optimistic UX only.
  • A browser-safe pure evaluator may be reused on both sides, but privileged policies use a client-safe claim projection or typed transport.
  • Built-in operations receive automatic enforcement only after their permission semantics are explicitly declared.
  • Lifecycle hooks remain available for additional ownership, tenant, and data-dependent rules.

Scope

  • Publish a complete permission inventory connecting every protected first-party control, client route, and backend operation.
  • Declare matching resource/action/params tuples for built-in permission-sensitive endpoints.
  • Route those endpoints through [v3 auth] Add authoritative request-scoped server permission enforcement #177's authoritative server policy before protected work.
  • Align every built-in <CanAccess>, useCan, and route guard with the tuple enforced by its backend operation.
  • Fix or verify [v3 RC2] CommentThread ignores delete permission and surfaces failed owner action #169 through the shared tuple rather than a component-local exception.
  • Remove duplicated first-party base role checks only after equivalent authoritative enforcement is covered; retain hooks for application-specific record rules.
  • Document both supported policy variants: a browser-safe pure evaluator reused by client/server adapters, and a privileged server-only policy exposed through safe claims or typed transport.
  • Verify framework packaging, SSR, hydration, client navigation, and API enforcement using production fixtures.

Required package boundaries

  • Isomorphic permission definitions live in a neutral auth entry and neutral plugin /permissions subpaths.
  • @btst/stack/context remains the client React surface.
  • @btst/stack/api remains the server request-enforcement surface.
  • The isomorphic barrel does not re-export environment-specific providers or helpers.
  • Client imports cannot pull database, session, secret, request, or server-only modules into browser output.

Framework verification

Next.js

  • The Client Component imports or constructs its client adapter; no policy/provider function crosses the Server Component serialization boundary.
  • The server adapter remains outside the Client Component import graph.
  • Any initial identity/capability value passed to the client is serializable.
  • A production build proves representative server-only modules and secrets are absent from client output.

React Router

  • Normal Framework Mode keeps the server adapter in a .server.ts module/directory.
  • The supported RSC variant uses its server-only boundary rather than relying on normal .server semantics.
  • Route components may import neutral permissions/client auth; loaders, actions, and resource routes may import the server adapter.
  • A negative fixture proves an intentional server-module leak is rejected.

TanStack Start

  • Isomorphic loaders do not import or invoke the request-scoped server authorizer.
  • Authoritative checks run in the BTST server route/handler or an explicitly server-bound application function.
  • SSR and subsequent client navigation use the appropriate adapters without moving the server policy into the browser.
  • BTST core remains independent of createServerFn, createServerOnlyFn, and createIsomorphicFn; the framework adapter/application owns those boundary primitives.

SSR and hydration

Document and test the current protected-UI behavior while client identity is pending during SSR/hydration. The v3 requirement is consistent, hydration-safe pending/redirect behavior across all supported fixtures. An optional initialIdentity or generalized capability snapshot is a follow-up unless separately approved.

Acceptance criteria

  • Every protected built-in control, route, and endpoint appears in a reviewed permission inventory.
  • Matching client and server paths use the same registered resource/action/params tuple.
  • Every declared permission-sensitive built-in endpoint invokes the authoritative server policy.
  • Undeclared custom endpoints are not advertised as automatically protected.
  • [v3 RC2] CommentThread ignores delete permission and surfaces failed owner action #169 is fixed or closed through the shared permission contract with client/backend tests.
  • Representative lifecycle hooks demonstrate additional ownership/data rules without duplicating the base role policy.
  • Next.js, React Router, and TanStack Start fixtures each exercise the same anonymous, authenticated-denied, and authenticated-allowed route/read/mutation tuples.
  • Each framework fixture verifies server-derived record parameters and rejects reliance on client-supplied authorization claims.
  • Next.js production CI proves no server-only dependency reaches the client graph and no policy function crosses an RSC serialization boundary.
  • React Router production CI proves the documented server module split and includes the supported RSC boundary where covered.
  • TanStack Start production CI exercises SSR and client navigation and proves an isomorphic loader cannot import/invoke the server authorizer.
  • Bundle inspection or an equivalent negative fixture proves representative database/session/secret modules are absent from client output.
  • Protected UI pending, redirect, and hydration behavior is documented and consistent across all three fixtures.
  • Documentation shows the minimal client/server setup for pure shared and privileged server-only policies.
  • Package typecheck, authorization tests, all representative plugin tests, three framework production builds, and docs build pass.

Non-goals

  • Optional SSR identity/capability snapshots beyond documenting current behavior.
  • A generalized remote-capability client with batching, caching, and invalidation.
  • Exhaustive experimental React Router RSC coverage beyond the supported fixture.
  • A role/authorization DSL, authorization code generation, or migration tooling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions