Skip to content

Code-owned configuration

Workflow profiles, roles and their schemas, topics, MCP server definitions, agents, scan schemes and the domain dictionary can be owned by the database or by the code that declares them. One dial decides, and every entry can override it. With code ownership, the same git commit produces the same configuration locally, in staging and in production, without wiping a database.

index.ts
await start({
database: { connectionString: process.env.DATABASE_URL },
configSource: 'code', // declarations apply on every boot
workers: WORKERS,
roles: ROLES,
topics: TOPICS,
agents: AGENTS,
scanSchemes: SCHEMES,
});
configSource Boot behavior Who edits
'db' (default) Insert each declared record if absent. When code and database disagree, log config drift: and leave the row alone. Admins, live, in the dashboard and API
'code' Compare each declaration with the database and apply the difference. An unchanged declaration writes nothing. Code, through git and CI/CD. Dashboard edits to declared fields are replaced on the next deploy.

Every entry accepts reset, which wins over the dial in either direction:

configSource: 'code',
topics: [
{ topic: 'app.orders.created' }, // follows the dial: code-owned
{ topic: 'app.ops.notes', reset: false }, // db-owned: admins keep editing it
],

The domain dictionary’s override is mcp.domainDictionaryReset.

Surface Declared in A code-owned apply writes Left alone
Workflow profiles workers[].config The full profile, including role lists, input_schema and input_lookups Task history, escalations
Roles roles[] Declared fields only; escalation targets replace Membership, undeclared fields
Topics topics[] The whole catalog entry last_seen_at
MCP servers mcp.serverFactories[].config Description, tags, category, compile hints, credential providers Tool manifest, connection status
Agents agents[] Description, status, goals, rules, domain, schedules Capabilities, metadata, run history
Agent subscriptions agents[].subscriptions Reaction fields per agent and topic enabled, the admin switch
Scan schemes scanSchemes[] The scheme and its rules, as one unit
Domain dictionary mcp.domainDictionary or mcp.domainDictionaryPath The whole document, one version per change
Graph workflows graphWorkflows[] Always compare and apply; redeploy on a YAML version bump Run history

roles[] declares titles, versioned form, metadata and list schemas, escalation targets, upstream inputs, Pace Board dials, pins and portals:

roles.ts
export const ROLES = [
{
role: 'packer',
title: 'Packer',
form_schema: PACKER_FORM,
escalation_targets: ['lead'],
sla_minutes: 30,
target_per_hour: 40,
properties: { kiosk: true },
},
];

Only declared fields are written. An omitted field keeps whatever the database holds, under either mode. Under 'db', the declaration is written once when the role is first created.

Role schemas version through the same write path as the dashboard. A declaration whose form_schema or metadata_schema differs from the stored pair advances the role’s schema version and snapshots the new pair with the change summary startup apply (code).

In-flight escalations keep the version they were created against, so their forms keep working while new rows get the new shape. Version history only grows: an apply never rewinds or rewrites a version. list_schema versions on its own timeline.

A scheme and its rules are one ownership unit, so one reset covers both:

scanSchemes: [
{
version: 12,
name: 'Serial locate',
target_facet: 'serialNumber',
encoding: 'fixed',
target_length: 8,
rules: [{ category: '1', name: 'Locate', steps: [{ verb: 'show-detail' }] }],
},
],

The scheme applies before its rules, so rule validation sees the scheme’s kind. The pass runs whether or not features.scanCodes is on.

Each surface logs one line per boot:

[long-tail] config apply (workflows): applied 2, unchanged 31, db-owned 0
[long-tail] config apply (roles): applied 1, unchanged 11, db-owned 0, orphans: [old-station]

An orphan is a database record of a declared surface with no matching declaration. Orphans are logged at warn level and left in place. Removing a workflow config, role, topic or agent stays a deliberate act through the dashboard or API.

Surface Orphan candidates
Roles Rows with real configuration (a title or a form schema). Bare rows created for foreign keys and membership-only roles never appear. Skipped when examples: true.
Scan schemes Rules in the database but absent from a code-owned scheme, reported as version/category
Agent subscriptions Subscriptions not declared in code

Containers that boot together serialize their configuration pass on a dedicated Postgres advisory lock, separate from the migration lock. Each upsert also carries an IS DISTINCT FROM guard, so an identical declaration from two containers writes once and no-ops once.

display.timeZone (an IANA name) renders every dashboard date in that zone: list columns, station facts and detail pages. Unset, dates follow the viewer’s browser. An unknown zone fails the boot.

await start({
database: { connectionString: process.env.DATABASE_URL },
display: { timeZone: 'America/Chicago' },
});