> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuturuuu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Permission parity inventory

> Review mobile and satellite API authorization evidence and detect inventory drift.

The planned permission parity check inventories API paths from mobile Dart clients and
satellite request calls, follows shared client imports, and records the matching
handlers in `scripts/ci/permission-parity.snapshot.json`. Each entry identifies
the route, exported HTTP method, consumers, owning application, membership
helper, named permissions, permission denial expressions and candidate UI pages.
Source hashes make changes to consumers and analyzed authorization code visible.

## Implementation status

The checker, tests and snapshot described here are pending [PR
\#7019](https://github.com/tutur3u/platform/pull/7019). They are not included in this
documentation commit. Run the commands below only after that implementation lands.

## Planned commands (pending #7019)

After #7019 lands, use the repository resource queue:

ttr resources run -- node --test scripts/ci/permission-parity.test.js

After adoption, the existing Root script tests (24) job in
`.github/workflows/turbo-unit-tests.yaml` will discover this file through
`scripts/run-script-tests.js`. No separate workflow or deployment is required.
The check is subject to the existing workflow admission rules.

Regenerate the snapshot after an intentional change:

ttr resources run -- node scripts/ci/permission-parity.js --write

Writing the snapshot does **not** clear authorization failures. The command
returns a nonzero status while unresolved paths or workspace permission checks
remain. Review the diff before committing; never regenerate solely to turn CI
green.

For complete diagnostics from the repository root:

node -e "const p = require('./scripts/ci/permission-parity'); console.log(p.checkInventory(p.buildInventory(process.cwd())).join('\n'))"

## Interpret failures

The gate rejects an unresolved consumed route, missing membership evidence,
missing named permission evidence, missing UI policy evidence, differing API and
UI denial expressions, or snapshot drift. An unrecognized authorization pattern
is a failed proof, not evidence that the endpoint is exploitable.

Membership evidence currently recognizes an awaited `getPermissions` result with
an unconditional return or throw when it is absent. Named permissions must appear
in a top-level conditional denial using `withoutPermission`. Boolean AND and OR
remain distinct. Shared route re-exports are followed; returned helpers and
helper results with a subsequent rejection branch can contribute evidence.
Unused imports, unused functions, ignored helper results and checks inside a
nested conditional cannot supply evidence for an otherwise unguarded method.
GET evidence cannot authorize POST.

Client discovery treats Dart endpoint definitions as possible consumers and
checks every exported method of each matching route. Satellite discovery follows
static imports, barrel dependencies and literal dynamic imports from source
request calls. Shared internal API endpoint builders are included. Tests,
generated registries, server route trees and routing configuration are excluded
from client discovery. Dynamic values are matched conservatively against route
segments; unresolved expressions need review.

Workspace checks apply to routes containing a workspace parameter. Public,
authentication and user-only routes remain in the inventory but do not receive
an invented workspace permission requirement.

## Review and adoption

The initial inventory is a strict audit candidate. Do not merge it as a required
gate until its unresolved paths, helper contracts and UI policies have been
reviewed. It carries no baseline exemptions for missing checks.

UI candidates are selected by the longest matching feature path across active
app pages. This is a review aid: shared layouts, action-specific controls,
ownership rules, board visibility, approval roles, wallet restrictions and
parameterized helper policies can require explicit endpoint contracts. Verify
those contracts against first-party callers and add behavioral denial and
success tests before treating a static match as authorization acceptance.
Do not add broad exemptions or remove a client simply to satisfy this checker.

Mobile does not send every request to web. `api_origins.dart` selects owning
satellites for several domains, while web retains other contracts. The inventory
therefore includes matching satellite implementations and shared handler
packages alongside web's current and retained legacy routes. Matching a path
does not prove that a deployment routes traffic to that owner.

This check does not execute handlers or prove control-flow dominance, returned
HTTP status, row scoping, RLS behavior, deployment identity or complete Dart and
TypeScript data flow. A green static check cannot replace runtime authorization
tests or security review. During adoption, distinguish missing enforcement from
unsupported static analysis and intentional contextual policies.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.