Skip to content

Add admin webhook status summary#331

Merged
ramimbo merged 3 commits into
ramimbo:mainfrom
LubuSeb:codex/mergework-admin-webhook-summary
May 26, 2026
Merged

Add admin webhook status summary#331
ramimbo merged 3 commits into
ramimbo:mainfrom
LubuSeb:codex/mergework-admin-webhook-summary

Conversation

@LubuSeb
Copy link
Copy Markdown
Contributor

@LubuSeb LubuSeb commented May 25, 2026

Refs #316

What changed:

  • Added a read-only processed-status summary to the browser /admin webhook outcomes section.
  • Groups webhook delivery outcomes case-insensitively and prioritizes high-signal statuses such as missing_submitter, bounty_not_found, exhausted_bounty, duplicate delivery, already-paid, and paid.
  • Keeps the existing event table, processed-status filter, and bounded limit behavior intact.
  • Uses the existing admin cookie flow through /admin; no admin-token-only API path or mutation control is added.
  • Renders only aggregate processed-status labels and counts, plus the existing safe table fields. No payload bodies, secrets, token values, deployment details, payout details, or private vulnerability details are rendered.

Why this is distinct:

  • PR Show webhook outcomes on admin page #318 added the recent delivery table with filtering and limit controls.
  • This PR adds a scan layer above that table so maintainers can see outcome counts before drilling into individual deliveries.

Post-rebase validation:

  • C:\Users\sebas\Documents\BountyBar\work\mergework-281\.venv\Scripts\python.exe -m pytest -q -> 318 passed.
  • C:\Users\sebas\Documents\BountyBar\work\mergework-281\.venv\Scripts\python.exe -m ruff check app/main.py tests/test_security.py -> passed.
  • C:\Users\sebas\Documents\BountyBar\work\mergework-281\.venv\Scripts\python.exe -m ruff format --check app/main.py tests/test_security.py -> passed.
  • C:\Users\sebas\Documents\BountyBar\work\mergework-281\.venv\Scripts\python.exe -m mypy app -> success.
  • git diff --check origin/main...HEAD -> clean.

Summary by CodeRabbit

  • New Features

    • Added a "Recent delivery outcomes" summary section on the admin page showing webhook status counts, prioritized ordering, and conditional display when data exists.
    • Status aggregation is now case-insensitive so differently-cased entries are grouped.
  • Tests

    • Expanded tests to cover the summary display, ordering, case-insensitive matching, and inclusion of newly represented statuses.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 63bc881c-917c-4d9f-b24b-70ce2219ab33

📥 Commits

Reviewing files that changed from the base of the PR and between c1b7895 and 5834624.

📒 Files selected for processing (1)
  • tests/test_security.py

📝 Walkthrough

Walkthrough

Adds a prioritized, case-insensitive summary of webhook delivery outcomes to the admin page: defines a scan-order mapping, computes counts grouped by normalized processed_status, passes the summary into the /admin template, renders a conditional summary block, and updates tests to validate case-insensitive behavior and the new summary.

Changes

Webhook status summary

Layer / File(s) Summary
Status ordering and summary computation
app/main.py
Adds WEBHOOK_OUTCOME_SCAN_ORDER and webhook_status_summary(session) that groups WebhookEvent.processed_status case-insensitively, counts occurrences, and returns a sorted list using explicit priority with fallback rank and secondary ordering by descending count and status text.
Admin page wiring and template rendering
app/main.py, app/templates/admin.html
/admin handler computes webhook_status_summary and passes it to admin.html. Template conditionally renders a .bounty-list-summary block with one article per {processed_status, count} entry when webhook_status_summary is present.
Test coverage for case-insensitive status handling
tests/test_security.py
Test seeds webhook events with case-variant processed_status values (including Missing_Submitter and exhausted_bounty) and updates assertions to verify the summary block includes exhausted_bounty, the missing_submitter filter markup/count, and case-insensitive filtering behavior.

Sequence Diagram(s)

