Manifest Reference
The manifest declares everything the platform needs to know about your app: methods, tables, roles, interfaces, scenarios. It's read on every git push to determine what to compile and deploy.
#Full Example
{
"appId": "e452fcf2-06c5-49e8-b4f1-6353563f24b0",
"name": "Procure-to-Pay",
"roles": [
{ "id": "requester", "name": "Requester", "description": "Can submit vendor requests and purchase orders." },
{ "id": "approver", "name": "Approver", "description": "Reviews and approves purchase orders." },
{ "id": "admin", "name": "Administrator", "description": "Full access to all app functions." },
{ "id": "ap", "name": "Accounts Payable", "description": "Processes invoices and payments." }
],
"tables": [
{ "name": "vendors", "path": "dist/methods/src/tables/vendors.ts", "export": "Vendors" },
{ "name": "purchase-orders", "path": "dist/methods/src/tables/purchase-orders.ts", "export": "PurchaseOrders" },
{ "name": "invoices", "path": "dist/methods/src/tables/invoices.ts", "export": "Invoices" }
],
"methods": [
{
"id": "submit-vendor-request",
"name": "Submit Vendor Request",
"path": "dist/methods/src/submitVendorRequest.ts",
"export": "submitVendorRequest"
},
{
"id": "get-dashboard",
"name": "Dashboard",
"path": "dist/methods/src/getDashboard.ts",
"export": "getDashboard"
}
],
"interfaces": [
{ "type": "web", "path": "dist/interfaces/web/web.json" },
{ "type": "api", "path": "dist/interfaces/api/api.json" },
{ "type": "cron", "path": "dist/interfaces/cron/interface.json" }
],
"scenarios": [
{
"id": "ap-overdue-invoices",
"name": "AP: Overdue Invoices",
"description": "AP user with two invoices past due date.",
"path": "dist/methods/.scenarios/apOverdueInvoices.ts",
"export": "apOverdueInvoices",
"roles": ["ap"]
},
{
"id": "empty-requester",
"name": "Empty Requester",
"description": "Brand new user, no data.",
"path": "dist/methods/.scenarios/emptyRequester.ts",
"export": "emptyRequester",
"roles": ["requester"]
}
]
}#Fields
#appId
| Type | string (UUID) |
| Required | Yes |
The app's UUID, assigned when created on the platform. Found in the git remote URL: https://git.mscdn.ai/{appId}.git.
#name
| Type | string |
| Required | Yes |
Display name. Shown in the editor, workspace listings, and session context.
#auth
| Type | object |
| Required | No (omit for an app with no user accounts) |
Opts the app into managed user accounts. Without it, the app uses anonymous guest sessions: no login, no user identity, no roles.
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | true to enable auth |
methods | string[] | Yes | Auth methods: "email-code", "sms-code", "api-key", "remy" (platform-delegated sign-in, org-owned apps). At least one required. |
table.name | string | Yes | Name of the defineTable table holding user records |
table.columns.email | string | If email-code | Column name for email (platform-managed, read-only from code) |
table.columns.phone | string | If sms-code | Column name for phone (platform-managed, read-only from code) |
table.columns.roles | string | No | Column name for the roles array (bidirectional sync) |
table.columns.apiKey | string | If api-key | Column name for API key (platform-managed, stores masked value) |
The user table is a normal app table that you own and can extend with your own columns. See Auth & Roles for the full configuration and the frontend/backend APIs.
#roles
| Type | Array<{ id, name?, description? }> |
| Required | No (defaults to []) |
Defines the app's roles for access control. Each role:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Kebab-case identifier (used in code: auth.requireRole('admin')) |
name | string | No | Display name |
description | string | No | What this role can do (shown in editor, useful context for the agent) |
The platform syncs roles on deploy. Assign users to roles in the editor. See Auth & Roles.
#tables
| Type | Array<{ name, path, export }> |
| Required | No (defaults to []) |
Declares database tables. Each entry:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Table name (matches db.defineTable('name')) |
path | string | Yes | Path to the TypeScript file (relative to project root) |
export | string | Yes | Named export from the file (e.g., Vendors) |
The platform parses the TypeScript to extract the schema. See Tables & Database.
#methods
| Type | Array<{ id, name?, description?, path, export, ... }> |
| Required | Yes (at least one) |
Declares backend methods. Each entry:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Kebab-case identifier (used in API URLs and frontend method map) |
name | string | No | Display name |
description | string | No | What the method does. Used as the fallback tool description when the method is exposed to an agent. |
path | string | Yes | Path to the TypeScript file |
export | string | Yes | Named export (the async function) |
See Methods.
#Jewel fields
Only relevant when a method has an AI companion attached. Most methods set none of them. See Jewels.
| Field | Type | Required | Description |
|---|---|---|---|
autonomy | string | No | What happens to each proposal: "manual", "shadow", "approve", or "auto". "manual" records a policy of no automation. |
jewel | { path, export } | No | The jewel implementation file and its export |
sampleRate | number | No | Fraction of eligible decision moments that get the full autonomy treatment. Default 1; validated 0 < rate <= 1 at compile. Requires autonomy. |
attributionWindow | number | No | How long, in seconds, a proposal raised by jewels.propose waits for a human to act on the method so it has something to be graded against. It closes as expired if nobody does. Default 604800 (7 days), capped at 90 days. Requires autonomy. |
tuning | object | No | Training recipe for the jewel's own model (base, windowDays, epochs, rank, learningRate). Every knob optional, with platform defaults. Requires jewel. |
#interfaces
| Type | Array<{ type, path?, config?, enabled? }> |
| Required | No (defaults to []) |
Declares how users interact with the app. Each entry:
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | One of: web, api, cron, webhook, email, mcp, agent, voice |
path | string | No | Path to the interface config file |
config | object | No | Inline config (alternative to a file) |
enabled | boolean | No | Default true. Set false to skip during build. |
See Interfaces for the config schema for each type.
#scenarios
| Type | Array<{ id, name?, description?, path, export, roles }> |
| Required | No (defaults to []) |
Declares seed scripts for testing. Each entry:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Kebab-case identifier |
name | string | No | Display name |
description | string | No | What state this scenario creates |
path | string | Yes | Path to the TypeScript file |
export | string | Yes | Named export (the async function) |
roles | string[] | Yes | Roles assigned to the dev test user after seeding |
See Scenarios.