opbox

The row.* family (6 verbs). Every verb enters through the one front door: it is capability-checked, permission-checked, scope-checked and audited before it runs (see Security & permissions). Each entry below lists its capability, risk class (which fixes the minimum autonomy level), the minimum caller permission, its availability tier, whether it is idempotent, and any outbound egress.

Bulkrow.bulk

PropertyValue
Capabilitydata.row.write
Risk classDestructive - autonomy L3
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

{ tableId, rows: [ { id?, fields } ], mergeWithLocks? }. The bounded bulk write: each entry creates a row (no id) or updates an existing one (id). BOUNDED: more than MAX_BULK_ROWS entries is REJECTED outright (never silently truncated). Per row it honours the SAME guards as the single-row path (INV-1, one write path via set_fact): prototype-pollution + the lock-keyspace fence on every field key, the computed-write rejection (INV-6), and mergeWithLocks (default true - a __lock__ed cell is SKIPPED, reported per row; mergeWithLocks=false is refused if it would overwrite a lock - fail-closed, never silently clobber a hand-verified cell). One row’s hard error (a computed-column write, a missing column) fails the whole call (atomic on the dispatch tx) - a partial bulk is never committed.

Call POST /v/row.bulk with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Createrow.create

PropertyValue
Capabilitydata.row.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Creates a typed Row SHELL (no JSON cell blob - the Opbox TableRow.data footgun is retired). If fields (a key->value map) is supplied, each non-computed field is written as a canonical Fact via the same upsert as cell.set (INV-1, one write path). Any field key is prototype-pollution-fenced; a write to a computed column is rejected (INV-6).

Input { tableId, fields?, linkedMatterId?, displayOrder? } (fields ending in ? are optional)

Call POST /v/row.create with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Deleterow.delete

PropertyValue
Capabilitydata.row.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Deletes one row; its Facts cascade by the FK (migration 0026). Any derived side-effect (an entity_edge regeneration, a downstream rollup) is FIRE-AND-FORGET (INV-2): the canonical delete is the transition, the derived index is rebuilt off-band and never gates this write. RLS-scoped + explicit workspace predicate; a row in another workspace reads back not-found (anti-enumeration).

Input { id } (fields ending in ? are optional)

Call POST /v/row.delete with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Getrow.get

PropertyValue
Capabilitydata.row.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

s one row + the canonical Facts joined to it (cell key -> value). RLS-scoped + an explicit workspace predicate. PII facts are surfaced as encrypted (the decrypt-on-read path is a later beat - the skeleton returns the encryption_scheme tag so the cell is visibly regulated, never the plaintext from a ciphertext column).

Input { id } (fields ending in ? are optional)

Call POST /v/row.get with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Listrow.list

PropertyValue
Capabilitydata.row.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentYes
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - drives an inline chat artefact and a GUI panel

Lists the rows of a table for the inline-edit grid (the data-plane grid surface). Each row carries its id + its cells (the canonical Facts: a map of columnKey -> value). RLS-scoped with an EXPLICIT workspace_id = $ predicate. PII facts are surfaced as masked (the decrypt-on-read path is a later beat - the list returns the encryption_scheme tag so a cell is visibly regulated, never plaintext from a ciphertext column). Computed columns have no Facts (INV-6) so they do not appear in the cell map. IDEMPOTENT: the list is a projection, never a write.

Input { tableId, limit?, offset? } (fields ending in ? are optional)

Call POST /v/row.list with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.

Patchrow.patch

PropertyValue
Capabilitydata.row.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)

Partial field write: each key in fields is written as a canonical Fact via the same upsert as cell.set. REJECTS a write to a computed column (INV-6). Honours cell locks (a __lock__ed cell is NOT overwritten - it is skipped, reported in lockedSkipped). Prototype-pollution keys are fenced.

Input { id, fields } (fields ending in ? are optional)

Call POST /v/row.patch with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.