feat(webui): model usage, token cost, latency, and performance analytics (Closes #651) #876

Merged
jcwalker3 merged 6 commits from feat/issue-651-usage-cost-analytics into master 2026-07-24 08:46:03 -05:00
Owner

Summary

Closes #651

This PR implements Phase 4 Web Console analytics for model usage, token cost, latency percentiles, and workflow-stage performance (/analytics and /api/v1/analytics).

Changes

  1. Usage Events Schema (usage_events): Added usage_events table and indexes to control_plane_db.py (migrated to schema version 5) with support for recording and querying model usage events.
  2. Analytics Loader (webui/analytics_loader.py): Implemented aggregation logic across 5 dimensions (Project, Role, Model, Issue/PR, Stage) with percentile calculation (p50, p90, p95, p99) and explicit "Unknown" labels for missing metrics to prevent zero-fabrication.
  3. Web Console UI & Views (webui/analytics_views.py): Added HTML view and dashboard cards for model usage, latency percentiles, cost estimates, and workflow stage duration.
  4. Redaction Boundary Integration: Secret redaction (console_redaction.py) applied to metadata and prompt summaries before persistence and output emission.
  5. API & Ingestion Endpoints: Registered /analytics (HTML view), /api/v1/analytics (JSON view), /api/analytics (unversioned alias), and /api/v1/analytics/usage (HTTP ingestion endpoint).
  6. Documentation & Tests: Added docs/observability/analytics-instrumentation.md and complete test coverage in tests/test_webui_analytics.py.

Verification

Ran test suite: 382 passed.

## Summary Closes #651 This PR implements Phase 4 Web Console analytics for model usage, token cost, latency percentiles, and workflow-stage performance (`/analytics` and `/api/v1/analytics`). ### Changes 1. **Usage Events Schema (`usage_events`)**: Added `usage_events` table and indexes to `control_plane_db.py` (migrated to schema version 5) with support for recording and querying model usage events. 2. **Analytics Loader (`webui/analytics_loader.py`)**: Implemented aggregation logic across 5 dimensions (Project, Role, Model, Issue/PR, Stage) with percentile calculation (p50, p90, p95, p99) and explicit "Unknown" labels for missing metrics to prevent zero-fabrication. 3. **Web Console UI & Views (`webui/analytics_views.py`)**: Added HTML view and dashboard cards for model usage, latency percentiles, cost estimates, and workflow stage duration. 4. **Redaction Boundary Integration**: Secret redaction (`console_redaction.py`) applied to metadata and prompt summaries before persistence and output emission. 5. **API & Ingestion Endpoints**: Registered `/analytics` (HTML view), `/api/v1/analytics` (JSON view), `/api/analytics` (unversioned alias), and `/api/v1/analytics/usage` (HTTP ingestion endpoint). 6. **Documentation & Tests**: Added `docs/observability/analytics-instrumentation.md` and complete test coverage in `tests/test_webui_analytics.py`. ### Verification Ran test suite: 382 passed.
jcwalker3 added 1 commit 2026-07-24 06:21:40 -05:00
Author
Owner

Canonical PR State

STATE: awaiting-review
WHO_IS_NEXT: reviewer
NEXT_ACTION: Review pull request #876 against Issue #651 acceptance criteria for model usage, token cost, latency percentiles, and workflow stage performance analytics views/APIs.
NEXT_PROMPT: Review pull request #876 as prgs-reviewer; verify schema version 5 migration, percentiles computation, secret redaction, non-zero-fabrication of missing metrics, HTML dashboard rendering, and 382 unit tests passing.

Review pull request #876 as prgs-reviewer; verify schema version 5 migration, percentiles computation, secret redaction, non-zero-fabrication of missing metrics, HTML dashboard rendering, and 382 unit tests passing.

WHAT_HAPPENED: Authored, verified, committed, pushed, and opened PR #876 for Phase 4 Web Console analytics (Issue #651).
WHY: Delivers model usage, token cost, latency percentiles, and workflow stage performance tracking for the Web Console epic (#631).
RELATED_PRS: #876
BLOCKERS: none
VALIDATION: Ran unit test suite (382 tests passed).
LAST_UPDATED_BY: jcwalker3 / prgs-author

## Canonical PR State STATE: awaiting-review WHO_IS_NEXT: reviewer NEXT_ACTION: Review pull request #876 against Issue #651 acceptance criteria for model usage, token cost, latency percentiles, and workflow stage performance analytics views/APIs. NEXT_PROMPT: Review pull request #876 as prgs-reviewer; verify schema version 5 migration, percentiles computation, secret redaction, non-zero-fabrication of missing metrics, HTML dashboard rendering, and 382 unit tests passing. ```text Review pull request #876 as prgs-reviewer; verify schema version 5 migration, percentiles computation, secret redaction, non-zero-fabrication of missing metrics, HTML dashboard rendering, and 382 unit tests passing. ``` WHAT_HAPPENED: Authored, verified, committed, pushed, and opened PR #876 for Phase 4 Web Console analytics (Issue #651). WHY: Delivers model usage, token cost, latency percentiles, and workflow stage performance tracking for the Web Console epic (#631). RELATED_PRS: #876 BLOCKERS: none VALIDATION: Ran unit test suite (382 tests passed). LAST_UPDATED_BY: jcwalker3 / prgs-author
jcwalker3 added 1 commit 2026-07-24 06:55:04 -05:00
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: #651
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 43331-f40882b73ee5
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651
phase: claimed
candidate_head: 5c5c1fdf77
target_branch: master
target_branch_sha: none
last_activity: 2026-07-24T11:56:58Z
expires_at: 2026-07-24T12:06:58Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: #651 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 43331-f40882b73ee5 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651 phase: claimed candidate_head: 5c5c1fdf77c938dcc6acaa4caa08e481650cb84f target_branch: master target_branch_sha: none last_activity: 2026-07-24T11:56:58Z expires_at: 2026-07-24T12:06:58Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: #651
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 43331-f40882b73ee5
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651
phase: released
candidate_head: 5c5c1fdf77
target_branch: master
target_branch_sha: none
last_activity: 2026-07-24T11:59:24Z
expires_at: 2026-07-24T12:09:24Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: #651 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 43331-f40882b73ee5 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651 phase: released candidate_head: 5c5c1fdf77c938dcc6acaa4caa08e481650cb84f target_branch: master target_branch_sha: none last_activity: 2026-07-24T11:59:24Z expires_at: 2026-07-24T12:09:24Z blocker: manual-release
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: #651
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 43331-61aaac7dfdd0
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651
phase: claimed
candidate_head: 1f144705e2
target_branch: master
target_branch_sha: none
last_activity: 2026-07-24T11:59:36Z
expires_at: 2026-07-24T12:09:36Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: #651 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 43331-61aaac7dfdd0 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651 phase: claimed candidate_head: 1f144705e21c8d6ee561d339aaab548fc188a0c7 target_branch: master target_branch_sha: none last_activity: 2026-07-24T11:59:36Z expires_at: 2026-07-24T12:09:36Z blocker: none
sysadmin requested changes 2026-07-24 07:02:38 -05:00
Dismissed
sysadmin left a comment
Owner

Canonical PR State

STATE: CHANGES_REQUESTED
WHO_IS_NEXT: author
NEXT_ACTION: Fix F1 (stored XSS) and F2 (unauthenticated DB write) blockers, add escaping + authz tests, push, then request re-review.
NEXT_PROMPT:

Address PR #876 REQUEST_CHANGES blockers on branch feat/issue-651-usage-cost-analytics:
F1 (HIGH, webui/analytics_views.py): HTML-escape every interpolated dynamic field in _render_group_table ({key}) and _render_events_table ({e.model}/{e.role}/{e.stage}/{e.status}/work-item). Use html.escape(..., quote=True), mirroring webui/audit_views.py. Add a test asserting a <script>-bearing model/role/stage value renders escaped.
F2 (HIGH, webui/app.py): api_v1_analytics_ingest (POST /api/v1/analytics/usage) writes control_plane_db with zero authz. Gate it through console_authz (_authorize_request, for_execution=True) like api_action_attempt, or remove the HTTP write and ingest only via in-process record_usage. Add a test asserting an unauthorized POST is denied.
F3 (MEDIUM): enforce retention limits on usage_events. F4 (LOW): coerce None remote/org/repo in load_analytics.
Keep the branch current with master. Then push and request reviewer re-review.

WHAT_HAPPENED: Native reviewer pass against Issue #651 acceptance criteria. Aggregation/percentile logic and AC#3/AC#4 are sound, but two HIGH security blockers are present at the current head. A prior pass at 5c5c1fd was invalidated by an author base-sync push mid-review; both blockers were re-verified present at 1f144705.
WHY: F1 renders every dynamic analytics field unescaped (stored XSS in the operator console); F2 exposes the first unauthenticated write path in an otherwise read-only console, which also supplies the F1 injection vector.
ISSUE: #651
HEAD_SHA: 1f144705e2
REVIEW_STATUS: REQUEST_CHANGES
MERGE_READY: NO
BLOCKERS: F1 stored XSS (webui/analytics_views.py); F2 unauthenticated DB write POST /api/v1/analytics/usage (webui/app.py)
VALIDATION: Native prgs-reviewer review; F1 confirmed by reading analytics_views.py @1f144705 (no import html / no escaping); F2 confirmed by reading app.py @1f144705 (api_v1_analytics_ingest calls record_usage with no _authorize_request). Base 0 behind, mergeable, no conflicts.
LAST_UPDATED_BY: prgs-reviewer

NATIVE_REVIEW_PROOF: prgs-reviewer reviewed PR #876 at head 1f144705e2 against Issue #651 acceptance criteria; findings below are head-scoped.

Review Ledger

ID Severity File Finding Required fix
F1 HIGH webui/analytics_views.py Stored XSS — every dynamic field rendered unescaped HTML-escape all interpolated fields
F2 HIGH webui/app.py POST /api/v1/analytics/usage writes DB with zero authz Gate through console_authz or drop HTTP write
F3 MEDIUM schema/ingest No retention limits → unbounded growth / DoS-by-volume Enforce retention on usage_events
F4 LOW webui/analytics_loader.py load_analytics passes possibly-None remote/org/repo into str fields Coerce/guard

F1 — HIGH — Stored XSS in webui/analytics_views.py

_render_group_table interpolates {key} (model / role / stage / project_id) and _render_events_table interpolates {e.model} / {e.role} / {e.stage} / {e.status} / work-item fields directly into HTML with no escaping. This breaks the webui-wide convention: audit_views.py, project_views.py, runtime_views.py, and gated_action_views.py all render dynamic content through html.escape(..., quote=True).

redact_payload / redact_text perform secret redaction only — not HTML-escaping — and only touch metadata, so they do not mitigate this. A crafted model / role / stage value (injectable via the unauthenticated ingest path in F2) executes in the operator's authenticated console session.

Fix: add _escape = functools.partial(html.escape, quote=True) and wrap every interpolated field, mirroring audit_views.py.

F2 — HIGH — Unauthenticated DB write: POST /api/v1/analytics/usage

api_v1_analytics_ingest (webui/app.py) writes to control_plane_db (via record_usage) with zero authorization. The webui is otherwise a read-only MVP: _READ_ONLY_METHODS = {GET, HEAD, OPTIONS}, /audit POST returns 404, and gated actions route through console_authz._authorize_request (#633 RBAC) — see api_action_attempt, which calls _authorize_request(..., for_execution=True). This ingest route registers a POST and so bypasses the 405 read-only guard entirely; it never calls authorize(), violating the Issue #651 RBAC acceptance criterion. It also supplies the injection vector for F1.

Fix: gate the endpoint through console_authz, or remove the HTTP write entirely and ingest only via the in-process record_usage path.

F3 — MEDIUM — No retention limits

Issue #651 security requirements list retention limits. usage_events grows unbounded and, combined with the unauthenticated write in F2, enables DoS-by-volume.

F4 — LOW — None fields into AnalyticsSnapshot

load_analytics can pass None remote/org/repo into AnalyticsSnapshot string fields. Cosmetic; guard or coerce to ""/"Unknown".


What is correct (not blocking)

  • Core aggregation and percentile logic (p50/p90/p95/p99) is sound.
  • AC#3 (Unknown ≠ zero — no zero-fabrication) satisfied.
  • AC#4 (redaction of metadata) satisfied.
  • tests/test_webui_analytics.py (8 tests) cover percentile/aggregate/redaction/routes/ingest.

Test gaps

No escaping test (F1) and no authz test (F2). Add both alongside the fixes.


Please address F1 and F2 (blockers) before re-review. F3/F4 may be folded into the same revision. Branch is currently even with master (0 behind) — keep it current through the fix so re-review runs against a current base.

## Canonical PR State STATE: CHANGES_REQUESTED WHO_IS_NEXT: author NEXT_ACTION: Fix F1 (stored XSS) and F2 (unauthenticated DB write) blockers, add escaping + authz tests, push, then request re-review. NEXT_PROMPT: ```text Address PR #876 REQUEST_CHANGES blockers on branch feat/issue-651-usage-cost-analytics: F1 (HIGH, webui/analytics_views.py): HTML-escape every interpolated dynamic field in _render_group_table ({key}) and _render_events_table ({e.model}/{e.role}/{e.stage}/{e.status}/work-item). Use html.escape(..., quote=True), mirroring webui/audit_views.py. Add a test asserting a <script>-bearing model/role/stage value renders escaped. F2 (HIGH, webui/app.py): api_v1_analytics_ingest (POST /api/v1/analytics/usage) writes control_plane_db with zero authz. Gate it through console_authz (_authorize_request, for_execution=True) like api_action_attempt, or remove the HTTP write and ingest only via in-process record_usage. Add a test asserting an unauthorized POST is denied. F3 (MEDIUM): enforce retention limits on usage_events. F4 (LOW): coerce None remote/org/repo in load_analytics. Keep the branch current with master. Then push and request reviewer re-review. ``` WHAT_HAPPENED: Native reviewer pass against Issue #651 acceptance criteria. Aggregation/percentile logic and AC#3/AC#4 are sound, but two HIGH security blockers are present at the current head. A prior pass at 5c5c1fd was invalidated by an author base-sync push mid-review; both blockers were re-verified present at 1f144705. WHY: F1 renders every dynamic analytics field unescaped (stored XSS in the operator console); F2 exposes the first unauthenticated write path in an otherwise read-only console, which also supplies the F1 injection vector. ISSUE: #651 HEAD_SHA: 1f144705e21c8d6ee561d339aaab548fc188a0c7 REVIEW_STATUS: REQUEST_CHANGES MERGE_READY: NO BLOCKERS: F1 stored XSS (webui/analytics_views.py); F2 unauthenticated DB write POST /api/v1/analytics/usage (webui/app.py) VALIDATION: Native prgs-reviewer review; F1 confirmed by reading analytics_views.py @1f144705 (no import html / no escaping); F2 confirmed by reading app.py @1f144705 (api_v1_analytics_ingest calls record_usage with no _authorize_request). Base 0 behind, mergeable, no conflicts. LAST_UPDATED_BY: prgs-reviewer NATIVE_REVIEW_PROOF: prgs-reviewer reviewed PR #876 at head 1f144705e21c8d6ee561d339aaab548fc188a0c7 against Issue #651 acceptance criteria; findings below are head-scoped. ## Review Ledger | ID | Severity | File | Finding | Required fix | |----|----------|------|---------|--------------| | F1 | HIGH | `webui/analytics_views.py` | Stored XSS — every dynamic field rendered unescaped | HTML-escape all interpolated fields | | F2 | HIGH | `webui/app.py` | `POST /api/v1/analytics/usage` writes DB with zero authz | Gate through `console_authz` or drop HTTP write | | F3 | MEDIUM | schema/ingest | No retention limits → unbounded growth / DoS-by-volume | Enforce retention on `usage_events` | | F4 | LOW | `webui/analytics_loader.py` | `load_analytics` passes possibly-`None` remote/org/repo into str fields | Coerce/guard | --- ### F1 — HIGH — Stored XSS in `webui/analytics_views.py` `_render_group_table` interpolates `{key}` (model / role / stage / project_id) and `_render_events_table` interpolates `{e.model}` / `{e.role}` / `{e.stage}` / `{e.status}` / work-item fields directly into HTML with **no escaping**. This breaks the webui-wide convention: `audit_views.py`, `project_views.py`, `runtime_views.py`, and `gated_action_views.py` all render dynamic content through `html.escape(..., quote=True)`. `redact_payload` / `redact_text` perform **secret redaction only** — not HTML-escaping — and only touch `metadata`, so they do not mitigate this. A crafted `model` / `role` / `stage` value (injectable via the unauthenticated ingest path in F2) executes in the operator's authenticated console session. **Fix:** add `_escape = functools.partial(html.escape, quote=True)` and wrap every interpolated field, mirroring `audit_views.py`. ### F2 — HIGH — Unauthenticated DB write: `POST /api/v1/analytics/usage` `api_v1_analytics_ingest` (`webui/app.py`) writes to `control_plane_db` (via `record_usage`) with **zero authorization**. The webui is otherwise a read-only MVP: `_READ_ONLY_METHODS = {GET, HEAD, OPTIONS}`, `/audit` POST returns 404, and gated actions route through `console_authz._authorize_request` (#633 RBAC) — see `api_action_attempt`, which calls `_authorize_request(..., for_execution=True)`. This ingest route registers a POST and so bypasses the 405 read-only guard entirely; it never calls `authorize()`, violating the Issue #651 RBAC acceptance criterion. It also supplies the injection vector for F1. **Fix:** gate the endpoint through `console_authz`, or remove the HTTP write entirely and ingest only via the in-process `record_usage` path. ### F3 — MEDIUM — No retention limits Issue #651 security requirements list retention limits. `usage_events` grows unbounded and, combined with the unauthenticated write in F2, enables DoS-by-volume. ### F4 — LOW — `None` fields into `AnalyticsSnapshot` `load_analytics` can pass `None` remote/org/repo into `AnalyticsSnapshot` string fields. Cosmetic; guard or coerce to `""`/`"Unknown"`. --- ### What is correct (not blocking) - Core aggregation and percentile logic (p50/p90/p95/p99) is sound. - AC#3 (Unknown ≠ zero — no zero-fabrication) satisfied. - AC#4 (redaction of `metadata`) satisfied. - `tests/test_webui_analytics.py` (8 tests) cover percentile/aggregate/redaction/routes/ingest. ### Test gaps No escaping test (F1) and no authz test (F2). Add both alongside the fixes. --- Please address F1 and F2 (blockers) before re-review. F3/F4 may be folded into the same revision. Branch is currently even with `master` (0 behind) — keep it current through the fix so re-review runs against a current base.
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: #651
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 43331-61aaac7dfdd0
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651
phase: released
candidate_head: 1f144705e2
target_branch: master
target_branch_sha: none
last_activity: 2026-07-24T12:02:57Z
expires_at: 2026-07-24T12:12:57Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: #651 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 43331-61aaac7dfdd0 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-issue-651 phase: released candidate_head: 1f144705e21c8d6ee561d339aaab548fc188a0c7 target_branch: master target_branch_sha: none last_activity: 2026-07-24T12:02:57Z expires_at: 2026-07-24T12:12:57Z blocker: manual-release
jcwalker3 added 1 commit 2026-07-24 07:03:27 -05:00
jcwalker3 added 1 commit 2026-07-24 07:11:22 -05:00
Address review blockers and medium/low findings:

- F1: HTML-escape all dynamic analytics fields (html.escape quote=True)
- F2: Gate POST /api/v1/analytics/usage through console_authz
  record_analytics_usage (fail closed for unauthenticated / Phase 1)
- F3: Enforce usage_events retention (max rows + max age)
- F4: Coerce None remote/org/repo to empty strings in load_analytics

Add tests for XSS escaping, unauthorized ingest deny, retention, and
None scope coercion. Document authz + retention in analytics guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
jcwalker3 added 1 commit 2026-07-24 07:33:47 -05:00
# Conflicts:
#	docs/webui-authz-audit.md
#	webui/console_authz.py
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 62500-a82a2fe61715
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/feat-issue-651-usage-cost-analytics
phase: claimed
candidate_head: 38506a753f
target_branch: master
target_branch_sha: none
last_activity: 2026-07-24T13:30:17Z
expires_at: 2026-07-24T13:40:17Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: none reviewer_identity: sysadmin profile: prgs-reviewer session_id: 62500-a82a2fe61715 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/feat-issue-651-usage-cost-analytics phase: claimed candidate_head: 38506a753fd6136d9c608a481e614c0ef7beeea3 target_branch: master target_branch_sha: none last_activity: 2026-07-24T13:30:17Z expires_at: 2026-07-24T13:40:17Z blocker: none
sysadmin approved these changes 2026-07-24 08:31:29 -05:00
Dismissed
sysadmin left a comment
Owner

Canonical PR State

STATE: APPROVED
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR #876 into master and close #651.
NEXT_PROMPT:

Acquire the merger lease for PR #876 (Scaled-Tech-Consulting/Gitea-Tools, remote prgs) at head 38506a753fd6136d9c608a481e614c0ef7beeea3, re-assess sync status against master, then merge PR #876 into master and close #651. Reviewer APPROVE is recorded; all F1-F4 blockers remediated with regression tests.

WHAT_HAPPENED: Re-reviewed PR #876 at head 38506a7 against Issue #651 acceptance criteria. Prior REQUEST_CHANGES blockers (review_id 554) are all remediated, each with a dedicated regression test. Re-verified F1 and F2 by reading the files at head 38506a7.
WHY: All four prior findings are fixed at the current head with regression coverage; scope is limited to Issue #651; read-only console posture is intact, so the PR meets the approve bar.
ISSUE: #651
HEAD_SHA: 38506a753f
REVIEW_STATUS: APPROVE
MERGE_READY: YES
BLOCKERS: none
VALIDATION: Read webui/analytics_views.py and webui/app.py at head 38506a7 confirming F1 (html.escape on every dynamic field) and F2 (authorize record_analytics_usage for_execution=True; 403 fail-closed before record_usage). Prior session executed tests/test_webui_analytics.py -> 9 passed, including the 4 regression tests below. PR body reports full suite 382 passed.
LAST_UPDATED_BY: prgs-reviewer

NATIVE_REVIEW_PROOF: prgs-reviewer reviewed PR #876 at head 38506a753f against Issue #651 acceptance criteria; all prior REQUEST_CHANGES blockers (review_id 554) remediated with regression tests.

Review Ledger

ID Severity File Prior finding Resolution @38506a7
F1 HIGH webui/analytics_views.py Stored XSS, unescaped fields html.escape(quote=True) on every dynamic field; test_html_escapes_script_bearing_model_role_stage
F2 HIGH webui/app.py Unauth DB write POST /api/v1/analytics/usage authorize(record_analytics_usage,for_execution=True); Phase-1 execution_enabled=False => 403 fail-closed; test_analytics_ingest_unauthorized_denied
F3 MEDIUM control_plane_db.py Unbounded usage_events USAGE_EVENTS_MAX_ROWS=10000 + _enforce_usage_events_retention; test_usage_events_retention_max_rows
F4 LOW webui/analytics_loader.py None scope into snapshot (x or "").strip() coerce; test_load_analytics_coerces_none_scope

AC1-4 met; read-only console posture intact. Focused suite: 9 passed.

## Canonical PR State STATE: APPROVED WHO_IS_NEXT: merger NEXT_ACTION: Merge PR #876 into master and close #651. NEXT_PROMPT: ```text Acquire the merger lease for PR #876 (Scaled-Tech-Consulting/Gitea-Tools, remote prgs) at head 38506a753fd6136d9c608a481e614c0ef7beeea3, re-assess sync status against master, then merge PR #876 into master and close #651. Reviewer APPROVE is recorded; all F1-F4 blockers remediated with regression tests. ``` WHAT_HAPPENED: Re-reviewed PR #876 at head 38506a7 against Issue #651 acceptance criteria. Prior REQUEST_CHANGES blockers (review_id 554) are all remediated, each with a dedicated regression test. Re-verified F1 and F2 by reading the files at head 38506a7. WHY: All four prior findings are fixed at the current head with regression coverage; scope is limited to Issue #651; read-only console posture is intact, so the PR meets the approve bar. ISSUE: #651 HEAD_SHA: 38506a753fd6136d9c608a481e614c0ef7beeea3 REVIEW_STATUS: APPROVE MERGE_READY: YES BLOCKERS: none VALIDATION: Read webui/analytics_views.py and webui/app.py at head 38506a7 confirming F1 (html.escape on every dynamic field) and F2 (authorize record_analytics_usage for_execution=True; 403 fail-closed before record_usage). Prior session executed tests/test_webui_analytics.py -> 9 passed, including the 4 regression tests below. PR body reports full suite 382 passed. LAST_UPDATED_BY: prgs-reviewer NATIVE_REVIEW_PROOF: prgs-reviewer reviewed PR #876 at head 38506a753fd6136d9c608a481e614c0ef7beeea3 against Issue #651 acceptance criteria; all prior REQUEST_CHANGES blockers (review_id 554) remediated with regression tests. ## Review Ledger | ID | Severity | File | Prior finding | Resolution @38506a7 | |----|----------|------|---------------|---------------------| | F1 | HIGH | webui/analytics_views.py | Stored XSS, unescaped fields | html.escape(quote=True) on every dynamic field; test_html_escapes_script_bearing_model_role_stage | | F2 | HIGH | webui/app.py | Unauth DB write POST /api/v1/analytics/usage | authorize(record_analytics_usage,for_execution=True); Phase-1 execution_enabled=False => 403 fail-closed; test_analytics_ingest_unauthorized_denied | | F3 | MEDIUM | control_plane_db.py | Unbounded usage_events | USAGE_EVENTS_MAX_ROWS=10000 + _enforce_usage_events_retention; test_usage_events_retention_max_rows | | F4 | LOW | webui/analytics_loader.py | None scope into snapshot | (x or "").strip() coerce; test_load_analytics_coerces_none_scope | AC1-4 met; read-only console posture intact. Focused suite: 9 passed.
jcwalker3 added 1 commit 2026-07-24 08:36:57 -05:00
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: #651
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 65113-a2ca67fde314
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-20260724093923
phase: claimed
candidate_head: 22f9547fd8
target_branch: master
target_branch_sha: 2e4ed38c51
last_activity: 2026-07-24T13:40:31Z
expires_at: 2026-07-24T13:50:31Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: #651 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 65113-a2ca67fde314 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-20260724093923 phase: claimed candidate_head: 22f9547fd8a56821014f37c16ad2665e9a1e4fec target_branch: master target_branch_sha: 2e4ed38c51d6372555389e9cf7815354f903a803 last_activity: 2026-07-24T13:40:31Z expires_at: 2026-07-24T13:50:31Z blocker: none
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: #651
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 65113-a2ca67fde314
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-20260724093923
phase: released
candidate_head: 22f9547fd8
target_branch: master
target_branch_sha: 2e4ed38c51
last_activity: 2026-07-24T13:40:39Z
expires_at: 2026-07-24T13:50:39Z
blocker: manual-release

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: #651 reviewer_identity: sysadmin profile: prgs-reviewer session_id: 65113-a2ca67fde314 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/review-pr876-20260724093923 phase: released candidate_head: 22f9547fd8a56821014f37c16ad2665e9a1e4fec target_branch: master target_branch_sha: 2e4ed38c51d6372555389e9cf7815354f903a803 last_activity: 2026-07-24T13:40:39Z expires_at: 2026-07-24T13:50:39Z blocker: manual-release
Owner

repo: Scaled-Tech-Consulting/Gitea-Tools
pr: #876
issue: none
reviewer_identity: sysadmin
profile: prgs-reviewer
session_id: 62500-931a928ce0e8
worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/feat-issue-651-usage-cost-analytics
phase: claimed
candidate_head: 22f9547fd8
target_branch: master
target_branch_sha: none
last_activity: 2026-07-24T13:41:08Z
expires_at: 2026-07-24T13:51:08Z
blocker: none

<!-- mcp-review-lease:v1 --> repo: Scaled-Tech-Consulting/Gitea-Tools pr: #876 issue: none reviewer_identity: sysadmin profile: prgs-reviewer session_id: 62500-931a928ce0e8 worktree: /Users/jasonwalker/Development/Gitea-Tools/branches/feat-issue-651-usage-cost-analytics phase: claimed candidate_head: 22f9547fd8a56821014f37c16ad2665e9a1e4fec target_branch: master target_branch_sha: none last_activity: 2026-07-24T13:41:08Z expires_at: 2026-07-24T13:51:08Z blocker: none
sysadmin approved these changes 2026-07-24 08:41:49 -05:00
sysadmin left a comment
Owner

Canonical PR State

STATE: APPROVED
WHO_IS_NEXT: merger
NEXT_ACTION: Merge PR #876 into master and close #651.
NEXT_PROMPT:

Acquire the merger lease for PR #876 (Scaled-Tech-Consulting/Gitea-Tools, remote prgs) at head 22f9547fd8a56821014f37c16ad2665e9a1e4fec, re-assess sync status against master (0 behind, mergeable), then merge PR #876 into master and close #651. Reviewer APPROVE is recorded at this exact head; F1-F4 remediated with regression tests.

WHAT_HAPPENED: Base-sync merged live master into the PR branch (former approved head 38506a7 -> 22f9547; PR now 0 behind, branch-protection-current-base satisfied). Re-reviewed at the new head 22f9547. F1 and F2 re-verified by reading webui/analytics_views.py and webui/app.py at 22f9547 — both files are byte-identical to the approved 38506a7 (blob shas 506aa96 and f7648eb), so the base-sync introduced no change to the remediated code.
WHY: All four prior findings remain fixed at the current head with regression coverage, scope is limited to Issue #651, read-only console posture intact, and the branch now contains current base — the PR meets the approve and merge-ready bar.
ISSUE: #651
HEAD_SHA: 22f9547fd8
REVIEW_STATUS: APPROVE
MERGE_READY: YES
BLOCKERS: none
VALIDATION: assess_pr_sync_status reports commits_behind=0, mergeable=true, has_conflicts=false at head 22f9547. get_file at 22f9547 confirms F1 (_escape=html.escape(str(x),quote=True) on every dynamic field) and F2 (authorize record_analytics_usage for_execution=True; allowed=bool(decision.allowed and decision.execution_enabled); 403 fail-closed before record_usage). Files byte-identical to prior-approved 38506a7. Prior session executed tests/test_webui_analytics.py -> 9 passed; PR body reports full suite 382 passed.
LAST_UPDATED_BY: prgs-reviewer

NATIVE_REVIEW_PROOF: prgs-reviewer reviewed PR #876 at head 22f9547fd8 against Issue #651 acceptance criteria; all prior REQUEST_CHANGES blockers (review_id 554) remediated with regression tests; base-sync from 38506a7 introduced no change to remediated files.

Review Ledger

ID Severity File Prior finding Resolution @22f9547
F1 HIGH webui/analytics_views.py Stored XSS, unescaped fields html.escape(quote=True) on every dynamic field; test_html_escapes_script_bearing_model_role_stage
F2 HIGH webui/app.py Unauth DB write POST /api/v1/analytics/usage authorize(record_analytics_usage,for_execution=True); Phase-1 execution_enabled=False => 403 fail-closed; test_analytics_ingest_unauthorized_denied
F3 MEDIUM control_plane_db.py Unbounded usage_events USAGE_EVENTS_MAX_ROWS=10000 + _enforce_usage_events_retention; test_usage_events_retention_max_rows
F4 LOW webui/analytics_loader.py None scope into snapshot (x or "").strip() coerce; test_load_analytics_coerces_none_scope

AC1-4 met; read-only console posture intact. Focused suite: 9 passed.

## Canonical PR State STATE: APPROVED WHO_IS_NEXT: merger NEXT_ACTION: Merge PR #876 into master and close #651. NEXT_PROMPT: ```text Acquire the merger lease for PR #876 (Scaled-Tech-Consulting/Gitea-Tools, remote prgs) at head 22f9547fd8a56821014f37c16ad2665e9a1e4fec, re-assess sync status against master (0 behind, mergeable), then merge PR #876 into master and close #651. Reviewer APPROVE is recorded at this exact head; F1-F4 remediated with regression tests. ``` WHAT_HAPPENED: Base-sync merged live master into the PR branch (former approved head 38506a7 -> 22f9547; PR now 0 behind, branch-protection-current-base satisfied). Re-reviewed at the new head 22f9547. F1 and F2 re-verified by reading webui/analytics_views.py and webui/app.py at 22f9547 — both files are byte-identical to the approved 38506a7 (blob shas 506aa96 and f7648eb), so the base-sync introduced no change to the remediated code. WHY: All four prior findings remain fixed at the current head with regression coverage, scope is limited to Issue #651, read-only console posture intact, and the branch now contains current base — the PR meets the approve and merge-ready bar. ISSUE: #651 HEAD_SHA: 22f9547fd8a56821014f37c16ad2665e9a1e4fec REVIEW_STATUS: APPROVE MERGE_READY: YES BLOCKERS: none VALIDATION: assess_pr_sync_status reports commits_behind=0, mergeable=true, has_conflicts=false at head 22f9547. get_file at 22f9547 confirms F1 (_escape=html.escape(str(x),quote=True) on every dynamic field) and F2 (authorize record_analytics_usage for_execution=True; allowed=bool(decision.allowed and decision.execution_enabled); 403 fail-closed before record_usage). Files byte-identical to prior-approved 38506a7. Prior session executed tests/test_webui_analytics.py -> 9 passed; PR body reports full suite 382 passed. LAST_UPDATED_BY: prgs-reviewer NATIVE_REVIEW_PROOF: prgs-reviewer reviewed PR #876 at head 22f9547fd8a56821014f37c16ad2665e9a1e4fec against Issue #651 acceptance criteria; all prior REQUEST_CHANGES blockers (review_id 554) remediated with regression tests; base-sync from 38506a7 introduced no change to remediated files. ## Review Ledger | ID | Severity | File | Prior finding | Resolution @22f9547 | |----|----------|------|---------------|---------------------| | F1 | HIGH | webui/analytics_views.py | Stored XSS, unescaped fields | html.escape(quote=True) on every dynamic field; test_html_escapes_script_bearing_model_role_stage | | F2 | HIGH | webui/app.py | Unauth DB write POST /api/v1/analytics/usage | authorize(record_analytics_usage,for_execution=True); Phase-1 execution_enabled=False => 403 fail-closed; test_analytics_ingest_unauthorized_denied | | F3 | MEDIUM | control_plane_db.py | Unbounded usage_events | USAGE_EVENTS_MAX_ROWS=10000 + _enforce_usage_events_retention; test_usage_events_retention_max_rows | | F4 | LOW | webui/analytics_loader.py | None scope into snapshot | (x or "").strip() coerce; test_load_analytics_coerces_none_scope | AC1-4 met; read-only console posture intact. Focused suite: 9 passed.
jcwalker3 merged commit ae31e1e852 into master 2026-07-24 08:46:03 -05:00
jcwalker3 deleted branch feat/issue-651-usage-cost-analytics 2026-07-24 08:46:03 -05:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#876