sequenceDiagram
  participant AdminRoute
  participant webhook_status_summary
  participant DB
  AdminRoute->>webhook_status_summary: call with Session
  webhook_status_summary->>DB: query WebhookEvent.processed_status
  DB-->>webhook_status_summary: rows (case-variant statuses)
  webhook_status_summary-->>AdminRoute: sorted [{processed_status,count}, ...]
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • ramimbo/mergework#318: Both PRs modify the /admin webhook-outcome UI path by changing how processed_status is handled for filtering/rendering (including case-insensitive behavior) across app/main.py, app/templates/admin.html, and tests.

Suggested reviewers

  • weilixiong
  • ayskobtw-lil
  • g8rr5dg2p7-svg
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: adding a webhook status summary to the admin page.
Description check ✅ Passed The PR description is comprehensive with clear sections covering what changed, why it's distinct, and post-rebase validation. However, the template's 'Summary' section lacks a bulleted item.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@TateLyman TateLyman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The summary implementation looks behaviorally focused, but I would clean up two merge/validation issues before accepting it.

Evidence checked:

  • Inspected app/main.py, app/templates/admin.html, and tests/test_security.py on current PR head 617d03080a6ecee23e3cf0c03a789a073cd33233.
  • Verified the admin route still uses the existing /admin cookie flow before querying webhook data.
  • Verified the added summary groups processed_status case-insensitively and renders only aggregate labels/counts, not payload bodies.
  • Ran the focused admin rendering test locally: uv run --extra dev python -m pytest tests/test_security.py::test_admin_page_renders_safe_webhook_events_for_cookie_admin -q -> 1 passed.
  • Ran Python-only validation: uv run --extra dev ruff check app/main.py tests/test_security.py -> passed; uv run --extra dev ruff format --check app/main.py tests/test_security.py -> 2 files already formatted; uv run --extra dev python -m mypy app/main.py -> success; git diff --check origin/main...HEAD -> clean.

Actionable notes:

  • GitHub currently reports this PR as DIRTY, so it needs a rebase/update before maintainers can merge even though the local diff-check is clean.
  • The PR description's Ruff command includes app/templates/admin.html. Running that exact command locally fails because Ruff parses the Jinja template as Python. Please update the validation notes to either run Ruff on Python files only or use a template-aware check for admin.html.

@LubuSeb LubuSeb force-pushed the codex/mergework-admin-webhook-summary branch from 617d030 to 00ca4f2 Compare May 25, 2026 23:36
@LubuSeb
Copy link
Copy Markdown
Contributor Author

LubuSeb commented May 25, 2026

Updated. I rebased the branch onto current origin/main and force-pushed 00ca4f2049dcc2bff73dfc708da32dd4d89a18c0; GitHub now reports the PR as mergeable.

