The manifest
An application manifest is a JSON document that declares the application's services, network access, and other deployment requirements. Generated and hand-written manifests use the same schema. Ask your tool to read the context://manifest_schema resource before it submits with submit_manifest. A manifest that fails validation is refused with the JSON path of each violation.
The members
Seven top-level members are required. Three more, settings, upstreams, and realm, are optional, and any other top-level member is refused. The manifest declares no environments: an application has production, and development where you turn it on with create_environment. A manifest with an environments member is refused environment_unsupported.
| Member | What it declares |
|---|---|
manifest_version |
The version of the manifest format, the integer 1. An unknown version is refused. |
services |
The provisioned services the application uses, each an object with a kind. The list after this table gives the members each kind takes. An empty array declares no services. Hosting is not an entry, because every accepted application is hosted. |
health |
The health endpoint, an absolute path on the application's own address. The platform checks it at every deploy, promote, and platform redeploy. A deploy to an environment that serves no version yet is refused health_path_unserved where no source file of the zip names the path's last segment. |
region |
usa is the only value available today. The schema also lists europe, uk, and global, but submission refuses them as region_unavailable. The global value makes no promise about where data is kept. |
egress |
The outbound hosts the application may reach: exact lowercase hostnames and *.example.com host families. An empty array declares no external hosts. In enforce mode the egress proxy refuses undeclared destinations; in observe mode it can allow and record them. See Egress firewall and request limits. |
audience |
Who may reach the application: {"kind": "public"}, {"kind": "invited"}, or {"kind": "workforce", "tenant": …}. The invited and workforce kinds may also list session_free_paths. See The audience kinds. |
packages |
The library entries the application includes, each as a name and a version. The version is null for a font family and for the library's own requirements entry, library/prd. Use the library says how your tool copies it from system/manifest.json at each submission. An application with no entries declares an empty array. |
settings |
Optional. Stored secrets the application's code reads as named settings, as an object from a setting name to {"secret": "<stored name>"}, at most fifty entries. Each deploy and promote injects the value stored for its environment. See Bound settings. |
upstreams |
Optional. The application programming interfaces (APIs) the application calls with a stored key through the platform's gateway, as an object from an upstream's name to its declaration, at most fifty entries. Each submission declares them for the application. See Upstreams in the manifest. |
realm |
Optional. The sign-in setup of both end-user realms: sign_in_methods, creation, entra, and apple, as configure_realm takes them. See Sign-in and push in the manifest. |
Each kind of services entry takes these members besides its kind:
database,object_storage,accounts, andemailtake no other member.pushtakes only its providers.issue_trackingwith no other member gives the application one issue-tracking space for both environments. It may instead give aspaceyour account owns, one identifier or{ "development": ..., "production": ... }, with alevelofreportorcontribute. The application is then bound to that space, and nothing is created.custom_domaintakes itsdomain.scheduletakes itsschedules: one to twenty-five declarations, each aname, a five-fieldcronin UTC, and an absolutepathon the application's own server. The path may not be thehealthpath or fall under/__account/or/__router/. Such a declaration is refusedmanifest_invalidat its own JSON path.
The database, object storage, and accounts services run today. The schema accepts email and custom_domain, and declaring one provisions nothing. schedule runs today and requires its schedules array; a bare schedule entry is refused. push runs today, and the declaration allows the push configuration and the push routes. Its providers are named in the entry itself (Sign-in and push in the manifest) or configured afterwards with configure_push (Send push notifications).
The audience kinds
- Public. Anyone can reach the application.
- Invited. Every request needs an end-user session. The application's realms become invitation-only: a first sign-in without an invitation from
issue_invitationcreates no user, whatever the realm'screationsetting is. - Workforce. Only one company's staff can reach the application. The
tenantmember is the identifier (a GUID) of the company's work-account tenant. The realm'sentrasign-in method is configured against that tenant, as Manage end users describes. Only that tenant's signed-in users reach the application.
Under invited and workforce, a request without an end-user session is refused. There are two exceptions: the platform's own scheduled runs, and the paths the audience lists in session_free_paths. A payment provider's webhook, or any other service's callback, has no session, so list its path there to receive it. The platform checks nothing about the sender on a listed path, so the route checks each caller itself, by the provider's signature. Add sign-in to your app gives the rules for the list.
Bound settings
The settings member binds a stored secret to a setting the application's code reads. The binding names the secret, never its value, and it is reviewed and versioned with the code. A setting name is an upper-case letter, then upper-case letters, digits, or underscores, ending in a letter or a digit.
Most outbound API keys belong with the egress gateway instead, which adds the key to each call and never gives it to the application. A bound value is in the container. A replacement takes effect at the environment's next deploy or promote, or at a restart where the running copy already has the binding. Store a secret compares the two.
A binding never names a setting name the platform reserves, a name the platform created, an upstream's key, or a sign-in method's or push provider's credential. Author the manifest lists each refusal.
Upstreams in the manifest
An upstream is an outside API the application calls through the platform's gateway, which adds the stored key on the way. The upstreams member declares them with the code, in place of a declare_upstream call for each. Each entry takes what declare_upstream takes except application, because the manifest's application is the one it is submitted for.
With its upstreams in the manifest, an application is described by one file. Re-creating it, or copying it into another account, takes the manifest, a store_secret for each key, and a deploy.
Upstream names are unique within an account. A copy beside the original in the same account gives its upstreams names of their own. A name another application already uses is refused, and the refusal names that application.
While the member lists an upstream, the manifest controls it, and declare_upstream refuses to change it. An upstream the member does not list can still be changed with declare_upstream. No submission ends an upstream, so a running version that calls it keeps working. undeclare_upstream ends one once the member no longer lists it. Author the manifest shows the member and its refusals.
Sign-in and push in the manifest
The realm member declares the sign-in setup that is the same in every environment: the sign-in methods, who may create an account, and the entra and apple route members. A push entry in services may also name its providers, apns and fcm. Each credential member names a stored secret, never its value.
With these members and upstreams, re-creating an application, or copying it into another account, takes the manifest, a store_secret for each credential, and a deploy. No configure_realm or configure_push call is needed.
While the manifest names a field, it controls that field, and configure_realm or configure_push refuses to change it. The settings that differ by environment stay with the actions: a realm's limits, session lengths, invitation days, and native clients, and Apple's push gateway. Author the manifest shows the members.
What submitting does
submit_manifest records the manifest for an application, then provisions the implemented services it declares:
- Database. The first database declaration creates the development database and its role at submission, on every application, for local runs. While the manifest declares the kind, the first deploy to production creates the production database and role on one environment, and the first promote creates them on two.
- Accounts. The first accounts declaration creates an end-user realm for each environment the application has: production's alone on one environment. The production realm stays until the application is deleted. A development realm is created by
create_environmentor by a submission while development is on, and ends withdelete_environmentor with the application. - Credentials. The first submission creates two development values: the development platform credential, and the development database credential where the manifest declares the database kind. No production credential is ever returned.
- Bound settings. A
settingsmember provisions nothing. The result'ssettingsrows say, per setting and environment the application has, whether the bound name is stored there yet. - Upstreams. An
upstreamsmember declares each upstream, asdeclare_upstreamwould, from that moment. A key not stored yet is accepted. The result'supstreamsrows say, per upstream and environment, whether its key is stored there. An entry that drops its key setting ends the egress keys running copies hold, andegress_keys_endedcounts them. Adetailline names each environment that lost one and the way back: restore the entry'ssettings.key, submit again, then callrestart_applicationthere. - Sign-in and push. A
realmmember configures the realm of each environment the application has, and apushentry's providers configure each of those environments, as the two actions would. On one environment that is production alone, andcreate_environmentconfigures development when it adds it. A credential not stored yet is accepted. The result'sdetailnames each one not stored yet, with the environment where only one environment lacks it.
How your tool receives the two development values depends on how it calls:
- On the Hypertext Transfer Protocol (HTTP) API, a submission that names no
local_runreturns each value once, for your local environment file. - Through the Model Context Protocol (MCP) tool, the result withholds both values. So does an HTTP submission that names
local_run, because the line it returns creates both again. - A submission that names
local_run: truereturns the provision line, which writes the settings a local run needs into your environment file. Through the MCP tool, a submission with nolocal_runreturnsprovisioning.next, which says to submit again naming it.
Submission also updates schedule declarations. A declaration fires in an environment once that environment has a deploy or promote made at or after the declaration. On one environment that is a deploy to production. On two it is a deploy to development or a promote to production. It does not fire while its environment is halted. Run scheduled work covers the rest.
The platform validates the whole manifest before it provisions anything, but provisioning itself can stop part way. A failed database setup can leave the manifest recorded and the setup partly done. The refusal says how to retry; Author the manifest explains this case.
Changing the manifest
Change the manifest through submit_manifest, and send the whole document. A submission replaces the recorded manifest, so a member you leave out removes that declaration. Adding a service or an egress entry changes what the application depends on or can reach. A deploy reads the recorded manifest and does not change it. The manifest-author skill writes or changes a manifest against the published schema, and the add-service skill adds a service declaration.
Removing a declaration deletes nothing:
- A removed database, with its role, remains until
delete_environmentremoves the development database ordelete_applicationremoves both. - A removed accounts declaration leaves each realm in place on the same terms.
- A removed schedule declaration runs no more, and its run records are kept.
- A removed upstream entry stays declared, and
declare_upstreamcan change it again. It ends when you callundeclare_upstream, or when the application or your account is deleted. Promote the version that no longer calls it first: within a short cache interval, its calls are refused in both environments. - A removed
realmfield orpushprovider keeps its configuration, andconfigure_realmorconfigure_pushcan change it again.
A binding added or removed takes effect at the environment's next deploy or promote. A restart re-applies the bindings the running copy was started with, never the current manifest's. A rollback re-applies the bindings its version last had in production, or those its deploy recorded where production never ran it.
The platform gives a deployed copy what the environment has, not what the manifest declares. While a database remains, each deploy or promote supplies the connection string of the environment it reaches. While a realm remains, the deploy and the promote still supply its public keys. A deploy to production or a promote creates the production database only while the manifest declares the database kind. One made after the kind is declared again creates it.
A resubmission that changes nothing records the document. If the development database and the development platform credential already exist, it provisions nothing new and creates no credential. To create new development credentials, your tool submits again naming local_run and runs the provision line the response returns. The line calls rotate_secret on the development scope.
Provenance
The platform does not record where an application's code came from. Today's workflow uploads an artifact you build yourself, and no result reports its origin. The manifest has no member for it: generated and hand-written manifests pass the same validation and get the same access and network controls.
Related
- Author the manifest — the how-to: writing, submitting, reading a refusal, and scheduled work.
- Applications and environments — the environments the manifest's services are provisioned for.
- Egress firewall and request limits — what the
egressmember controls, and the observe and enforce modes. - Manage end users — what the
audiencemember and the accounts service do for an application's users. - Use the library — the file the
packagesmember is copied from. - Glossary — the terms used on this page.