Every app has two parts. The App Definition says what the app is — you author it, and the
compiler consumes it. The App Contract says what the app offers — it is compiled, and
everything outside the app reads it: other apps, agents, connectors, the catalog.The manifest is not the contract. The manifest serves the runtime and may change shape whenever the
compiler wants. The contract serves everything outside, and its stability is a promise.
cordango build # writes contract.json beside app.jsoncordango discover # read every app's contract, here and on your instance
The contract is compiled locally and needs nothing. Reading the contracts of apps installed on an
instance is the part that needs one.
Platform features need a Cordango workspace.Sign up here and create one in a few minutes.
What is in it
identity key, name, version, hashespurpose summary + duties ← authoredentities keys, labels, fields and their TYPESdependencies the apps this one builds on, and how we knowevents what it announcesactions what it can be asked to dorules what an action will refuse
Everything is derived from the definition except purpose and uses, which are in the definition
because no compiler can work them out.
purpose — why the app exists
Nothing in a list of entities says whether they are there to run a sales pipeline or to record its
aftermath. That is what purpose is for.
purpose: summary: Owns the request to buy something — what is wanted, what it costs, who agreed. duties: - owns purchase requests, their line items and their quotes - routes approval by amount, and refuses to let somebody approve their own request - records what was actually bought, which is rarely the estimate
A duty is a claim other apps may rely on, so state what this app owns, never what it merely
displays. “Shows the budget” is not a duty. “Owns committed spend against a line” is.
uses — the apps you build on
Declared intent, stated once, before any field points anywhere.
uses: - app: core_organizations entities: [organization] why: a vendor is the same company record the whole workspace uses - app: budget_tracker entities: [budget_line] why: an approval commits against the line the request named
The compiler never writes into uses. A reference to an app you did not declare is reported to you,
not quietly added:
note: 'budget_tracker' is referenced by 'spend_entry.budget_line' but is not declared in `uses` declare it: uses: [{ app: budget_tracker, entities: [budget_line] }]
The platform directory (targetApp: platform) is never listed. Every app has it, so declaring it
would be noise on every definition in existence.
events — three kinds, and they are not the same
Kind
When
Named
record.created / .updated / .deleted
every write
<entity>.created
process.state_entered
a governed status field moved
<entity>.<state>
command.emitted
a command announced a name it declares in emits
whatever you called it
Every write already announces the first kind, and a command that moves a process state already
announces the second. So only declare emits when the domain word differs from the state key:
transitions: mark_purchased: to: purchased action: emits: - purchase.completed # "completed" says more than "purchased"
An emitted name may be announced by one command. If three transitions all reach approved, none
of them may claim purchase.approved — a name that identifies three things identifies nothing.
Subscribe to the state instead, which the runtime announces however the record got there.
rules — what an action will refuse
Every rule carries the fact it asserts, so a caller can tell whether it will pass before it tries: a
required field, a guard’s condition, the states a transition may run from.
Nothing is published that the runtime does not do
Every event kind listed is one the runtime actually emits. Every rule is one that actually refuses a
write. A contract listing an event nobody emits is a promise that fails silently in somebody else’s
app, which is worse than no contract at all.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Cordango","description":"Build complete business applications from a definition you own.","colors":{"primary":"#1D4ED8","light":"#3B6BF0","dark":"#1D4ED8"},"logo":{"light":"https://mintcdn.com/cordango/Fb6tWISooksDFX10/logo-light.png?fit=max\u0026auto=format\u0026n=Fb6tWISooksDFX10\u0026q=85\u0026s=95a8ad3ae8faf04b6053814a2a2fcea0","dark":"https://mintcdn.com/cordango/Fb6tWISooksDFX10/logo-dark.png?fit=max\u0026auto=format\u0026n=Fb6tWISooksDFX10\u0026q=85\u0026s=5f58c21c2b6c3b5b2cbc7bdc7027a397","href":"https://cordango.com"},"favicon":"https://mintcdn.com/cordango/rEsfB4Nx_N_Ej8W4/favicon.svg?fit=max\u0026auto=format\u0026n=rEsfB4Nx_N_Ej8W4\u0026q=85\u0026s=93e401d727f79eb83c91478d606797eb","navbar":{"links":[{"href":"https://cordango.com","label":"Homepage"},{"href":"https://github.com/cordango/cordango","label":"GitHub"}]},"footer":{"socials":{"website":"https://cordango.com","github":"https://github.com/cordango"}},"seo":{"metatags":{"canonical":"https://docs.cordango.com"}},"integrations":{"ga4":{"measurementId":"G-SCPVJ9QFG6"}},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"cordango","hasAudioNarration":false,"actualSubdomain":"cordango","customDomains":["docs.cordango.com"],"gitSource":{"type":"github","owner":"cordango","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ac28fd732cf889e79145ac6","clientVersion":"0.0.4143","searchFilterCounts":[{"language":"default","tag":"Documentation","count":23},{"language":"default","tag":"Concepts","count":9},{"language":"default","tag":"CLI","count":8},{"language":"default","tag":"API reference","count":6},{"language":"default","tag":"Guides","count":6},{"language":"default","tag":"MCP","count":6},{"language":"default","tag":"Quickstart with an AI agent","count":5},{"language":"default","tag":"Get started","count":2},{"language":"default","tag":"Security","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"concepts/app-contract","slug":"/concepts/app-contract","pageMetadata":{"title":"App Contract","description":"What an app offers, compiled beside what it is.","href":"/concepts/app-contract"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"What an app offers, compiled beside what it is.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,..._provideComponents(),...props.components},{CodeBlock,Heading,Note,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Every app has two parts. The `,_jsx(_components.strong,{children:`App Definition`}),` says what the app `,_jsx(_components.em,{children:`is`}),` — you author it, and the\ncompiler consumes it. The `,_jsx(_components.strong,{children:`App Contract`}),` says what the app `,_jsx(_components.em,{children:`offers`}),` — it is compiled, and\neverything outside the app reads it: other apps, agents, connectors, the catalog.`]}),`\n`,_jsx(_components.p,{children:`The manifest is not the contract. The manifest serves the runtime and may change shape whenever the\ncompiler wants. The contract serves everything outside, and its stability is a promise.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`cordango`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # writes contract.json beside app.json`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`cordango`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` discover`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # read every app's contract, here and on your instance`})]}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`The contract is compiled locally and needs nothing. Reading the contracts of apps installed on an\ninstance is the part that needs one.`}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Platform features need a Cordango workspace.`}),`\n`,_jsx(_components.a,{href:`https://www.cordango.com/start/`,children:`Sign up here`}),` and create one in a few minutes.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`what-is-in-it`,children:`What is in it`}),`\n`,_jsx(CodeBlock,{numberOfLines:`8`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`8`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`identity key, name, version, hashes`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`purpose summary + duties ← authored`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`entities keys, labels, fields and their TYPES`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`dependencies the apps this one builds on, and how we know`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`events what it announces`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`actions what it can be asked to do`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`rules what an action will refuse`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`Everything is derived from the definition except `,_jsx(_components.code,{children:`purpose`}),` and `,_jsx(_components.code,{children:`uses`}),`, which are in the definition\nbecause no compiler can work them out.`]}),`\n`,_jsx(Heading,{level:`2`,id:`purpose-—-why-the-app-exists`,children:`purpose — why the app exists`}),`\n`,_jsxs(_components.p,{children:[`Nothing in a list of entities says whether they are there to run a sales pipeline or to record its\naftermath. That is what `,_jsx(_components.code,{children:`purpose`}),` is for.`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`6`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`purpose`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` summary`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`Owns the request to buy something — what is wanted, what it costs, who agreed.`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` duties`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`owns purchase requests, their line items and their quotes`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`routes approval by amount, and refuses to let somebody approve their own request`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`records what was actually bought, which is rarely the estimate`})]}),`\n`]})})}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`A duty is a claim other apps may rely on, so state what this app `,_jsx(_components.strong,{children:`owns`}),`, never what it merely\ndisplays. “Shows the budget” is not a duty. “Owns committed spend against a line” is.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`uses-—-the-apps-you-build-on`,children:`uses — the apps you build on`}),`\n`,_jsx(_components.p,{children:`Declared intent, stated once, before any field points anywhere.`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`7`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`7`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`uses`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`app`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`core_organizations`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` entities`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`organization`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` why`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`a vendor is the same company record the whole workspace uses`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`app`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`budget_tracker`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` entities`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`budget_line`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` why`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`an approval commits against the line the request named`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The compiler never writes into `,_jsx(_components.code,{children:`uses`}),`. A reference to an app you did not declare is reported to you,\nnot quietly added:`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`3`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`3`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:\"note: 'budget_tracker' is referenced by 'spend_entry.budget_line' but is not declared in `uses`\"})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` declare it: uses: [{ app: budget_tracker, entities: [budget_line] }]`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`The platform directory (`,_jsx(_components.code,{children:`targetApp: platform`}),`) is never listed. Every app has it, so declaring it\nwould be noise on every definition in existence.`]}),`\n`,_jsx(Heading,{level:`2`,id:`events-—-three-kinds-and-they-are-not-the-same`,children:`events — three kinds, and they are not the same`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Kind`}),_jsx(_components.th,{children:`When`}),_jsx(_components.th,{children:`Named`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsxs(_components.td,{children:[_jsx(_components.code,{children:`record.created`}),` / `,_jsx(_components.code,{children:`.updated`}),` / `,_jsx(_components.code,{children:`.deleted`})]}),_jsx(_components.td,{children:`every write`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`\u003centity>.created`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`process.state_entered`})}),_jsx(_components.td,{children:`a governed status field moved`}),_jsx(_components.td,{children:_jsx(_components.code,{children:`\u003centity>.\u003cstate>`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`command.emitted`})}),_jsxs(_components.td,{children:[`a command announced a name it declares in `,_jsx(_components.code,{children:`emits`})]}),_jsx(_components.td,{children:`whatever you called it`})]})]})]}),`\n`,_jsxs(_components.p,{children:[`Every write already announces the first kind, and a command that moves a process state already\nannounces the second. So only declare `,_jsx(_components.code,{children:`emits`}),` when the domain word differs from the state key:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`6`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`transitions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` mark_purchased`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` to`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`purchased`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` action`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` emits`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`purchase.completed`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # \"completed\" says more than \"purchased\"`})]}),`\n`]})})}),`\n`,_jsx(Warning,{children:_jsxs(_components.p,{children:[`An emitted name may be announced by `,_jsx(_components.strong,{children:`one`}),` command. If three transitions all reach `,_jsx(_components.code,{children:`approved`}),`, none\nof them may claim `,_jsx(_components.code,{children:`purchase.approved`}),` — a name that identifies three things identifies nothing.\nSubscribe to the state instead, which the runtime announces however the record got there.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`rules-—-what-an-action-will-refuse`,children:`rules — what an action will refuse`}),`\n`,_jsx(_components.p,{children:`Every rule carries the fact it asserts, so a caller can tell whether it will pass before it tries: a\nrequired field, a guard’s condition, the states a transition may run from.`}),`\n`,_jsx(Heading,{level:`2`,id:`nothing-is-published-that-the-runtime-does-not-do`,children:`Nothing is published that the runtime does not do`}),`\n`,_jsx(_components.p,{children:`Every event kind listed is one the runtime actually emits. Every rule is one that actually refuses a\nwrite. A contract listing an event nobody emits is a promise that fails silently in somebody else’s\napp, which is worse than no contract at all.`})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"App Contract","description":"What an app offers, compiled beside what it is.","href":"/concepts/app-contract"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"What is in it","slug":"what-is-in-it","depth":2,"children":[]},{"title":"purpose — why the app exists","slug":"purpose-—-why-the-app-exists","depth":2,"children":[]},{"title":"uses — the apps you build on","slug":"uses-—-the-apps-you-build-on","depth":2,"children":[]},{"title":"events — three kinds, and they are not the same","slug":"events-—-three-kinds-and-they-are-not-the-same","depth":2,"children":[]},{"title":"rules — what an action will refuse","slug":"rules-—-what-an-action-will-refuse","depth":2,"children":[]},{"title":"Nothing is published that the runtime does not do","slug":"nothing-is-published-that-the-runtime-does-not-do","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"cordango","siteName":"Cordango","title":"App Contract - Cordango","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-04T17:41:47.016Z","originalFileLocation":"concepts/app-contract.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"What an app offers, compiled beside what it is.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Cordango\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"App Contract - Cordango\">\u003cmeta data-mint-head property=\"og:description\" content=\"What an app offers, compiled beside what it is.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Cordango\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.cordango.com/concepts/app-contract\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://cordango.mintlify.site/_mintlify/api/og/v2?division=Concepts\u0026amp;title=App+Contract\u0026amp;description=What+an+app+offers%2C+compiled+beside+what+it+is.\u0026amp;theme=726d7292d81e7ed559f5aead\u0026amp;signature=7085531a97b56ce67e3282e4419e560bf275b6cf4eeb12d33b301acb0066c58c\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"App Contract - Cordango\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"What an app offers, compiled beside what it is.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://cordango.mintlify.site/_mintlify/api/og/v2?division=Concepts\u0026amp;title=App+Contract\u0026amp;description=What+an+app+offers%2C+compiled+beside+what+it+is.\u0026amp;theme=726d7292d81e7ed559f5aead\u0026amp;signature=7085531a97b56ce67e3282e4419e560bf275b6cf4eeb12d33b301acb0066c58c\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/cordango/Vl8DMyR37v-tD5rv/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Cordango\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#1D4ED8\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.cordango.com/concepts/app-contract\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/concepts/app-contract.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.cordango.com/#organization\",\"name\":\"Cordango\",\"url\":\"https://docs.cordango.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/cordango/Fb6tWISooksDFX10/logo-light.png?fit=max\u0026auto=format\u0026n=Fb6tWISooksDFX10\u0026q=85\u0026s=95a8ad3ae8faf04b6053814a2a2fcea0\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.cordango.com#website\",\"name\":\"Cordango\",\"url\":\"https://docs.cordango.com\",\"publisher\":{\"@id\":\"https://docs.cordango.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.cordango.com/concepts/app-contract#webpage\",\"url\":\"https://docs.cordango.com/concepts/app-contract\",\"name\":\"App Contract\",\"description\":\"What an app offers, compiled beside what it is.\",\"dateModified\":\"2026-10-04T17:41:47.016Z\",\"isPartOf\":{\"@id\":\"https://docs.cordango.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.cordango.com/concepts/app-contract#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.cordango.com/concepts/app-contract#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Concepts\",\"item\":\"https://docs.cordango.com/concepts\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"App Contract\",\"item\":\"https://docs.cordango.com/concepts/app-contract\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.cordango.com/concepts/app-contract#article\",\"headline\":\"App Contract\",\"name\":\"App Contract\",\"description\":\"What an app offers, compiled beside what it is.\",\"url\":\"https://docs.cordango.com/concepts/app-contract\",\"mainEntityOfPage\":{\"@id\":\"https://docs.cordango.com/concepts/app-contract#webpage\"},\"dateModified\":\"2026-10-04T17:41:47.016Z\",\"publisher\":{\"@id\":\"https://docs.cordango.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.cordango.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Cordango\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Cordango\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/concepts/app-contract.md","siteName":"Cordango","nav":{"global":null,"tabs":[{"tab":"Documentation","groups":[{"group":"Get started","icon":"rocket","pages":[{"title":"Cordango","href":""},{"title":"Quickstart","href":"/quickstart"}]},{"group":"Quickstart with an AI agent","icon":"sparkles","pages":[{"title":"Building with an agent","href":"/ai/overview"},{"title":"Claude Code","href":"/ai/claude"},{"title":"Codex","href":"/ai/codex"},{"title":"Cursor","href":"/ai/cursor"},{"title":"GLM","href":"/ai/glm"}]},{"group":"Concepts","icon":"diagram-project","pages":[{"title":"Overview","href":"/concepts"},{"title":"Semantic source","href":"/concepts/semantic-source"},{"title":"The App Definition","description":"The JSON document your source compiles into.","href":"/concepts/app-definition"},{"title":"App Contract","href":"/concepts/app-contract"},{"title":"The schema","description":"The contract behind the App Definition, and how to ask it questions.","href":"/concepts/schema"},{"title":"Targets","href":"/concepts/targets"},{"title":"Core apps","href":"/concepts/core-apps"},{"title":"Apps working together","href":"/concepts/cross-app"},{"title":"Forms","href":"/concepts/forms"}]},{"group":"Guides","icon":"book-open","pages":[{"title":"Editing an app","href":"/guides/authoring"},{"title":"Semantic operations","href":"/guides/semantic-ops"},{"title":"Roles and access","href":"/guides/roles"},{"title":"Custom code","href":"/guides/custom-code"},{"title":"Validating and CI","href":"/guides/validation"},{"title":"Deploying a generated app","href":"/guides/deploying"}]},{"group":"Security","icon":"shield","pages":[{"title":"Security \u0026 privacy","href":"/security"}]}]},{"tab":"CLI","pages":[{"title":"CLI","href":"/cli/install"}]},{"tab":"API reference","pages":[{"title":"API reference","href":"/api-reference/introduction"}]},{"tab":"MCP","pages":[{"title":"MCP","href":"/mcp/overview"}]}]},"basePath":"","title":"App Contract - Cordango","buildId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","deploymentId":"dpl_Fyv1NbzwP68g2bEH2Roy98uY1zmE","dynamics":[],"chunks":[]}