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
| Property | Value |
|---|---|
| Capability | data.row.write |
| Risk class | Destructive - autonomy L3 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - 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
| Property | Value |
|---|---|
| Capability | data.row.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - 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
| Property | Value |
|---|---|
| Capability | data.row.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - 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
| Property | Value |
|---|---|
| Capability | data.row.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - 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
| Property | Value |
|---|---|
| Capability | data.row.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - 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
| Property | Value |
|---|---|
| Capability | data.row.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | No |
| Egress | None - 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.