DocsDevelopersManifest Reference

Manifest Reference

The manifest.json is the single source of truth for your application. It declares entities, fields, permissions, actions, webhooks, crons, and public access. Everything else (database tables, CRUD API, constraints, RBAC policies) is derived from it automatically.

All field names use camelCase (the manifest is parsed with serde(rename_all = "camelCase")).


Top-level fields

Field Type Required Default Description
appId string Yes Unique identifier. Lowercase snake_case (letters, digits, underscores). Immutable after first deploy. Becomes the PostgreSQL schema name.
name string Yes Display name.
version string No "0.0.1" Semantic version.
description string No "" Short description.
type string No "app" "app", "integration", or "agent".
icon string No Icon path (relative to project root). Stored in platform storage on deploy.
dataContract array No [] Array of entity definitions.
permissions object No Object with a permissions array of permission key declarations.
actions array No [] Array of RPC action declarations.
webhooks array No [] Array of webhook definitions.
crons array No [] Array of declarative cron schedules.
public object No Public-access surface (RPCs and collections that bypass auth).
configSchema object No JSON Schema for app-level configuration.
userAuth object No User authentication mode (for integrations).
instructions string No Usage instructions surfaced to AI agents via list_integrations.
trigger object No Auto-invoke this agent on entity changes in another app.

dataContract

Each entry becomes a PostgreSQL table. System columns (id, created_at, updated_at) are added automatically.

Field Type Required Description
entityName string Yes Table name. Used in API routes. Lowercase snake_case.
fields array Yes Array of field definitions.
identityKind string No Federates records across apps (e.g., "contact").
identityKey string No Field name used for identity lookup. Required if identityKind is set.
indexes array No Declarative secondary indexes. See indexes.
checks array No Declarative CHECK constraints. See checks.

fields

Field Type Required Default Description
name string Yes Column name. Lowercase snake_case. created_at and updated_at are reserved.
type string Yes One of the field types below.
required boolean No false Adds NOT NULL constraint.
default_value any No Default on insert. Accepts JSON values.
enum_values string[] No Allowed values. Generates a CHECK constraint automatically.
references object No For entity_link only. { "entity": "...", "field": "id" }.
is_primary_key boolean No false Custom primary key. Rarely needed.
on_delete string No For entity_link. "cascade", "restrict", or "set_null". Default: "restrict" if required, "set_null" if optional.

Field types

Type PostgreSQL Description
text TEXT Variable-length string.
number DOUBLE PRECISION 64-bit floating-point.
boolean BOOLEAN True/false.
date DATE Calendar date (YYYY-MM-DD).
timestamp TIMESTAMPTZ Date and time in UTC.
json JSONB Arbitrary JSON.
uuid UUID UUID value.
file TEXT File reference from the upload endpoint.
entity_link UUID REFERENCES Foreign key. Requires references.
[text] TEXT[] Array of strings.
[number] DOUBLE PRECISION[] Array of numbers.

References

Local entity:

{ "entity": "contacts", "field": "id" }

System users (creates FK to rootcx_system.users(id) with ON DELETE SET NULL):

{ "entity": "core:users", "field": "id" }

permissions

"permissions": {
  "permissions": [
    { "key": "contacts.create", "description": "Create contacts" },
    { "key": "contacts.read", "description": "View contacts" }
  ]
}

Keys follow entity.action convention. On deploy, they are prefixed with app:{appId}:. If not declared, CRUD keys are auto-generated from entities + cron keys (cron.read, cron.write, cron.trigger).


actions

"actions": [
  {
    "id": "pipeline",
    "name": "Pipeline Summary",
    "description": "Returns deal counts per stage",
    "inputSchema": { "type": "object", "properties": {...} },
    "outputSchema": { "type": "object", "properties": {...} }
  }
]
Field Type Required Description
id string Yes Must match a key in serve() rpc handlers.
name string Yes Display name for AI agents.
description string No What the action does.
inputSchema object No JSON Schema for input parameters.
outputSchema object No JSON Schema for the return value.

Each action gets an RBAC permission: app:{appId}:action:{actionId}.


webhooks

"webhooks": [
  { "name": "stripe", "method": "onStripePayment" },
  "github"
]

Two formats: full object { "name", "method" } or simple string (name only, method defaults to "POST"). For applications, always use the full format with an explicit method name.

See Webhooks for full reference.


crons

"crons": [
  {
    "name": "daily-check",
    "schedule": "0 9 * * *",
    "timezone": "America/New_York",
    "method": "onDailyCheck",
    "payload": { "task": "check_replies" },
    "overlapPolicy": "skip"
  }
]
Field Type Required Default Description
name string Yes 1-64 chars, alphanumeric + dash + underscore.
schedule string Yes 5-field cron expression or "N seconds" (1-59).
timezone string No GMT Timezone for the schedule.
method string No If set, added to payload as payload.method.
payload object No {} JSON object passed to the worker.
overlapPolicy string No "skip" "skip" or "queue".

See Scheduled Jobs for full reference.


public

"public": {
  "rpcs": [
    { "name": "submitForm", "scope": [] },
    { "name": "checkStatus", "scope": ["orderId"] }
  ],
  "collections": [
    { "entity": "announcements", "actions": ["list", "read"] }
  ]
}

