> ## 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.

# Feature flags

> Default-off registry and the mobile evaluation contract.

The root `config/feature-flags.json` owns the flag inventory. Each array entry has
`key` (unique snake\_case), `description`, `owner`, `class` (`read`, `write`, `ui`,
`kill`), `default: false`, and `removeBy` (ISO date). The initial 16 mobile flags
belong to `mona` and expire on `2027-01-31`.

## Add a flag

Name the flag in its PR, add its registry entry with default OFF, assign an owner
and removal date, and wire its kill switch before enabling the feature. Follow the
[trunk-based delivery rule](https://docs.tuturuuu.com/build/development-tools/git-conventions.md#trunk-based-delivery):
flags default OFF; kill switch first, rollback second.

Run `cd packages/feature-flags && bun run generate` after editing the JSON, then
format the generated file with Biome and commit it. `@tuturuuu/feature-flags`
exports `registry`, the generated `FlagKey` union, and the pure
`evaluateFlags(registry, context, overrides?)` function. Its tests validate the
registry and detect generated-source drift.

## Mobile endpoint

`GET /api/v1/mobile/feature-flags?wsId=<uuid>` accepts the existing session or
mobile app-session authentication. Authentication failures return 401. `wsId` is
optional; when supplied it must be a UUID (400 otherwise), and the caller must
belong to that workspace (403 otherwise). Membership lookup failures return 500.

A 200 response contains only:

```json theme={null}
{
  "version": "<sha256>",
  "ttlSeconds": 30,
  "flags": { "mobile_offline": false, "offline_read_notes": false }
}
```

The example abbreviates `flags`; the response includes **every registry key**.
`version` hashes the JSON payload `{ttlSeconds, flags}` with SHA-256, excluding
`version` itself. `ETag` is that version in double quotes. A matching
`If-None-Match` returns 304 with no body, after authentication and membership
checks. Responses use `Cache-Control: private, no-cache` and
`Vary: Authorization, Cookie`. The mobile reader polls using the 30-second TTL
and retains the last payload on 304. No user or workspace identifiers are
returned. User identity comes only from the authenticated session; query
parameters cannot select a user. The handler uses
`await connection()` for request-time evaluation, with no shared output cache.
Both `CDN-Cache-Control` and `Vercel-CDN-Cache-Control` are `no-store`, including
304 and error responses.

## v0 semantics

v0 returns defaults; store-backed targeting (user/%/workspace, kill switch, audit)
replaces v0 behind the same contract. The endpoint supplies no overrides. The
pure evaluator accepts future overrides for known keys only and applies the kill
switch last: `mobile_offline: false` forces every `offline_` key OFF, including
reads, writes and status UI. Context currently has no effect. This endpoint does
not enable offline functionality or grant access to underlying data.

Regression coverage lives in `packages/feature-flags/src/index.test.ts` and
`apps/web/src/app/api/v1/mobile/feature-flags/route.test.ts`.


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