Core Invariants & Business Rules
These are the platform's guarantees: the invariants the core enforces (or, where noted, the contract it asks plugins to honour). They're consolidated here as a reference; the reasoning behind each lives in the relevant conceptual article.
Boundary
- The core never reads from or writes to plugin-owned tables. It has no knowledge of their shape.
- Plugin tables may reference core tables (
workspace,workflow_execution) via foreign keys; core tables never reference plugin tables. - Domain-specific business rules live in the plugin, never in the core.
- By contract, plugins mutate core tables only through core services, with a single startup exception (seeding their
entityandworkspace_statusrows). This is a discipline the contract asks for, not a mechanism the core enforces — a plugin runs with database access, so honouring it is the plugin developer's responsibility.
Workspaces & status
- Core workspaces are never deleted. There is no
is_deleted/is_archivedon the core workspace table; deletion and archival are plugin concerns on the join table. This preserves execution history and financial data by design. - Workspace status is scoped to an entity type (
workspace_status.entity_id), unique per(entity_id, slug). Two plugins may reuse the same slug. - A workflow may launch only from a workspace in one of its eligible statuses, and on success transitions the workspace to its single resulting status. The backend owns this transition — it never relies on UI assumptions — and validates that a workflow's eligible/resulting statuses share the workflow's entity type.
Configuration & cost
prompt.active_prompt_version_idmust reference a version belonging to the same prompt.- Configuration validity is derived from upstream enablement, not stored; the disable cascade propagates from any disabled dependency to the workflows above it.
- Cost is core-owned. Workflows report consumption only; the core computes
cost_usdat ingestion using current registry pricing. Each log row carries its owncost_usd; cumulative cost is derived at query time (no running-total column). - Financial reporting always derives from
workflow_execution_log; plugin-level deletion or archival never affects it.
Execution & snapshots
- A
workflow_executionstores four immutable snapshots (workflow_config,service_config,system,workspace), allJSONB NOT NULL; the webhook payload is assembled from them (there is no separate context-fetch endpoint). - The execution always references the original workspace it launched against, even when a workflow creates a new one.
- A dispatch failure marks the execution
failed_permanent; a result-handler throw rolls back and marksfailed_permanent. Workflow-reported, reconciler, and operator terminations markfailed_transient. Onlyfailed_transientis retryable, and retry replays the original snapshots exactly. - Truthfulness Invariant: the platform never marks an execution terminal while the engine may still be running. The reconciler never marks
completed— completion requires the/completeresult payload. - Threshold enforcement is
>=(reaching a limit exactly is a breach); a value of0means unlimited.
Auth
- Human and machine auth are separate concerns:
user_jwt_secretfor operators,workflow_jwt_secretfor API Keys, and the two must never be identical (enforced at startup). - Both token classes revoke by
jtidenylist, not raw-token storage. API Keys expire in 30 days; the full key is shown only once and never stored.
Plugin contract
- Every plugin provides an
entityrow, one or more workspace statuses, an entity-object table, a{entity_slug}_workspacejoin table (withis_deleted/is_archived), a manifest, and migrations — and supplies four extension points (resultHandler,workspaceSnapshotProvider,dashboardStatsProvider,workspaceDisplayResolver). - The core validates plugin structure at startup; a plugin that fails validation is skipped, and the platform starts without it.