rpcs

Field Type Description
name string RPC method name to expose publicly.
scope string[] Keys to enforce-match between share token context and request body. Empty = anonymous access (no token needed). Non-empty = share token required.

collections

Field Type Description
entity string Entity name to expose.
actions string[] Subset of CRUD actions: "list", "read", "create", "update", "delete".

trigger

For agent apps. Auto-invoke the agent when data changes in another app:

"trigger": {
  "appId": "crm",
  "entity": "contacts",
  "on": ["INSERT", "UPDATE"]
}
Field Type Description
appId string Target app whose entity to watch.
entity string Entity name to watch.
on string[] Operations: "INSERT", "UPDATE", "DELETE".

configSchema

JSON Schema for app-level configuration. For integrations, fields with platformSecret store values in the encrypted vault:

"configSchema": {
  "properties": {
    "botToken": { "type": "string", "platformSecret": "SLACK_BOT_TOKEN" }
  },
  "required": ["botToken"]
}

indexes

Declare secondary indexes on an entity. Reconciled at every deploy: the core creates, replaces, or drops only the indexes it owns (tagged with a hash comment). Manually-created indexes are never touched.

"indexes": [
  { "name": "deal_stage_idx", "columns": ["stage"] },
  { "columns": ["company_id", "created_at"], "unique": true },
  { "columns": [{ "column": "amount", "sort": "desc" }], "where": "amount > 0" }
]
Field Type Required Default Description
name string No Auto-derived Index name. Auto-generated if omitted.
columns array Yes Column names (strings) or specs ({ column, expr, sort, nulls, ops }).
unique boolean No false Create a UNIQUE index.
using string No "btree" Index method: btree, hash, gin, gist, spgist, brin.
where string No Partial-index predicate (SQL fragment).
with object No Storage parameters (e.g. {"fillfactor": "70"}).

checks

Declare table-level CHECK constraints with arbitrary SQL boolean expressions. Same ownership model as indexes: the core reconciles only the checks it owns, and never drops manually-created constraints.

Enum-derived CHECKs (from enum_values) are generated automatically. Use checks for business rules that span multiple columns or express conditions beyond simple value membership.

"checks": [
  { "name": "dates_valid", "expr": "end_date IS NULL OR end_date >= start_date" },
  { "expr": "quantity > 0" }
]
Field Type Required Description
name string No Constraint name. Auto-derived if omitted.
expr string Yes SQL boolean expression. Can reference any column on the table.

Schema sync

Every deploy diffs dataContract against the live PostgreSQL schema and applies the minimum DDL:

Change DDL
New entity CREATE TABLE
New field ALTER TABLE ADD COLUMN
Field type changed ALTER COLUMN TYPE with USING cast
required changed SET / DROP NOT NULL
default_value changed SET / DROP DEFAULT
on_delete changed Replace foreign key constraint
Field removed DROP COLUMN CASCADE
Entity removed DROP TABLE CASCADE
indexes changed Drop + recreate (tag-owned, no churn if unchanged)
checks / enum_values changed Drop + recreate (tag-owned, no churn if unchanged)

Column DDL runs in a single transaction per table. Indexes and checks are reconciled in a separate pass. If any statement fails, the transaction rolls back. Unchanged objects are left untouched (no drop/recreate churn).

The Schema Sync Engine drops columns removed from the manifest. Only id, created_at, and updated_at are protected.

Full example

{
  "appId": "sales_crm",
  "name": "Sales CRM",
  "version": "1.0.0",
  "description": "Manage contacts, companies, and deals.",
  "dataContract": [
    {
      "entityName": "contacts",
      "identityKind": "contact",
      "identityKey": "email",
      "fields": [
        { "name": "first_name", "type": "text", "required": true },
        { "name": "last_name", "type": "text", "required": true },
        { "name": "email", "type": "text" },
        { "name": "company_id", "type": "entity_link", "references": { "entity": "companies", "field": "id" } },
        { "name": "assigned_to", "type": "entity_link", "references": { "entity": "core:users", "field": "id" } },
        { "name": "stage", "type": "text", "enum_values": ["lead", "qualified", "proposal", "won", "lost"], "default_value": "lead" }
      ]
    },
    {
      "entityName": "companies",
      "fields": [
        { "name": "name", "type": "text", "required": true },
        { "name": "industry", "type": "text" },
        { "name": "website", "type": "text" }
      ]
    }
  ],
  "actions": [
    { "id": "pipeline", "name": "Pipeline Summary", "description": "Returns deal counts per stage" }
  ],
  "permissions": {
    "permissions": [
      { "key": "contacts.create", "description": "Create contacts" },
      { "key": "contacts.read", "description": "View contacts" },
      { "key": "contacts.update", "description": "Edit contacts" },
      { "key": "contacts.delete", "description": "Delete contacts" }
    ]
  },
  "webhooks": [
    { "name": "stripe", "method": "onStripePayment" }
  ],
  "crons": [
    { "name": "daily-sync", "schedule": "0 9 * * *", "overlapPolicy": "skip" }
  ]
}