Actor-grain target — populated when the event subject is bound to
a specific actor.
Concretely:
- Always populated: role_grant_revoke and role_grant_create
(admin direct-grant, self-service toggle, and in-tx
role_grant_offer_accept all populate both target columns — the
role_grant's grantee is the actor-grain subject regardless of who
initiated the grant), role_grant_offer_accept on accept (the
accept binds the actor deterministically), role_grant_offer_decline
(the grantor actor — decline is *to* the offering actor).
- Conditionally populated: offer-shape events
(role_grant_offer_create, _expire, _retract, _supersede)
carry the actor when the offer was actor-targeted at create time
(role_grant_offer.to_actor_id set), null when the offer was
account-grain (any actor on to_account_id may accept).
- Not populated: admin actions, account-shape events (login,
logout, signup, bootstrap, password_change, session/token
revoke, app_settings_update, invite events) — subject is the
account or no specific resource, not an actor-bound role_grant.
- Not populated: events whose principal isn't an actor-bound
resource (e.g. consumer events that name a non-actor scope in
metadata).
Multi-actor invariants this column relies on: when both
target_actor_id and target_account_id are populated they refer
to the same account (actor.account_id-derivable). The invariant
holds uniformly across every populated event including decline
(the grantor's account is joined into the decline RETURNING) and
the supersede cascade (the recipient account is known on
role_grant_offer.to_account_id). target_account_id stays the
SSE/WS socket-close key because sessions remain account-grain
after multi-actor lands.