Skip to content

feat(#582): auto-approve queries covered by a pre-approving JIT grant#588

Open
babltiga wants to merge 1 commit into
mainfrom
feature/AF-582-grant-covered-auto-approval
Open

feat(#582): auto-approve queries covered by a pre-approving JIT grant#588
babltiga wants to merge 1 commit into
mainfrom
feature/AF-582-grant-covered-auto-approval

Conversation

@babltiga

@babltiga babltiga commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Closes #582

What

A JIT access request (AF-378) can now opt into query pre-approval via a new pre_approve_queries flag (checkbox on the Request Access form, default off, shown as a highlighted tag to the approving reviewer). While such a grant is APPROVED and unexpired, a submitted query it covers — matching capability (SELECT→can_read, DML→can_write, DDL→can_ddl) and allowed_schemas/allowed_tables scope — is auto-approved (PENDING_AI → APPROVED) instead of routing to human review, with the grant and its approver recorded as the approval provenance.

How

  • Placement: a dedicated fast-path in QueryReviewStateMachine (tryGrantFastPath), evaluated on the AI-completed and AI-skipped paths after routing-policy evaluation returns no match and before the plan fall-through — so AUTO_REJECT / REQUIRE_APPROVALS / ESCALATE policies (incl. anomaly-driven, AF-383) always win.
  • Safety valves: suppressed on HIGH/CRITICAL AI risk, on an open behavioural anomaly, on the AI-failed path, and on SQL re-parse failure (fail closed — the routing context's referencedTables is empty on parse failure, which would pass an allow-list check vacuously).
  • Module boundary: workflow consumes grant state via a new public access.api.AccessGrantLookupService (+ AccessGrantView with approver provenance from access_grant_decision) — a new, cycle-free workflow → access.api Modulith edge.
  • Coverage semantics reuse DatasourcePermissionChecker (hasCapability / rejectedTables) — the exact matching used by the submission gate.
  • Atomicity: new core.api.QueryRequestStateService.approveByAccessGrant stamps query_requests.approved_by_grant_id in the same locked transaction as the transition.
  • Audit: QueryAutoApprovedEvent extended with grant fields; audited as QUERY_APPROVED with metadata {auto_approved, source: "ACCESS_GRANT", access_grant_id, grant_approver, reason}.
  • API: GET /queries/{id} gains nullable approved_by_grant (grant id, approver, approved_at, expires_at); access-request submit body + responses gain pre_approve_queries.
  • Frontend: Request Access checkbox + hint, "Pre-approves queries" tag on my-requests and the admin queue (with tooltip), success alert with grant provenance on the query detail page; i18n in all 7 locales.
  • Flyway: V112__access_grant_query_pre_approval.sql (flag column + approved_by_grant_id + partial index).

Acceptance criteria

  • Query under an active covering grant auto-approves without human review (e2e + integration tests)
  • Justification references grant id + grant approver in audit metadata and on the query detail
  • Grant expiry/revocation immediately stops the fast-path (status flip; integration test)
  • Out-of-scope queries route through normal review unchanged (unit/integration/e2e)
  • AUTO_REJECT policies win over the fast-path (unit tests; ESCALATE too)
  • E2E spec: request access → approve → submit query → executed without reviewer action (e2e/tests/query-grant-pre-approval.spec.ts)

Docs & website updated

Verification

  • Backend: mvn verify -Pcoverage — 4667 tests green (incl. ApplicationModulesTest, ApiPackageDependencyTest, MessagesParityTest, new unit + Testcontainers integration tests)
  • Frontend: lint / typecheck / test:coverage (1139 tests, thresholds met) / build — green
  • e2e: full suite on a fresh stack — 225 passed, including the new query-grant-pre-approval.spec.ts (positive: request → approve → covered query auto-approved and executed with no reviewer action, detail shows grant provenance; negative: a grant without the flag keeps human review). The only failure is the pre-existing flaky query-scheduling.spec.ts timing race (20s wait vs the job's lockAtLeastFor=PT30S cadence, masked in CI by retries — untouched by this change, flagged for a separate fix).

A JIT access request can opt into query pre-approval (pre_approve_queries).
While the grant is APPROVED and unexpired, a query it covers (capability +
table scope, DatasourcePermissionChecker semantics) is auto-approved after
AI analysis instead of routing to human review, with the grant id and its
final-stage approver recorded on the query, in the audit log, and on the
query detail. Routing policies (incl. AUTO_REJECT and anomaly-driven
escalation), HIGH/CRITICAL risk, open anomalies, the AI-failed path, and
SQL re-parse failures all suppress the fast-path.
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Frontend Test Results

1 144 tests   1 144 ✅  3m 0s ⏱️
  155 suites      0 💤
    1 files        0 ❌

Results for commit 14d6985.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Frontend Coverage (frontend)

Status Category Percentage Covered / Total
🔵 Lines 94.18% (🎯 90%) 1994 / 2117
🔵 Statements 92.12% (🎯 90%) 2222 / 2412
🔵 Functions 91.47% (🎯 90%) 601 / 657
🔵 Branches 83.69% (🎯 80%) 1247 / 1490
File CoverageNo changed files found.
Generated in workflow #741 for commit 14d6985 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Backend Test Results

4 676 tests   4 676 ✅  15m 28s ⏱️
  617 suites      0 💤
  617 files        0 ❌

Results for commit 14d6985.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Queries under an active approved JIT access grant still require review — auto-approve with grant justification

1 participant