Source: admission_manifest.md

Generated automatically from the published contract sources.

Source path: admission_manifest.md.

Contract text

The Admission Manifest — Format Contract

Purpose

This document defines the JSON format of the application manifest the admission PRD describes: its required fields, allowed values, and format errors. The JSON Schema at schemas/manifest.schema.json is maintained alongside this contract; neither file is generated from the other. A test in the platform's suite checks their agreement.

Runtime admission checks belong to the requirements that own the affected service, region, audience, and policy. A valid JSON document does not prove those runtime checks passed. MAN-01 states how the manifest reaches submit_manifest; account-side egress policy belongs to ADM-L0-04.

Requirements are numbered MAN-nn.

The document

MAN-01 (decided): A manifest is one JSON document conforming to the schema, and it opens with its own contract revision: manifest_version, the integer 1 for this form. A manifest whose version is not a known revision is refused as malformed rather than best-effort-read, because a reader guessing at an unknown revision enforces something other than what the author declared. The manifest's home is a file in the application project — manifest.json at the project root — and the admitting act reads it from the submit_manifest request body: the customer's tool sends the file's content, and no path is fetched from anywhere.

MAN-02 (decided): The manifest's members are the six declarations ADM-L0-01 names — services, health, region, egress, audience, packages — and manifest_version, every one required, and the three optional declarations ADM-L0-01 names, settings, upstreams, and realm; nothing else is admitted. Membership changes by ADM-L0-01 amendment, the schema and citing tests changing in the same change. An unknown member fails validation instead of passing as inert, because a field the check ignores is a declaration the reader believes and Turn Zero does not enforce — the nothing-undeclared rule applied to the manifest itself.

One unknown member is refused by its own name rather than as unknown: an environments member is refused environment_unsupported with the remedy (MAN-06). It is named because an application's environments are the platform's, set by create_environment and delete_environment (PLD-L0-96), and the author of a manifest written against an earlier revision of this contract is told what to change. The ai_purposes member, which carried the retired AI gateway's purposes and which no service read, left the manifest with MAN-04's retirement. A manifest written against the earlier revision fails as an unknown member at that member's path (MAN-12), and the remedy is to delete the member.

The manifest carries no application identity: it declares what an application consumes and contains, and which application it binds to is the admitting action's (API-L0-01), so one manifest text can serve one application today and a fork tomorrow without editing.

The three optional members may be absent. The settings member is the stored secrets the application's process reads as named settings; a manifest that omits it binds no setting (MAN-14). The upstreams member is the keyed upstreams the application calls through the gateway; a manifest that omits it leaves its upstreams to declare_upstream (EGW-L0-02). The realm member is the sign-in configuration of the application's end-user realms; a manifest that omits it leaves that configuration to configure_realm (ACS-L0-07).

The members

MAN-03 (decided): services declares the provisioned services the application consumes, by the catalog's own names (SVC-L0-01; SVC-L0-06). It is an array of entries, each {"kind": …}. The kinds database, object_storage, email, accounts, and push (SVC-L0-20) stand alone, and issue_tracking stands alone or carries a space and a level. custom_domain carries its domain, the manifest declaration SVC-L0-07 names. schedule carries its schedules.

schedules is a list of one to twenty-five declarations at the shape's cap, the plan's schedule-count-limit refused at submit by name. Each declaration is a name, a cron, and a path. The name is a lowercase letter followed by lowercase letters, digits, or underscores, with no hyphen, and is unique within the application. The cron is five fields in UTC, minute, hour, day of month, month, and day of week, each *, an integer, a range, a list, or a step. The schema refuses any other shape at its path, and the admitting act refuses a field out of range or an expression with no due time inside a year. The path is an absolute HTTP path on the application's own server in MAN-05's form, under neither reserved path prefix, /__account/ (ACS-L0-04) nor /__router/. The schedule service PRD's declaration statement owns the bounds.