I also updated the PR description with the post-rebase validation and kept Ruff scoped to Python files only:

  • pytest -q -> 318 passed
  • ruff check app/main.py tests/test_security.py -> passed
  • ruff format --check app/main.py tests/test_security.py -> passed
  • mypy app -> success
  • git diff --check origin/main...HEAD -> clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_security.py`:
- Around line 200-210: Add assertions in tests/test_security.py that verify the
summary priority ordering by checking string positions in the rendered summary
HTML: use all_events.text.find(...) (or .index(...)) to assert that
"exhausted_bounty" appears before "missing_submitter" and that
"missing_submitter" appears before "paid" (i.e., assert idx_exhausted <
idx_missing < idx_paid), and similarly assert ordering for filtered.text (e.g.,
that "delivery-missing-submitter" appears before
"delivery-missing-submitter-uppercase") so the scan-order contract is enforced.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 86af19d9-f6e5-4f3f-8edd-117ac864b2ae

📥 Commits

Reviewing files that changed from the base of the PR and between 617d030 and 00ca4f2.

📒 Files selected for processing (3)
  • app/main.py
  • app/templates/admin.html
  • tests/test_security.py

Comment thread tests/test_security.py
@TateLyman
Copy link
Copy Markdown
Contributor

Rechecked after the rebase/force-push. My two original blockers are resolved now:

  • GitHub reports mergeStateStatus: CLEAN; hosted quality check is green.
  • The PR description validation no longer includes the Jinja template in the Ruff command; local Python-only Ruff check/format passes.

Local validation on current head 00ca4f2049dcc2bff73dfc708da32dd4d89a18c0:

  • uv run --extra dev python -m pytest tests/test_security.py::test_admin_page_renders_safe_webhook_events_for_cookie_admin -q -> 1 passed
  • uv run --extra dev ruff check app/main.py tests/test_security.py -> passed
  • uv run --extra dev ruff format --check app/main.py tests/test_security.py -> passed
  • uv run --extra dev python -m mypy app/main.py -> success
  • git diff --check origin/main...HEAD -> clean

The remaining CodeRabbit note about asserting summary/display ordering looks valid but lower-severity; it would improve regression coverage for the ordering contract but is not the same merge/validation blocker I originally flagged.

@LubuSeb
Copy link
Copy Markdown
Contributor Author

LubuSeb commented May 25, 2026

Addressed the CodeRabbit ordering test suggestion in c1b7895995d08f8f75646d6dd67c6cdd401104f5.

I added a rendered admin-page assertion that locks the intended status summary priority order:
missing_submitter -> bounty_not_found -> exhausted_bounty -> paid.

Validation after the follow-up commit:

  • pytest -q -> 318 passed
  • ruff check app/main.py tests/test_security.py -> passed
  • ruff format --check app/main.py tests/test_security.py -> passed
  • mypy app -> success
  • git diff --check origin/main...HEAD -> clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
tests/test_security.py (1)

204-210: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Scope status-order assertions to the summary block only.

Using all_events.text.index(...) here allows matches from the table, so Line 205-Line 208 can still pass even if a summary item regresses (for example, paid missing from the summary but present in rows). Extract .bounty-list-summary first, then assert order within that substring.

Suggested patch
-    status_summary_positions = [
-        all_events.text.index("<code>missing_submitter</code>"),
-        all_events.text.index("<code>bounty_not_found</code>"),
-        all_events.text.index("<code>exhausted_bounty</code>"),
-        all_events.text.index("<code>paid</code>"),
-    ]
+    summary_match = re.search(
+        r'<div class="bounty-list-summary"[^>]*>.*?</div>', all_events.text, flags=re.S
+    )
+    assert summary_match is not None
+    summary_html = summary_match.group(0)
+    status_summary_positions = [
+        summary_html.index("<code>missing_submitter</code>"),
+        summary_html.index("<code>bounty_not_found</code>"),
+        summary_html.index("<code>exhausted_bounty</code>"),
+        summary_html.index("<code>paid</code>"),
+    ]
     assert status_summary_positions == sorted(status_summary_positions)

As per coding guidelines, tests/**/*.py: Add or update tests for changed behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_security.py` around lines 204 - 210, The current order check uses
all_events.text.index(...) which can match items outside the summary; instead
extract only the bounty summary HTML/text first (the .bounty-list-summary block
from all_events.text), then compute status_summary_positions by calling
.index(...) on that summary substring and assert those positions are sorted;
update uses of status_summary_positions and all_events to operate on the
extracted summary string so the order assertion only checks the summary block.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@tests/test_security.py`:
- Around line 204-210: The current order check uses all_events.text.index(...)
which can match items outside the summary; instead extract only the bounty
summary HTML/text first (the .bounty-list-summary block from all_events.text),
then compute status_summary_positions by calling .index(...) on that summary
substring and assert those positions are sorted; update uses of
status_summary_positions and all_events to operate on the extracted summary
string so the order assertion only checks the summary block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1feefb12-e173-482a-9110-7bbfb2235fb9

📥 Commits

Reviewing files that changed from the base of the PR and between 00ca4f2 and c1b7895.

📒 Files selected for processing (1)
  • tests/test_security.py

@LubuSeb
Copy link
Copy Markdown
Contributor Author

LubuSeb commented May 25, 2026

Updated again in 58346248c4ae20bc42d03f84f172ef926aa3d1e4 to scope the ordering assertion to the rendered .bounty-list-summary block, rather than the whole page.

Validation after this commit:

  • pytest -q -> 318 passed
  • ruff check app/main.py tests/test_security.py -> passed
  • ruff format --check app/main.py tests/test_security.py -> passed
  • mypy app -> success
  • git diff --check origin/main...HEAD -> clean

@ramimbo ramimbo merged commit 86ec7ae into ramimbo:main May 26, 2026
2 checks passed
@ramimbo ramimbo added mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded labels May 26, 2026
@coderabbitai coderabbitai Bot mentioned this pull request May 26, 2026
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants