Why
Graph lock custody (#107) records why and when a graph was locked — but never who.
_pgrdf_graphs carries locked, lock_reason, locked_at; attribution is absent at
exactly the point where it matters most, and lock_reason is unverified prose (anyone with
the privilege can write "sanctioned repair" and it becomes the record).
Meanwhile the attribution facts already exist in-session: downstream dispatch layers
maintain a transaction-scoped GUC carrying the door-verified requester identity, and
Postgres always knows session_user. Nothing reads them.
What
Custody acts record the identity pair, from session facts, never from arguments:
_pgrdf_graphs.locked_by text / unlocked_by text (nullable)
- On
lock_graph / unlock_graph: record
COALESCE(current_setting('ckp.requester', true), NULL) + session_user
(two columns or one composite — implementation's choice, both values must survive)
- An empty requester is the honest record: an act through the raw superuser plane
arrives unattributed and stays visibly so — that is the signal, not a gap to paper over
Acceptance
- Lock through a session with the requester GUC set →
locked_by carries it + session_user
- Lock through a plain session → requester side NULL,
session_user recorded
- Regression case extends the
_pgrdf_graphs contract (the case-72 pattern) with the new
nullable columns
- The lock refusal message is unchanged (contract stability)
Non-goals
Not enforcement (that's the role floor + grants), not verification of the reason (that's
grant-referencing custody, see the companion issue). This is attribution only: who, from
facts the server established, recorded beside the why and when that already exist.
Why
Graph lock custody (#107) records why and when a graph was locked — but never who.
_pgrdf_graphscarrieslocked,lock_reason,locked_at; attribution is absent atexactly the point where it matters most, and
lock_reasonis unverified prose (anyone withthe privilege can write "sanctioned repair" and it becomes the record).
Meanwhile the attribution facts already exist in-session: downstream dispatch layers
maintain a transaction-scoped GUC carrying the door-verified requester identity, and
Postgres always knows
session_user. Nothing reads them.What
Custody acts record the identity pair, from session facts, never from arguments:
_pgrdf_graphs.locked_by text/unlocked_by text(nullable)lock_graph/unlock_graph: recordCOALESCE(current_setting('ckp.requester', true), NULL)+session_user(two columns or one composite — implementation's choice, both values must survive)
arrives unattributed and stays visibly so — that is the signal, not a gap to paper over
Acceptance
locked_bycarries it +session_usersession_userrecorded_pgrdf_graphscontract (the case-72 pattern) with the newnullable columns
Non-goals
Not enforcement (that's the role floor + grants), not verification of the reason (that's
grant-referencing custody, see the companion issue). This is attribution only: who, from
facts the server established, recorded beside the why and when that already exist.