opbox

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

PropertyValue
Capabilityengagement.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentYes
EgressNone - 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

PropertyValue
Capabilityengagement.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - 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

PropertyValue
Capabilityengagement.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - 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

PropertyValue
Capabilityengagement.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentYes
EgressNone - 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

PropertyValue
Capabilityengagement.read
Risk classRead - autonomy L0
Min. permissionMember
AvailabilityOn demand (MCP tier 2)
IdempotentNo
EgressNone - in-box (pure Postgres, no outbound call)
Render schemaYes - 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

PropertyValue
Capabilityengagement.write
Risk classWrite - autonomy L1
Min. permissionMember
AvailabilityAdmin only (CLI/HTTP; never advertised over MCP)
IdempotentYes
EgressNone - 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.