Declare what your product can do, once. Actions, risks, checks and off-limits screens, in one file.
Capability model v1 was frozen on 23 October 2026.
The same L1 check and wording as the CLI, running in your browser.
Six capabilities. Nothing invented. Three reads are required. Leave out any change you cannot make; no control appears.
Reads: all three required
Changes: declare the ones you support
task.list_assigned
The tasks assigned to this person, as { items, next_cursor }. next_cursor is null on the last page.
- risk
- read
- preconditions
- user_authorized
- input
- { workspace_id, cursor? }
- your handler
- list({ cursor? })
- verify
- Reads need no verify step; they still need a fallback.
- fallback
- deep_link
ownux test, L2 Verified
- task.list_assigned: lists valid tasks from this workspace, and paging ends
Conformance v0 accepts only these canonical capabilities, so the planned OwnUX Ready badge will mean the same everywhere.
Every field has a job. Fixed values: a typo fails at L1, not in front of a customer.
risk. One of read, reversible_write, irreversible_write or sensitive. By default, only the last two ask first.
preconditions. Reads need user_authorized. Changes also need task_unambiguous and field_editable. An ambiguous match asks; it never guesses.
verify. Always read_back on a change. OwnUX says Done only if it matches. Missing it fails L1.
fallback. Always deep_link, on every action, so any failure links to the task in your product.
input. Fields a change takes, such as task_ref. Dates are YYYY-MM-DD; keywords like today resolve first.
locked. Screens OwnUX must never re-render. Start with billing, security and consent. A missing list fails L1.
Locked surfaces
Some screens stay yours, whatever people ask for. List them once, and OwnUX never draws them.
An OwnUXSurface given a screen on your locked list never renders. It calls onFallback with locked_surface, and your own view shows instead.
- Billing, security and consent are in every starter manifest.
- Pass screen, or locked has nothing to compare against.
- Your design, logic and permission checks stay in your product.
<OwnUXSurface template="task_list" screen="admin" />
Today
Next
Renders in the person's OwnUX. The starter manifest asks you to lock screens like this one too.
Write it in TypeScript. It ships as data. defineManifest returns checked ownux-manifest/1 data. Satin's adapters pass the same L1 check.
import { defineManifest } from "@satin/ownux/integration"; const READ = { risk: "read", preconditions: ["user_authorized"], fallback: "deep_link" } as const;const WRITE = { risk: "reversible_write", preconditions: ["user_authorized", "task_unambiguous", "field_editable"], verify: "read_back", fallback: "deep_link",} as const; export const manifest = defineManifest({ app: { id: "acme-projects", version: "1.4.0" }, actions: { "task.list_assigned": READ, "task.search": READ, "task.get": READ, "task.transition": { ...WRITE, input: { task_ref: "task.ref", transition_id: "string" } }, "task.set_due_date": { ...WRITE, input: { task_ref: "task.ref", due_date: "date" } }, "task.assign": { ...WRITE, input: { task_ref: "task.ref", assignee_id: "string" } }, }, locked: ["billing", "security", "consent"],});{ "format": "ownux-manifest/1", "app": { "id": "acme-projects", "version": "1.4.0" }, "kind": "integration", "capabilities": { "task.get": { "risk": "read", "preconditions": ["user_authorized"], "fallback": "deep_link" }, "task.set_due_date": { "input": { "task_ref": "task.ref", "due_date": "date" }, "risk": "reversible_write", "preconditions": ["user_authorized", "task_unambiguous", "field_editable"], "verify": "read_back", "fallback": "deep_link" } }, "locked": ["billing", "security", "consent"]}$ npx ownux validate manifest.json✓ manifest.json: L1 Declared. L2 Verified needs `ownux test --config <ownux.config.ts>`.Handlers live in createIntegration. An execute or verify function in the manifest is accepted for spec compatibility, then ignored.
Manifest questions, answered.
Surfaces stay off until it passes. defineManifest returns the L1 result with the data. ownux validate and ownux test print a Fix: line for each finding.