docs(db): side_effects_at IS readable by clients — the last migration said otherwise - #825
Merged
Merged
Conversation
… said otherwise
20260828220000 added the column and its COMMENT asserted "Server-side only: no
client SELECT grant". False, and production proves it: anon holds SELECT.
I read payment_intents as having the same grant shape as wallets. It does not,
and the difference is exactly the thing the wallets drift guard exists for:
* wallets carries an explicit COLUMN-LIST grant, rebuilt that way so
nwc_connection_uri could be excluded — so a column added later is
unreadable until someone grants it.
* payment_intents holds TABLE-level grants, which automatically cover every
column added afterwards.
What misled me was counting 21 rows in information_schema.column_privileges:
that view expands a table-level grant per column, so it looks identical to an
explicit column list, and has_table_privilege does not distinguish them either.
The honest test is whether the grant was written as `GRANT SELECT (cols)`.
The exposure is acceptable and now says so deliberately rather than by
accident: a settlement-completion timestamp is not a secret, and RLS still
decides which intents a caller sees. Withholding it would mean rebuilding the
whole table's grants as a column list — the surgery the wallets lockdown did,
for a reason that does not apply to a timestamp.
A new forward migration rather than an edit to the applied one: 20260828220000
has already run, so its COMMENT would never be re-issued and production would
keep the false text.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018waGt1ieA9TjpscqrbrnGb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#823 added
side_effects_atand itsCOMMENTasserted "Server-side only: no client SELECT grant". That is false, and production proves it:anonholds SELECT on the column.What I got wrong
I read
payment_intentsas having the same grant shape aswallets. It doesn't, and the difference is exactly what the drift guard from #821 exists for:walletsGRANT SELECT (cols))payment_intentsWhat misled me: counting 21 rows in
information_schema.column_privileges. That view expands a table-level grant per column, so it looks identical to an explicit column list — andhas_table_privilegedoesn't distinguish them either. The honest test is whether the grant was written asGRANT SELECT (cols).The exposure is fine — now deliberately, not accidentally
A settlement-completion timestamp is not a secret, and RLS still decides which intents a caller may see at all. Withholding it would mean rebuilding the entire table's grants as a column list — the surgery the wallets lockdown performed, for a reason that doesn't apply to a timestamp.
Why a new migration rather than an edit
20260828220000 has already run, so its
COMMENTwould never be re-issued and production would keep the false text. Never edit an applied migration — the repo's own rule, and here it's also the only thing that actually fixes the database.Migration versions unique.