API reference
The public surface of the six released packages, curated (what the release
policy counts as semver-protected). Types are the
source of truth — everything here re-exports from each package’s index.
@ticora/core
Pure — no React, no IO; zod is the only runtime dependency.
Contracts
defineEntity({ name, schema, fieldKinds?, capabilities, fetch })→EntityContract. Declares an entity: a zod object schema (field names, kinds, and the.describe()strings the model reads), the allowed query capabilities, and your executor. ThrowsContractDefinitionErroron impossible declarations (e.g. a capability naming an undeclared field).serializeContract(contract)/reviveContract(json)— the declarative surface as JSON (what the Workspace Service stores) and back. A revived contract gates specs; itsfetchthrows by design.compileToTools/compileToValidator/compileToExecutor— one contract compiled three ways (LLM tool schema, query validator, executor); they cannot drift because they derive from the same object.executeQuery(rows, query, options?)— the in-memory engine: filter/sort/group/aggregate over fetched rows, capped atmaxClientRows(default 10 000;RowCapExceededErrorbeyond it).
Execution modes
Every capability runs client (default — the engine enforces it, your fetch
may over-return) or server (your fetch handles it; the engine trusts the
result). Declare per-operation:
capabilities: { ..., execution: { sort: "server" } }. Verify server modes
with ticora contracts lint --probe.
Specs
parseSpec(json)/serializeSpec(spec)— canonical (de)serialization;SpecParseErroron shape violations.validateSpec(spec, { contracts, policy? })→BUILD | CLARIFY | REJECT— the gate.MAX_BLOCKS,DEFAULT_REGISTRY, and the schema exports (workspaceSpecSchema,querySpecSchema, …) let you build tooling that cannot drift from the validator.migrateSpec/createMigrationRunner— forward migrations for future spec versions (v1 is frozen).
@ticora/react
react is the only peer; SSR-safe.
WorkspaceProvider— mount once:apiKey,userToken(passed untouched to every contract fetch),contracts,blocks, optionalstore,policy,registry,queryClient,onBlockDegraded,devMode.WorkspaceRenderer spec={…}— deterministic grid render of a validated spec. Per-block error boundaries; degradations fireonBlockDegradedonce each.defineBlock({ type, accepts, component })— register a custom block component; declarations are checked at mount, not at first render. See Bring your own components for the full path.- Headless hooks —
useBlockQuery,useWorkspaceFilters,useRuntimeFilters, workspace store hooks;createInMemoryWorkspaceStoreand theWorkspaceStoreport (list/get/create/update/remove) that the HTTP store implements.
@ticora/ui
defaultBlocks— the complete built-in block set (CasesTable,KpiCards,CaseQueue,GroupedBoard,FilterBar,Graph); hand toblocks={defaultBlocks}and swap entries one at a time.WorkspaceSandbox— the zero-config devMode screen.
Theming
Blocks read --we-* CSS custom properties from any ancestor — no CSS import:
--we-bg, --we-surface, --we-fg, --we-muted, --we-border,
--we-accent, --we-positive, --we-negative, --we-radius, --we-gap
(exported as tokens / TOKEN_NAMES).
Embedding in your app
The renderer is built to mount inside someone else’s shell, under someone
else’s stylesheet. Both directions of style interference are covered — and
pinned by tests (packages/react/src/renderer/embedding.test.tsx):
We cannot restyle your app. Every style we emit is an inline style
attribute on an element we rendered. The published packages ship no
stylesheet, and nothing is ever injected into document.head — so mounting
a workspace cannot change how the rest of your product looks.
Your CSS cannot break our layout. Inline styles outrank any selector, so
the layout-critical properties survive a hostile global stylesheet: the grid
stays display: grid with 12 columns and each block keeps its
grid-column placement, even under rules like
div { display: block !important } or * { box-sizing: content-box }.
The container contract — what you must provide:
- A block-level container with a width. The grid fills it; it does not assume a viewport, a position, or a stacking context.
- Nothing else. No required class, no reset, no wrapper.
The one caveat, stated plainly: properties we don’t set inline still
inherit from your page — font-family and text color most visibly. That is
usually what you want (the workspace picks up your typography). If you want it
isolated instead, set those explicitly on the container you mount into.
@ticora/client
Workspace Service client
createWorkspaceServiceClient({ baseUrl, apiKey, userId, fetch? })— typed /v1 client: workspaces CRUD + versions + rollback + shares + visibility + duplicate,listContracts/getContract/upsertContract/removeContract,listAudit({ workspaceId?, action?, limit? }), usage (getGenerationAllowance,recordGeneration,getUsageSummary). Errors:WorkspaceServiceError,WorkspaceNotFoundError,GenerationLimitedError.createHttpWorkspaceStore(options)— the same options, shaped as the SDK’sWorkspaceStoreport: swapping the in-memory store for the real service is one line. Keep the API key server-side — proxy pattern in the dashboard reference integration .
API key scopes
Keys are minted with one of two scopes. runtime covers the SDK’s own
traffic — workspace CRUD, telemetry ingest, usage allowance/generation — and
is the most a browser-adjacent key should ever hold. admin adds the
contracts registry, the audit trail, and the usage/telemetry summaries: a
dashboard, CLI, or CI credential. A runtime key hitting an admin endpoint
gets a machine-readable 403 with code: "insufficient_key_scope". Keys
minted before scopes existed behave as admin.
@ticora/cli
The canis binary — see the vendor CI guide:
contracts diff, contracts lint [--probe], contracts dev. Exit codes are
public API: 0 ok, 1 gating, 2 usage.
@ticora/devtools
In-app devtools bus + panel: recordSpec, recordVerdict,
DevtoolsQueryReporter, and the panel component for inspecting gate
verdicts and block queries during integration.