schedule is the recurring time-driven invocation service (SVC-L0-15), renamed from scheduled_jobs while no admitted manifest existed to carry the old kind. A schedule entry carrying no schedules is refused, a kind carrying no schedule declaring nothing. A resubmission converges the application's schedules to the entry. An unchanged declaration keeps its standing, a changed timing or path takes effect from the environment's next deploy (the schedule service PRD's environments statement), and a removed name ends its schedule with its run history kept. No submission fires a run (ADM-L0-07).

accounts is the application's end-user realms on the accounts service (SVC-L0-10), one per environment (PLD-L0-40), each created with its environment and deleted with it (PLD-L0-66).

issue_tracking is the application's space at the issue-tracking service (SVC-L0-19), one for both environments (PLD-L0-40), created at the first submission naming the kind with no space. The entry may name space, one account-kind space the account holds or { development, production } naming one per environment, and level, report or contribute, report where none is named, with space alone. level with no space is refused invalid_request naming space, a level outside the two level_invalid, a space the account cannot bind, an application's own among them, space_not_owned, and a standing pair's manifest naming space invalid_request naming the pair, each before any write. The issue service PRD's provisioning row states the act, the binding, the standing pairs, the egress gateway's route, and the space's deletion.

With space, the submission binds the application, or each environment, to the named space and creates nothing. An application bound to a chosen space moves to another space its later manifest names, the space it leaves standing. A later manifest naming no space keeps the chosen binding as it stands. An application holding its own space whose manifest names space is refused invalid_request before any write, its own space serving both environments until the application is deleted.

The kind vocabulary is closed at this revision and duplicates are refused. services means per-application provisioned services, so an application consuming account-grain surfaces alone declares the empty array, which is a statement, not an omission, its account-grain consumption visible in the account's own declarations. Hosting is not an entry: every admitted application is hosted, and a declaration that cannot be declined is not a declaration.

This paragraph qualifies the first paragraph's clause that push stands alone: a push entry may also name its providers, apns and fcm, whose configuration each submission records (PSH-L0-01). A second push entry is refused manifest_invalid at its path.

MAN-04: *Retired 2026-09-12 UTC.* The ai_purposes member leaves the manifest at Anthony's direction: no service read it, and the AI gateway whose purposes it carried was retired into the egress gateway. Keyed upstream declarations have their own manifest member, upstreams (EGW-L0-02), rather than growing this one.

MAN-05 (decided): health declares the application's health endpoint as an absolute HTTP path — / followed by non-whitespace — the endpoint supervision checks (SVC-L0-08). A path, not a URL: the host is the application's own managed address, and a manifest naming some other host's health would declare supervision of something Turn Zero does not run.

MAN-06 (decided): The manifest declares no environments. An application has one environment or two, its environment count the application's own, which create_environment and delete_environment change (PLD-L0-96). One manifest text serves every environment the application has; what an environment is, and what promotion between them means, is the platform and deployment PRD's. A manifest carrying an environments member is refused at submission with the slug environment_unsupported and the reason — an application's actions set its environments, never its manifest, and the member is removed from the manifest — before anything is provisioned (ADM-L0-08). The refusal is named rather than left to MAN-02's unknown-member failure so that the author of a manifest written against an earlier revision of this contract, which admitted the member, is told what to change.

MAN-07 (decided): region declares exactly one of the day-one values — usa, europe, uk, global (Q-144's list; what a region choice means is PLD-L0-22's). The enum is closed at this revision: a new region is a schema revision, never a free string, because an unavailable region must refuse before anything is provisioned (ADM-L0-08) and a string the format waves through defers that refusal to the worst possible moment.

MAN-08: *Retired 2026-08-17 UTC.* The update_channel member left the manifest with ADM-L0-01's amendment: no update service exists at launch and clients are the coding tool's work; a channel vocabulary returns only with a future distribution service, the backlog's territory.

MAN-09 (decided): egress declares the network allowlist: an array of entries, no duplicates, each an exact lowercase DNS hostname (api.stripe.com) or a host family written with one leading wildcard label (*.googleapis.com). An empty list declares no tunneled external destinations. In enforce mode those connections are refused; observe mode follows EGW-L0-17. The platform endpoints described in ADM-L0-03 are separate from this list.

A family admits every hostname below its labels at any depth — *.example.com admits api.example.com and a.b.example.com — and never the apex example.com, which is its own exact entry where it is reached. The wildcard stands only as the whole first label, followed by at least two labels, so *.com, *.*.example.com, a*.example.com, and a wildcard anywhere but first are refused. The grammar carries no schemes, ports, or address literals: tunneled connections are restricted to port 443 at the beta without inspecting their TLS or HTTP protocol (EGW-L0-12), and a destination's addresses are checked at establishment rather than declared (EGW-L0-13).

The member is the tunnel mode's declaration carrier (EGW-L0-11; CQ-172), read live and never injected at deploy. The control plane answers it to the tunnel seat at the seat's resolve of the application, and the seat's records classify an undeclared host against it. A keyed upstream stays declared through declare_upstream until A1 (EGW-L0-02).

MAN-10 (decided): audience declares exactly one boundary: {"kind": "public"}, {"kind": "invited"}, or {"kind": "workforce", "tenant": …}. {"kind": "invited"} is the invited audience of ADM-L0-05: gated by the serving router on the realm's session, it binds the application's end-user realms to invitation-only creation from the declaration, its invitations issued by the author (ACS-L0-08). {"kind": "workforce", "tenant": …} is one company's workforce, the tenant member a non-empty identity-provider tenant identifier whose interpretation is the provider's (Microsoft Entra ID's tenant id at this revision, ACS-L0-09).

The workforce kind was renamed from tenant so that the bare word keeps Turn Zero Cloud's own multi-tenancy sense (ADM-L0-10) and the directory sense stands qualified. The rename is on MAN-03's terms, with no alias: a manifest carrying the old value is refused at its next submission as the fourth shape it now is, and a recorded one is read as the workforce value and never as public (ADM-L0-05). One member, three shapes, no fourth: an audience the schema does not name is refused, not defaulted, because a defaulted audience is an exposure nobody declared.

The invited and workforce kinds may carry session_free_paths, the path prefixes the serving router lets through with no session, so a provider's callback reaches the application, which checks the caller's signature itself (ADM-L0-05). The list holds at most ten prefixes. Each starts with /, is not / alone, holds no whitespace and no .., and stands outside /__account/ and /__router/, the platform's own prefixes. A prefix covers the path equal to it and every path below it. The public kind carries no list, because it admits every request already. Submission refuses a list that breaks a rule by the rule's name, at the entry's own JSON path (MAN-12).

MAN-14: settings binds a stored secret to a setting the application's process reads. It is optional, one of the three members MAN-02 admits absent, and an object from a setting name to {"secret": "<stored name>"}, at most fifty entries. EGW-L0-02 owns the second, upstreams. ACS-L0-07 owns the third, realm. The setting name is an upper-case letter, then upper-case letters, digits, or underscores, ending in a letter or a digit, at most sixty-four characters. The secret is a custody name (SCRT-L0-01) stored at the application's scope, which the platform reads at each environment's own scope (SCRT-L0-08).

A setting name the platform reserves is refused manifest_invalid at the setting's own path (MAN-12). The platform reserves every name under TURNZERO_, APP_, HOSTING_, EGRESS_, ROUTER_, NODE_, or NPM_, and the names PORT, PATH, HOME, HTTPS_PROXY, HTTP_PROXY, and NO_PROXY. One rule holds the reserved names, applied at submission, in the deploy's and the promote's refusal orders, and when a redeploy or a rollback re-applies a binding (PLD-L0-63; PLD-L0-84). The member is optional where MAN-02's other members are required, because every manifest submitted before it would otherwise fail validation, and an absent member binds nothing. The packages member stays required, because its omission would read as a fact not yet known (MAN-13).

Five kinds of secret are never bound, each refused at submission before anything is recorded. A platform-minted name of any application of the account is refused platform_minted_name (SEC-L0-07), so no platform credential, database credential, or issue-tracking token reaches a process through a binding. A name an upstream declaration of the application names is refused setting_is_upstream_key, and declare_upstream refuses the reverse, a key a binding feeds, upstream_key_is_bound. So the gateway never gives an upstream's key to the application (EGW-L0-03).

A route credential of the application, at either environment scope, is refused as declare_upstream refuses it. A realm's work-account client secret or Apple signing key, or a name resting in the cell's realm vault, is refused name_bound_to_realm (ACS-L0-09). A push configuration's provider credential is refused name_bound_to_push. A name at the account scope or at another application's scope is refused setting_scope_refused, because a value stored at the account scope is applied only to a declared upstream's calls and a name never moves between scopes (SCRT-L0-08). The detail names the remedy, a new name stored at this application's scope.

The answer of submit_manifest carries one row per setting and environment the application has, naming the secret and whether it is stored at that environment's application scope. One name may stand at both environment scopes of one application, each with its own value (SCRT-L0-08), so development can bind a test value and production a live one. A name stored nowhere yet is admitted, and the rows say so.

A deploy or a promote reads each bound value at its environment's application scope solely to compose that environment's injected settings (SCRT-L0-09), and injects it as a secure setting of the binding's name. It holds each binding again to every rule above but the scope rule, and refuses setting_secret_missing where the name stands at no entry of that scope (PLD-L0-63). A value whose entry stands and whose store does not answer never reads as missing. It ends the act's row failed 502 bound_setting_unreadable before the compute apply, a deploy's, a promote's, a redeploy's, and a rollback's alike.

A redeploy re-applies the bindings its source row recorded, and a rollback those the latest production row of its version recorded (PLD-L0-84; PLD-L0-43). Neither reads the current manifest, and neither refuses for a binding a rule refuses or whose entry is gone, which it leaves out. A rotated value takes effect at the environment's next deploy or promote, and at a restart_application where the running copy already carries the binding (SCRT-L0-05). The answers of rotate_secret and list_secrets name the settings a stored name feeds.

The binding lives in the manifest because a setting the code reads is a declaration Turn Zero enforces, reviewed with the code and versioned with it as egress is (MAN-09). A member on store_secret would make the binding a custody fact that no review of the code reads, and a new action would offer nothing the manifest does not.

A bound name is refused both ways. configure_realm and configure_push refuse a name a binding feeds 409 name_bound_to_setting (ACS-L0-09; PSH-L0-01), and declare_upstream refuses it upstream_key_is_bound (EGW-L0-01). A binding feeds a name where the recorded manifest binds it, and where either environment's serving row or row in flight recorded it. Each refusal's detail names the setting and where it is bound: the recorded manifest, a running copy, or an act in flight. Each such action reads the bindings again after recording its route, and takes the route back and refuses where one now feeds the name. An act reads the routes again once its row records the bindings, refusing or leaving out a binding a route now names as the two paragraphs above state. So no interleaving makes a value a process reads or will read a route's credential or an upstream's key.

This paragraph qualifies the seventh paragraph's last sentence for rotate_secret. Its answer names, as restart_environment, the one environment whose application scope the rotation wrote where that environment's serving row binds the name, and says a restart_application of it applies the new value. A row in flight is never named, since a restart is refused while it runs (PLD-L0-84) and which value it applies depends on when it read its bindings. For a name at an application scope, the answer points to read_status's rotated_since_read, which answers such a row once it ends; where only such a row binds the name, the answer names no environment and still points there. An account-scope name names none and carries no pointer, since rotated_since_read reads a serving row's bindings and binding such a name is refused setting_scope_refused. So a rotation says which running copy still needs a restart.

This paragraph extends the paragraph above to rotate_secret's preparing form, a call naming no value (SEC-L0-19). Its answer carries next where the serving row of the environment whose application scope the call names binds the name: a restart_application call naming the application and that environment, to make once the answered line ends 0. The preparing call makes the read the rotation's own answer makes, so next names the environment that answer names as restart_environment. Where only a row in flight binds the name, at the account scope, and on a store_secret call, the answer carries no next.

submit_manifest and create_environment follow each realm's and push configuration's record with the bindings half of configure_realm's and configure_push's second read. Each credential a binding is read to feed is taken back where the record changed it, and the act is refused 409 name_bound_to_setting at the first one's path. Where a later credential's read or withdrawal fails, the refusal is answered, the failure recorded for the operator, and that credential stays as recorded until a repeat. The custody half is not run, since a manifest may name a credential not yet stored. A refused submission leaves its manifest recorded, its detail naming the realms or push configurations done and not. A submission whose store fails in this phase is answered store_unavailable with the same detail, nothing taken back. A route recorded after a submission's check is not read again: each later deploy and promote refuses a binding of its credential.

The check's format half

MAN-11 (decided): One schema admits both provenances. A generated manifest and a hand-written one validate against the same schema, and the format carries no member marking which it was — the check is the same check because the format gives it nothing to branch on. Provenance is ADM-L0-06's tier, held by Turn Zero Cloud about the application; a self-declared provenance field would be an honesty the format cannot verify.

MAN-12 (decided): A format refusal names what failed: validation reports the JSON path of every violation, so a malformed allowlist refuses as /egress/3 and a misspelled member as itself, rather than only a generic error. This is ADM-L0-08's named-refusal promise at the format layer; the runtime checks name their refusals on the same terms when they arrive.

MAN-13: The packages member lists one entry per library entry the application holds, each as its name and the version held (SPM-L0-50's rows; SPM-L0-49; Q-235). It is derived at each submission from the project's own record rather than kept beside it: the author copies each row's name and version from the folder manifest system/manifest.json. That folder manifest holds one row per vendored entry, written by the act that writes the files. What the rule forbids is a list kept by hand beside it, never that copy, because a second home for one fact goes stale further from the bytes.

API-L0-16 requires admission to use this member to refuse a deploy declaring a version whose compatibility window has closed, once the first-customer-release date activates that policy. That use is the reason the member is declared at all: the operated backend behind a package contract is Turn Zero Cloud's to run, and Turn Zero Cloud cannot keep every version of every backend alive forever. An application holding no library entry declares an empty list rather than omitting the member: MAN-02 requires it, and an omission would read as a fact not yet known where the truth is that there are none. The declaration and its format checks are implemented. Compatibility-window enforcement is not active during the beta while the first-customer-release date remains unset (API-L0-16).

Exact source Markdown

---
document: admission_manifest
prefix: MAN
---

# The Admission Manifest — Format Contract

## Purpose

This document defines the JSON format of the application manifest the admission PRD describes: its required fields, allowed values, and format errors. The JSON Schema at `schemas/manifest.schema.json` is maintained alongside this contract; neither file is generated from the other. A test in the platform's suite checks their agreement.

Runtime admission checks belong to the requirements that own the affected service, region, audience, and policy. A valid JSON document does not prove those runtime checks passed. MAN-01 states how the manifest reaches `submit_manifest`; account-side egress policy belongs to ADM-L0-04.

Requirements are numbered MAN-nn.

## The document

MAN-01 (decided): A manifest is one JSON document conforming to the schema, and it opens with its own contract revision: `manifest_version`, the integer `1` for this form. A manifest whose version is not a known revision is refused as malformed rather than best-effort-read, because a reader guessing at an unknown revision enforces something other than what the author declared. The manifest's home is a file in the application project — `manifest.json` at the project root — and the admitting act reads it from the `submit_manifest` request body: the customer's tool sends the file's content, and no path is fetched from anywhere.

MAN-02 (decided): The manifest's members are the six declarations ADM-L0-01 names — `services`, `health`, `region`, `egress`, `audience`, `packages` — and `manifest_version`, every one required, and the three optional declarations ADM-L0-01 names, `settings`, `upstreams`, and `realm`; nothing else is admitted. Membership changes by ADM-L0-01 amendment, the schema and citing tests changing in the same change. An unknown member fails validation instead of passing as inert, because a field the check ignores is a declaration the reader believes and Turn Zero does not enforce — the nothing-undeclared rule applied to the manifest itself.

One unknown member is refused by its own name rather than as unknown: an `environments` member is refused `environment_unsupported` with the remedy (MAN-06). It is named because an application's environments are the platform's, set by `create_environment` and `delete_environment` (PLD-L0-96), and the author of a manifest written against an earlier revision of this contract is told what to change. The `ai_purposes` member, which carried the retired AI gateway's purposes and which no service read, left the manifest with MAN-04's retirement. A manifest written against the earlier revision fails as an unknown member at that member's path (MAN-12), and the remedy is to delete the member.

The manifest carries no application identity: it declares what an application consumes and contains, and which application it binds to is the admitting action's (API-L0-01), so one manifest text can serve one application today and a fork tomorrow without editing.

The three optional members may be absent. The `settings` member is the stored secrets the application's process reads as named settings; a manifest that omits it binds no setting (MAN-14). The `upstreams` member is the keyed upstreams the application calls through the gateway; a manifest that omits it leaves its upstreams to `declare_upstream` (EGW-L0-02). The `realm` member is the sign-in configuration of the application's end-user realms; a manifest that omits it leaves that configuration to `configure_realm` (ACS-L0-07).

## The members

MAN-03 (decided): `services` declares the provisioned services the application consumes, by the catalog's own names (SVC-L0-01; SVC-L0-06). It is an array of entries, each `{"kind": …}`. The kinds `database`, `object_storage`, `email`, `accounts`, and `push` (SVC-L0-20) stand alone, and `issue_tracking` stands alone or carries a `space` and a `level`. `custom_domain` carries its `domain`, the manifest declaration SVC-L0-07 names. `schedule` carries its `schedules`.

`schedules` is a list of one to twenty-five declarations at the shape's cap, the plan's `schedule-count-limit` refused at submit by name. Each declaration is a `name`, a `cron`, and a `path`. The name is a lowercase letter followed by lowercase letters, digits, or underscores, with no hyphen, and is unique within the application. The cron is five fields in UTC, minute, hour, day of month, month, and day of week, each `*`, an integer, a range, a list, or a step. The schema refuses any other shape at its path, and the admitting act refuses a field out of range or an expression with no due time inside a year. The path is an absolute HTTP path on the application's own server in MAN-05's form, under neither reserved path prefix, `/__account/` (ACS-L0-04) nor `/__router/`. The schedule service PRD's declaration statement owns the bounds.

`schedule` is the recurring time-driven invocation service (SVC-L0-15), renamed from `scheduled_jobs` while no admitted manifest existed to carry the old kind. A `schedule` entry carrying no `schedules` is refused, a kind carrying no schedule declaring nothing. A resubmission converges the application's schedules to the entry. An unchanged declaration keeps its standing, a changed timing or path takes effect from the environment's next deploy (the schedule service PRD's environments statement), and a removed name ends its schedule with its run history kept. No submission fires a run (ADM-L0-07).

`accounts` is the application's end-user realms on the accounts service (SVC-L0-10), one per environment (PLD-L0-40), each created with its environment and deleted with it (PLD-L0-66).

`issue_tracking` is the application's space at the issue-tracking service (SVC-L0-19), one for both environments (PLD-L0-40), created at the first submission naming the kind with no `space`. The entry may name `space`, one `account`-kind space the account holds or `{ development, production }` naming one per environment, and `level`, `report` or `contribute`, `report` where none is named, with `space` alone. `level` with no `space` is refused `invalid_request` naming `space`, a level outside the two `level_invalid`, a space the account cannot bind, an application's own among them, `space_not_owned`, and a standing pair's manifest naming `space` `invalid_request` naming the pair, each before any write. The issue service PRD's provisioning row states the act, the binding, the standing pairs, the egress gateway's route, and the space's deletion.

With `space`, the submission binds the application, or each environment, to the named space and creates nothing. An application bound to a chosen space moves to another space its later manifest names, the space it leaves standing. A later manifest naming no `space` keeps the chosen binding as it stands. An application holding its own space whose manifest names `space` is refused `invalid_request` before any write, its own space serving both environments until the application is deleted.

The kind vocabulary is closed at this revision and duplicates are refused. `services` means per-application provisioned services, so an application consuming account-grain surfaces alone declares the empty array, which is a statement, not an omission, its account-grain consumption visible in the account's own declarations. Hosting is not an entry: every admitted application is hosted, and a declaration that cannot be declined is not a declaration.

This paragraph qualifies the first paragraph's clause that `push` stands alone: a `push` entry may also name its providers, `apns` and `fcm`, whose configuration each submission records (PSH-L0-01). A second `push` entry is refused `manifest_invalid` at its path.

MAN-04: *Retired 2026-09-12 UTC.* The ai_purposes member leaves the manifest at Anthony's direction: no service read it, and the AI gateway whose purposes it carried was retired into the egress gateway. Keyed upstream declarations have their own manifest member, `upstreams` (EGW-L0-02), rather than growing this one.

MAN-05 (decided): `health` declares the application's health endpoint as an absolute HTTP path — `/` followed by non-whitespace — the endpoint supervision checks (SVC-L0-08). A path, not a URL: the host is the application's own managed address, and a manifest naming some other host's health would declare supervision of something Turn Zero does not run.

MAN-06 (decided): The manifest declares no environments. An application has one environment or two, its environment count the application's own, which `create_environment` and `delete_environment` change (PLD-L0-96). One manifest text serves every environment the application has; what an environment is, and what promotion between them means, is the platform and deployment PRD's. A manifest carrying an `environments` member is refused at submission with the slug `environment_unsupported` and the reason — an application's actions set its environments, never its manifest, and the member is removed from the manifest — before anything is provisioned (ADM-L0-08). The refusal is named rather than left to MAN-02's unknown-member failure so that the author of a manifest written against an earlier revision of this contract, which admitted the member, is told what to change.

MAN-07 (decided): `region` declares exactly one of the day-one values — `usa`, `europe`, `uk`, `global` (Q-144's list; what a region choice means is PLD-L0-22's). The enum is closed at this revision: a new region is a schema revision, never a free string, because an unavailable region must refuse before anything is provisioned (ADM-L0-08) and a string the format waves through defers that refusal to the worst possible moment.

MAN-08: *Retired 2026-08-17 UTC.* The update_channel member left the manifest with ADM-L0-01's amendment: no update service exists at launch and clients are the coding tool's work; a channel vocabulary returns only with a future distribution service, the backlog's territory.

MAN-09 (decided): `egress` declares the network allowlist: an array of entries, no duplicates, each an exact lowercase DNS hostname (`api.stripe.com`) or a host family written with one leading wildcard label (`*.googleapis.com`). An empty list declares no tunneled external destinations. In enforce mode those connections are refused; observe mode follows EGW-L0-17. The platform endpoints described in ADM-L0-03 are separate from this list.

A family admits every hostname below its labels at any depth — `*.example.com` admits `api.example.com` and `a.b.example.com` — and never the apex `example.com`, which is its own exact entry where it is reached. The wildcard stands only as the whole first label, followed by at least two labels, so `*.com`, `*.*.example.com`, `a*.example.com`, and a wildcard anywhere but first are refused. The grammar carries no schemes, ports, or address literals: tunneled connections are restricted to port 443 at the beta without inspecting their TLS or HTTP protocol (EGW-L0-12), and a destination's addresses are checked at establishment rather than declared (EGW-L0-13).

The member is the tunnel mode's declaration carrier (EGW-L0-11; CQ-172), read live and never injected at deploy. The control plane answers it to the tunnel seat at the seat's resolve of the application, and the seat's records classify an undeclared host against it. A keyed upstream stays declared through `declare_upstream` until A1 (EGW-L0-02).

MAN-10 (decided): `audience` declares exactly one boundary: `{"kind": "public"}`, `{"kind": "invited"}`, or `{"kind": "workforce", "tenant": …}`. `{"kind": "invited"}` is the invited audience of ADM-L0-05: gated by the serving router on the realm's session, it binds the application's end-user realms to invitation-only creation from the declaration, its invitations issued by the author (ACS-L0-08). `{"kind": "workforce", "tenant": …}` is one company's workforce, the `tenant` member a non-empty identity-provider tenant identifier whose interpretation is the provider's (Microsoft Entra ID's tenant id at this revision, ACS-L0-09).

The `workforce` kind was renamed from `tenant` so that the bare word keeps Turn Zero Cloud's own multi-tenancy sense (ADM-L0-10) and the directory sense stands qualified. The rename is on MAN-03's terms, with no alias: a manifest carrying the old value is refused at its next submission as the fourth shape it now is, and a recorded one is read as the workforce value and never as public (ADM-L0-05). One member, three shapes, no fourth: an audience the schema does not name is refused, not defaulted, because a defaulted audience is an exposure nobody declared.

The invited and workforce kinds may carry `session_free_paths`, the path prefixes the serving router lets through with no session, so a provider's callback reaches the application, which checks the caller's signature itself (ADM-L0-05). The list holds at most ten prefixes. Each starts with `/`, is not `/` alone, holds no whitespace and no `..`, and stands outside `/__account/` and `/__router/`, the platform's own prefixes. A prefix covers the path equal to it and every path below it. The public kind carries no list, because it admits every request already. Submission refuses a list that breaks a rule by the rule's name, at the entry's own JSON path (MAN-12).

MAN-14: `settings` binds a stored secret to a setting the application's process reads. It is optional, one of the three members MAN-02 admits absent, and an object from a setting name to `{"secret": "<stored name>"}`, at most fifty entries. EGW-L0-02 owns the second, `upstreams`. ACS-L0-07 owns the third, `realm`. The setting name is an upper-case letter, then upper-case letters, digits, or underscores, ending in a letter or a digit, at most sixty-four characters. The secret is a custody name (SCRT-L0-01) stored at the application's scope, which the platform reads at each environment's own scope (SCRT-L0-08).

A setting name the platform reserves is refused `manifest_invalid` at the setting's own path (MAN-12). The platform reserves every name under `TURNZERO_`, `APP_`, `HOSTING_`, `EGRESS_`, `ROUTER_`, `NODE_`, or `NPM_`, and the names `PORT`, `PATH`, `HOME`, `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY`. One rule holds the reserved names, applied at submission, in the deploy's and the promote's refusal orders, and when a redeploy or a rollback re-applies a binding (PLD-L0-63; PLD-L0-84). The member is optional where MAN-02's other members are required, because every manifest submitted before it would otherwise fail validation, and an absent member binds nothing. The `packages` member stays required, because its omission would read as a fact not yet known (MAN-13).

Five kinds of secret are never bound, each refused at submission before anything is recorded. A platform-minted name of any application of the account is refused `platform_minted_name` (SEC-L0-07), so no platform credential, database credential, or issue-tracking token reaches a process through a binding. A name an upstream declaration of the application names is refused `setting_is_upstream_key`, and `declare_upstream` refuses the reverse, a key a binding feeds, `upstream_key_is_bound`. So the gateway never gives an upstream's key to the application (EGW-L0-03).

A route credential of the application, at either environment scope, is refused as `declare_upstream` refuses it. A realm's work-account client secret or Apple signing key, or a name resting in the cell's realm vault, is refused `name_bound_to_realm` (ACS-L0-09). A push configuration's provider credential is refused `name_bound_to_push`. A name at the account scope or at another application's scope is refused `setting_scope_refused`, because a value stored at the account scope is applied only to a declared upstream's calls and a name never moves between scopes (SCRT-L0-08). The detail names the remedy, a new name stored at this application's scope.

The answer of `submit_manifest` carries one row per setting and environment the application has, naming the secret and whether it is `stored` at that environment's application scope. One name may stand at both environment scopes of one application, each with its own value (SCRT-L0-08), so development can bind a test value and production a live one. A name stored nowhere yet is admitted, and the rows say so.

A deploy or a promote reads each bound value at its environment's application scope solely to compose that environment's injected settings (SCRT-L0-09), and injects it as a secure setting of the binding's name. It holds each binding again to every rule above but the scope rule, and refuses `setting_secret_missing` where the name stands at no entry of that scope (PLD-L0-63). A value whose entry stands and whose store does not answer never reads as missing. It ends the act's row `failed` 502 `bound_setting_unreadable` before the compute apply, a deploy's, a promote's, a redeploy's, and a rollback's alike.

A redeploy re-applies the bindings its source row recorded, and a rollback those the latest production row of its version recorded (PLD-L0-84; PLD-L0-43). Neither reads the current manifest, and neither refuses for a binding a rule refuses or whose entry is gone, which it leaves out. A rotated value takes effect at the environment's next deploy or promote, and at a `restart_application` where the running copy already carries the binding (SCRT-L0-05). The answers of `rotate_secret` and `list_secrets` name the settings a stored name feeds.

The binding lives in the manifest because a setting the code reads is a declaration Turn Zero enforces, reviewed with the code and versioned with it as `egress` is (MAN-09). A member on `store_secret` would make the binding a custody fact that no review of the code reads, and a new action would offer nothing the manifest does not.

A bound name is refused both ways. `configure_realm` and `configure_push` refuse a name a binding feeds 409 `name_bound_to_setting` (ACS-L0-09; PSH-L0-01), and `declare_upstream` refuses it `upstream_key_is_bound` (EGW-L0-01). A binding feeds a name where the recorded manifest binds it, and where either environment's serving row or row in flight recorded it. Each refusal's detail names the setting and where it is bound: the recorded manifest, a running copy, or an act in flight. Each such action reads the bindings again after recording its route, and takes the route back and refuses where one now feeds the name. An act reads the routes again once its row records the bindings, refusing or leaving out a binding a route now names as the two paragraphs above state. So no interleaving makes a value a process reads or will read a route's credential or an upstream's key.

This paragraph qualifies the seventh paragraph's last sentence for `rotate_secret`. Its answer names, as `restart_environment`, the one environment whose application scope the rotation wrote where that environment's serving row binds the name, and says a `restart_application` of it applies the new value. A row in flight is never named, since a restart is refused while it runs (PLD-L0-84) and which value it applies depends on when it read its bindings. For a name at an application scope, the answer points to `read_status`'s `rotated_since_read`, which answers such a row once it ends; where only such a row binds the name, the answer names no environment and still points there. An account-scope name names none and carries no pointer, since `rotated_since_read` reads a serving row's bindings and binding such a name is refused `setting_scope_refused`. So a rotation says which running copy still needs a restart.

This paragraph extends the paragraph above to `rotate_secret`'s preparing form, a call naming no value (SEC-L0-19). Its answer carries `next` where the serving row of the environment whose application scope the call names binds the name: a `restart_application` call naming the application and that environment, to make once the answered line ends 0. The preparing call makes the read the rotation's own answer makes, so `next` names the environment that answer names as `restart_environment`. Where only a row in flight binds the name, at the account scope, and on a `store_secret` call, the answer carries no `next`.

`submit_manifest` and `create_environment` follow each realm's and push configuration's record with the bindings half of `configure_realm`'s and `configure_push`'s second read. Each credential a binding is read to feed is taken back where the record changed it, and the act is refused 409 `name_bound_to_setting` at the first one's path. Where a later credential's read or withdrawal fails, the refusal is answered, the failure recorded for the operator, and that credential stays as recorded until a repeat. The custody half is not run, since a manifest may name a credential not yet stored. A refused submission leaves its manifest recorded, its detail naming the realms or push configurations done and not. A submission whose store fails in this phase is answered `store_unavailable` with the same detail, nothing taken back. A route recorded after a submission's check is not read again: each later deploy and promote refuses a binding of its credential.

## The check's format half

MAN-11 (decided): One schema admits both provenances. A generated manifest and a hand-written one validate against the same schema, and the format carries no member marking which it was — the check is the same check because the format gives it nothing to branch on. Provenance is ADM-L0-06's tier, held by Turn Zero Cloud about the application; a self-declared provenance field would be an honesty the format cannot verify.

MAN-12 (decided): A format refusal names what failed: validation reports the JSON path of every violation, so a malformed allowlist refuses as `/egress/3` and a misspelled member as itself, rather than only a generic error. This is ADM-L0-08's named-refusal promise at the format layer; the runtime checks name their refusals on the same terms when they arrive.

MAN-13: The `packages` member lists one entry per library entry the application holds, each as its name and the version held (SPM-L0-50's rows; SPM-L0-49; Q-235). It is **derived at each submission from the project's own record rather than kept beside it**: the author copies each row's name and version from the folder manifest `system/manifest.json`. That folder manifest holds one row per vendored entry, written by the act that writes the files. What the rule forbids is a list kept by hand beside it, never that copy, because a second home for one fact goes stale further from the bytes.

API-L0-16 requires admission to use this member to refuse a deploy declaring a version whose compatibility window has closed, once the first-customer-release date activates that policy. That use is the reason the member is declared at all: the operated backend behind a package contract is Turn Zero Cloud's to run, and Turn Zero Cloud cannot keep every version of every backend alive forever. An application holding no library entry declares an empty list rather than omitting the member: MAN-02 requires it, and an omission would read as a fact not yet known where the truth is that there are none. The declaration and its format checks are implemented. Compatibility-window enforcement is not active during the beta while the first-customer-release date remains unset (API-L0-16).