Raxx · internal docs

internal · gated

QA Report — PR #1432

Generated: 2026-05-09 04:58 UTC PR: #1432 — fix(console): deploy-pipeline backend — run_id backfill, audit viewer, heroku_app Issues closed: #1409 · #1410 · #1411 (backend half only) Mode: thorough Verdict: qa:partial-pending-deploy — code-level ACs all pass; live-prod re-verification required after merge + Heroku release. Auth identity: raxx-ops-bot (token-only static checks; no live mutation).


Summary

PR #1432 lands three independent backend fixes. All 21 new tests pass. All 96 existing deploy-related tests pass clean (no regressions). Static review confirms the ACs are correctly addressed at the code level. Because the bug fixes operate against a live state machine that only reaches the broken path on a real GitHub Actions dispatch + callback round-trip, the runtime ACs (#1409 run_id backfill, #1411 heroku_app in API response) cannot be verified until the PR merges and raxx-console-prod ships the new release. Post-deploy re-run procedure documented below.

AC Source Code-level Live-prod Status
#1409 — apply_callback back-fills run_id when ASYNC flag OFF tests + diff PASS NOT YET DEPLOYED partial-pending-deploy
#1410 — GET /console/audit returns 200 with paginated table tests + diff PASS NOT YET DEPLOYED partial-pending-deploy
#1410 — RBAC ops + superadmin only tests PASS n/a pass
#1410 — flag-gated 404 when FLAG_CONSOLE_DEPLOY_UI off tests PASS n/a pass
#1410 — own access audited as console.audit.viewed tests PASS n/a pass
#1410 — pagination + action_type filter + date range tests PASS n/a pass
#1411 (backend) — heroku_app in _deploy_to_dict() tests + diff PASS NOT YET DEPLOYED partial-pending-deploy
#1411 (backend) — null for CF Pages surfaces tests PASS n/a pass

Pre-conditions verified


Per-AC verification

AC #1409 — run_id back-fill from callback regardless of flag

Code review (PASS):

The fix in console/app/services/deploys.py:864-882 removes the wrong _async_flag_enabled() and ... guard. New guard is the single correct invariant: if deploy.github_run_id is None. The diff comment also explains why the original guard was incorrect (sync poll can miss the run due to per_page or GH latency; callback is the reliable fallback in both modes). This is a textbook root-cause fix — surgical, narrow, well-explained.

Test coverage (PASS):

console/tests/test_deploy_run_id_backfill_1409.py — 5 tests, all green: - test_backfill_when_async_flag_off_and_run_id_null — the regression case - test_no_overwrite_when_async_flag_off_and_run_id_already_set — invariant preserved - test_callback_without_run_id_leaves_null_when_flag_off — defensive - test_backfill_when_async_flag_on_and_run_id_null — pre-existing behaviour preserved - test_no_overwrite_when_async_flag_on_and_run_id_already_set

Live re-verification (PENDING): see "Re-run procedure" below.

AC #1410 — GET /console/audit operator-facing audit log viewer

Code review (PASS):

Test coverage (PASS):

console/tests/test_audit_viewer_1410.py — 13 tests, all green: - RBAC: superadmin/ops pass, unauthenticated/readonly redirected - Flag-gate: flag off returns 404 - Rendering: rows appear in HTML, empty-state shown when no rows - Filtering: action_type narrows correctly - Error handling: bad date param shows error banner (not 500) - Audit-of-audit: access writes a console.audit.viewed row - Pagination: total page count reflected - Page structure: filter form + title rendered

Live re-verification (PENDING): with FLAG_CONSOLE_DEPLOY_UI=true already on, the route should return 200 immediately upon release.

AC #1411 (backend) — heroku_app in deploy GET response

Code review (PASS):

Test coverage (PASS):

3 tests in test_deploy_run_id_backfill_1409.py: - test_heroku_app_present_for_api_prod_surfaceheroku_app=raxx-api-prod - test_heroku_app_present_for_console_prod_surfaceheroku_app=raxx-console-prod - test_heroku_app_none_for_cf_pages_surfaceheroku_app=None for getraxx (CF Pages)

Live re-verification (PENDING): see procedure below.

Out of scope — JS-side _deploy_modal.html cleanup

The full #1411 issue describes a JS sessionStorage corruption bug that lives in console/app/templates/_deploy_modal.html:1411-1538. This PR delivers only the backend half (the heroku_app field that the JS layer should consume). The JS-side fix is on the in-flight PR #1433 / DONE-state polisher. This is correctly noted in the PR title ("backend") and the PR body. Not a blocker for #1432 merge.


Test execution log

$ cd console && PYTHONPATH=. python3 -m pytest tests/test_deploy_run_id_backfill_1409.py tests/test_audit_viewer_1410.py -v

============================ 21 passed in 1.60s ============================

$ python3 -m pytest tests/test_deploy_hardening_904_905.py \
                     tests/test_deploys_callback_735.py \
                     tests/test_deploys_736.py

============================ 96 passed in 12.42s ============================

Re-run procedure (post-merge)

Once PR #1432 is merged to main and a new deploy-console.yml run targets production:

#1409 (run_id back-fill)

  1. Trigger a console-driven deploy via the in-console deploy modal — pick any non-prod surface or a low-risk prod redeploy.
  2. Within ~5 seconds of HMAC callback (the workflow's first heartbeat), query: GET /api/internal/deploys?limit=1
  3. Confirm row's github_run_id is non-null and github_run_url matches.
  4. If still null, check Heroku log drain for apply_callback execution traces — Sentry should also surface any exception.

#1410 (audit viewer)

  1. Authenticate to console as kris@moosequest.net (superadmin) via CF Access.
  2. Hit https://console.raxx.app/console/audit — expect 200 with table render.
  3. Apply action_type=console.deploy filter — table narrows to deploy events.
  4. Apply a stale from/to UTC range that matches no rows — empty-state row renders.
  5. Apply garbage to from (e.g. from=garbage) — error banner renders, no 500.
  6. Verify a console.audit.viewed row was just written by visiting the page (visible by reloading and seeing the new row).

#1411 (heroku_app)

  1. Find the most recent successful deploy id from /api/internal/deploys?limit=5.
  2. GET /api/internal/deploys/<deploy_id>
  3. Confirm heroku_app is raxx-api-prod for api-prod, raxx-console-prod for console-prod, etc.
  4. Find a getraxx deploy id and confirm heroku_app=null.

Risk assessment


Recommendation

MERGE-READY, gated on: - (1) author re-verifies the three live-prod ACs above after the next deploy-console.yml run - (2) re-running this report's verification steps and updating the labels from qa:partial-pending-deploy to qa:passed

No blockers found. No new issues filed.