mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 13:01:00 +00:00
Migration 0293 adds `sessions.acting_as_user_id`. NULL, which is what every session has carried until now, means the browser is acting as the account it signed in as. It is a selector and not an authorization. The resolver joins it against a live grant on every request, so a value stranded here by a grant that has since been revoked or expired confers nothing. Nothing sweeps the column for correctness; the sweeps that exist are housekeeping, so a delegate's browser lands back in its own account instead of on a wall of 403s. ON DELETE SET NULL, not CASCADE. The two ends mean opposite things: deleting the session's owner should take the session with it, which is the existing `user_id` cascade, while deleting the account being acted on must leave the delegate's browser session alive. A cascade on this side would sign a delegate out of their own account because somebody else deleted theirs.
37 lines
1.9 KiB
SQL
37 lines
1.9 KiB
SQL
-- v1.36.0 — the cookie transport's acting-account carrier.
|
|
--
|
|
-- One nullable column, and the whole reason it is a column rather than
|
|
-- something the client sends: a browser cannot address this row. The session
|
|
-- cookie carries a 32-byte secret whose hash is the lookup key, so nothing
|
|
-- reachable from the client names, reads, or writes `acting_as_user_id`. The
|
|
-- only writer is the switch endpoint, which validates the grant first.
|
|
--
|
|
-- It is still a SELECTOR and not an authorization. The resolver joins it
|
|
-- against a live row in `account_grants` on every request, so a value stranded
|
|
-- here by a grant that has since been revoked or expired confers nothing at
|
|
-- all. Nothing sweeps this column for correctness — sweeping it (on revocation,
|
|
-- on account deletion) is housekeeping so the delegate's browser lands back in
|
|
-- its own account instead of on a wall of 403s.
|
|
--
|
|
-- ON DELETE SET NULL, not CASCADE. The two ends mean opposite things here:
|
|
-- deleting the session's OWNER should take the session with it (that is the
|
|
-- existing `user_id` cascade), while deleting the account being ACTED ON must
|
|
-- leave the delegate's browser session alive and simply put it back into its
|
|
-- own record. A CASCADE on this side would sign a delegate out of their own
|
|
-- account because somebody else deleted theirs.
|
|
--
|
|
-- The index is not for the resolver — that reads by primary key. It is for the
|
|
-- two sweeps that go the other way: revocation clearing every session of the
|
|
-- delegate pointing at this owner, and the SET NULL above when an account is
|
|
-- deleted. Both scan on this column.
|
|
|
|
ALTER TABLE "sessions" ADD COLUMN "acting_as_user_id" TEXT;
|
|
|
|
ALTER TABLE "sessions"
|
|
ADD CONSTRAINT "sessions_acting_as_user_id_fkey"
|
|
FOREIGN KEY ("acting_as_user_id") REFERENCES "users"("id")
|
|
ON DELETE SET NULL ON UPDATE CASCADE;
|
|
|
|
CREATE INDEX "sessions_acting_as_user_id_idx"
|
|
ON "sessions" ("acting_as_user_id");
|