The engagement.* 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.
Favouriteengagement.favourite
| Property | Value |
|---|---|
| Capability | engagement.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Star an object (durable FAVOURITE). { objectType, objectId }.
Call POST /v/engagement.favourite with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.
Followengagement.follow
| Property | Value |
|---|---|
| Capability | engagement.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Follow an object (durable FOLLOW). { objectType, objectId }.
ZERO access (the read is still acl/visibility-gated - ADR-0042). Idempotent (re-follow = same row).
Call POST /v/engagement.follow with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool engagement.follow.
Listengagement.list
| Property | Value |
|---|---|
| Capability | engagement.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
The CALLING actor’s own durable engagements (follows +
favourites; { kind? } filters to one). A SELF-scoped read over the existing engagement store
(the CC-OPBOX 24 gate-(b) disposition: the data is modelled + written by engagement.follow/
favourite; this is the one thin read). Never another actor’s rows - the actor bind IS the scope.
Call POST /v/engagement.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool engagement.list.
Heartbeatengagement.presence.heartbeat
| Property | Value |
|---|---|
| Capability | engagement.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Publish my live-cursor TTL on an object.
{ objectType, objectId, ttlSeconds?, cursor? }. UPSERTS the caller’s PRESENCE row with
expires_at = now() + ttl. A stale (expired) row is never returned by presence.list (INV-6 - the row
is regenerable; no sweep is required for correctness). ZERO access (mirrors the durable verbs).
Call POST /v/engagement.presence.heartbeat with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool engagement.presence.heartbeat.
Listengagement.presence.list
| Property | Value |
|---|---|
| Capability | engagement.read |
| Risk class | Read - autonomy L0 |
| Min. permission | Member |
| Availability | On demand (MCP tier 2) |
| Idempotent | No |
| Egress | None - in-box (pure Postgres, no outbound call) |
| Render schema | Yes - drives an inline chat artefact and a GUI panel |
Who is live on an object (non-expired PRESENCE rows).
{ objectType, objectId }. Returns the actors with an un-expired heartbeat (the live multi-human
presence read). RLS-scoped + explicit ws predicate. A stale row (expires_at <= now) is filtered out
(INV-6 regenerable - never returned, no sweep needed). Render contract for the shell presence sweep.
Call POST /v/engagement.presence.list with a JSON body; returns JSON (or { error, code }). Also exposed as the MCP tool engagement.presence.list.
Viewengagement.view
| Property | Value |
|---|---|
| Capability | engagement.write |
| Risk class | Write - autonomy L1 |
| Min. permission | Member |
| Availability | Admin only (CLI/HTTP; never advertised over MCP) |
| Idempotent | Yes |
| Egress | None - in-box (pure Postgres, no outbound call) |
Record a view (last-seen marker). { objectType, objectId, context? }.
The “who touched this / when did I last look” affordance. UPSERT bumps updated_at (the last-seen).
Call POST /v/engagement.view with a JSON body; returns JSON (or { error, code }). Not advertised over MCP (admin-only); reachable via the CLI and HTTP doors.