feat(AF-937): persist the effective executed SQL on the query snapshot - #1091
Merged
Merged
Conversation
Contributor
Contributor
Coverage Report for Frontend Coverage (frontend)
File CoverageNo changed files found. |
Contributor
Contributor
Backend Code Coverage
|
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.
Closes #937
What
Persists the statement as it actually executed — row-security predicates and soft-delete rewrites spliced in, every bound value left as a
?placeholder — on the immutable query snapshot, so an auditor sees what ran instead of reconstructing it from policy rows that may since have been edited or deleted.query_snapshots.effective_sql(V187),updatable = false.RowSecurityRewriteralready deparses predicate values asJdbcParameter(?), so no redaction code was needed — tests pin that no bound value ever appears.DELETE → UPDATEis stored — that's what ran.;+ newline, NULL when no statement was rewritten. Keeps the read UI and diff simple.effectiveSqloncore.api.SelectExecutionResult/UpdateExecutionResult→QueryExecutedEvent→QuerySnapshotListener→recordOnExecution(id, effectiveSql). A SELECT result-cache hit is re-stamped with this execution's effective SQL.effective_sqlonGET /queries/{id}(existing gate: submitter orQUERY_VIEW_ALL); query detail SQL card gets a Submitted / Effective / Diff toggle reusingSqlDiffView; regulatory audit trail JSON + signed CSV (effective_sqlcolumn) + signed PDF (Effective SQL column) + auditor dashboard column.Acceptance: a policied query stores the spliced predicate with
?(backend Postgres IT + e2e); an unpolicied query stores NULL; deleting the policy afterwards leaves the stored statement unchanged (e2e deletes the policy and re-reads).Docs & website
docs/03-data-model.md,docs/04-api-spec.md,docs/05-backend.md,docs/06-frontend.md,docs/07-security.mdwebsite/docs/configuration/datasources/index.html,website/docs/configuration/audit-compliance/index.html,website/sitemap.xml(dates bumped)help-corpus/regeneratedVerification
mvn -o verify -Pcoverage: 10,270 tests, 0 failures (incl.ApplicationModulesTest,ApiPackageDependencyTest, Spotless, Checkstyle).test:coverage(96.0% lines / 87.7% branches) / build; website guards; help-corpus drift clean.row-security-policies.spec.ts(extended),auditor-compliance.spec.ts,query-replay.spec.ts— 9/9 passed.Review notes
Independent reviewers (af-verifier, af-reviewer, af-java-reviewer, af-frontend-reviewer, af-content-reviewer) — no Blockers. Addressed in the second commit: soft-delete wording (af-content-reviewer, af-frontend-reviewer), a positive + org-scoped
GET /queries/{id}integration case (af-java-reviewer), the auditor "—" fallback assertion and a class-free Segmented selector (af-frontend-reviewer).Surviving concerns, for a human decision:
effective_sqlis visible to the submitter, so an analyst can now see which column filters them, the operator, how many?anINlist carries, and1 = 0when their attribute didn't resolve — never the values. Documented indocs/07-security.md. If policy structure should stay admin-only, gating the field onQUERY_VIEW_ALLis a one-line change.effective_sql(pre-existing, documented); the MCP query-detail tool does not carry the field."effective_sql": nullalthough the backend omits nulls — kept to match the file's existing house style (af-content-reviewer nit).Screenshots