Skip to content

A07 — Review accountability analytics API ​

Status: in progress — protected API in PR #95; #41/#42/#68 and database evidence remain open. Updated: 2026-09-12. Assigned owner: smart analytics owner with bounded contract/service/test agents. Pure implementation: backend #80, merged 216fd63. Protected API: backend #95, commit 4a08fe3, stacked on #93.

Issues and acceptance covered ​

#52. The acceptance boundary is the implementation scope and completion checks below; see the issue acceptance matrix for parent coverage. Shared definitions: financial contract; proof anchors: evidence index.

Dependencies and blockers ​

A01 backend #78, which is the current stacked base; #41/#42 committed canonical review event contract, coordinated with #68. Frontend #31 (517379e) and backend #86/#87 landed on dev; dev-targeted carry-forwards #91/#92/#93 remain open and off dev. A07 PR #95 is stacked on #93. The payout-review adapter branch feature/review-payout-events remains an independent sibling. Known #42 producer coverage remains incomplete. #43 owns queue search/derived-sort repair if reused. The protected API is review-ready, but complete live claims still wait for normalized reliable reader coverage, #68 accountability data, and disposable database evidence.

Repository and expected files ​

Backend: implemented src/utils/analytics/reviews.ts, reviewAuditAdapter.ts, and focused tests; PR #95 adds the protected GET /api/admin/analytics/reviews router/service integration and contextual reads of the #41/#42/#68 normalized committed-event projection. Narrow admin.ts mount only.

Existing behavior and verified gap ​

Current status audit producer is best effort after mutation, has mixed actor identity, and misses automated/payout transition families. Queue/current track records are not historical reviewer activity (E11).

Proposed implementation boundary ​

Bounded committed decisions by period/campaign/reviewer/outcome and ordered submission context, with current queue counts separately labelled. Exclude denied attempts/duplicates; expose incomplete historical coverage. Reuse canonical events, not another audit store; producer repairs remain #41/#42/#68.

Expected API / data contract ​

Read-only review aggregate DTO: event counts, canonical actor reference safe for staff, from/to/reason/time, pagination, scope and event coverage. Optional latency only when both queue-entry and decision timestamps are evidenced; otherwise omit/unavailable.

Required tests ​

Duplicate commands versus distinct re-reviews; state stock versus event count; actor identity missing/legacy; denied attempt not counted as successful decision; ordered context and time boundaries; unauthorized staff; bounded result/query; no unrelated event payload leakage.

Suggested agent tier ​

Smart owner validates event/actor semantics and privacy. Lower-cost agent adds agreed endpoint wiring and count fixtures.

Expected PR boundary and reason ​

One review analytics API PR stacked on reliable event contract. Independently mergeable from financial UI; unlocks A14. No moderation mutation/queue performance redesign. Keep compatibility additive, avoid unrelated cleanup, and list exact stacked commits and later units unlocked in the PR. If observed scope grows beyond this boundary, update the plan before splitting or adding work.

RBAC requirements / TODOs ​

Preserve submission-moderation action guard. TODO(RBAC): Require approved reviewer-accountability access for actor activity and decision reasons; this exposes internal staff performance and creator moderation history.

Completion and reconciliation checks ​

Every counted decision is one committed event. Sum by reviewer/outcome = filtered event total, including explicit unknown actor bucket. Current queue stock is never substituted for historical activity.

Record actual tests, source schema/contract versions, PR/merge SHA, manual evidence and residual coverage before changing status to review/complete. Any unexpected migration must first satisfy the migration gates; never bundle upstream financial writer work into this analytics unit.

Current #41 reader follow-up ​

The dev-targeted #41 history reader carry-forward is backend PR #93 (151a80f), open and stacked beneath #95. It reads normalized v1/v2 events newest-first by (occurredAt,recordedAt,eventId), reports legacy/malformed diagnostics as partial, preserves the current SUBMISSION_MODERATION guard and exact TODO(RBAC), and introduces no migration or backfill. Rebase open siblings onto dev as parents land, then run disposable PostgreSQL behavioral evidence for transition/history ordering. Do not mark #41/#42 complete until merges and database evidence pass; afterward finalize A07/A02 historical modes.

Merge-topology correction (2026-09-12): backend dev is d937bfe with #86/#87 landed, frontend dev is e4b5f5c with #31 landed. Dev-targeted carry-forwards #91 (eaee854, scraper), #92 (9f38877, payout), and #93 (151a80f, history) are OPEN and off dev. A07 PR #95 (4a08fe3) is stacked on #93; A02 historical status is active on feature/performance-historical-status, stacked on #95. No TEST_DATABASE_URL is configured, configured databases are remote/non-test, and local PostgreSQL is down, so disposable transition/history-ordering evidence remains blocked. #41/#42 remain incomplete until merges and database evidence pass.

Implementation evidence ​

  • Pure projection #80 merged at 216fd63. #41/#42 implementation reuses canonical AuditEvent; it will not introduce a second moderation-history store.
  • Active producer evidence: frontend #31 at 517379e has three helper tests plus TypeScript/build validation for expectedStatus, commandId, and denial reason; backend #86 at f1d7096 has four tests/build and no migration for the v2 required AuditEvent contract; stacked backend #87 at edfb007 has 12 transition tests, three schema tests and build for atomic admin transition, current CPM clamp, notification, and event; scraper adapter backend #88 at 614120f has 14 focused tests/build and is stacked on #87; payout adapter backend #89 at 1ff5a50 has four focused tests/build, no migration, and no payment call, as a sibling atop #87. Deploy frontend #31 before backend #87; rollback retains v2 facts. The payout-review adapter branch feature/review-payout-events is active from #87 as an independent sibling. Known #42 producer coverage remains pending #87/#88/#89 merge, so #42 is not complete. No active Discord review writer exists because the dashboard owns that path. The scrape adapter branch remains active; #41's protected ordered history reader is in implementation on feature/review-history-reader.
  • Pure contract: platform/campaign scope, UTC [from,to) review-event windows, submission/actor/destination filters, exact daily buckets, stable newest-first context pagination, and source coverage. No current queue field exists, so stock cannot be mistaken for event flow.
  • Reconciliation: each normalized committed command/submission target counts once; bulk commands across submissions and distinct re-reviews remain distinct. Full filtered counts reconcile by actor, toStatus, and day independently of the paged rows. Missing non-system identity has an explicit unknown count.
  • Current-event compatibility: only moderation.submission.status-changed@1 successful staff events with matching campaign/submission targets and before/after status data are accepted. Existing mixed actor IDs are not relabelled as webUserId; all remain unattributed, and best-effort historical coverage remains partial.
  • Privacy/security: rows expose only normalized transition fields, not generic AuditEvent payloads. A specific TODO(RBAC) requires the separately approved reviewer-accountability capability before a route returns actor IDs or reasons; no central mapping changed.
  • Validation: 17 focused A07 projection/adapter tests, 23 A01 tests, and the existing 11 rate tests passed; strict targeted TypeScript and full npm run build passed; pre-commit diff checks passed.
  • Residual gate: do not mark A07 complete until #41/#42/#68 supply atomic/idempotent normalized committed events and coverage, the protected route/query tests pass, and actor/outcome totals reconcile against a disposable database. A14 remains locked; #43 retains queue behavior.

PR #95 protected API evidence ​

Backend PR #95 (4a08fe3) is stacked on #93 and adds protected GET /api/admin/analytics/reviews. It uses the canonical bounded event query, normalizes v1/v2 events, reports partial diagnostics for incomplete or malformed coverage, aggregates before pagination, and preserves the existing SUBMISSION_MODERATION guard with the exact TODO(RBAC). It adds no platform filter, current-state inference, schema change, or migration. The SUBMISSION_MODERATION event family remains an exact TODO for producer coverage. Six review-related suites passed, along with the backend build and diff check.

Independent review corrections recorded in this slice: conflicting campaign attribution is excluded as malformed, and ordering uses recordedAt as part of the deterministic tie-break rather than treating occurredAt alone as sufficient. The PR is review-ready evidence, not A07 completion: #41/#42 remain incomplete, #68 normalized accountability coverage remains a blocker, and disposable loopback _test database evidence is still required. A14 remains locked.

PR #96 (d113a4e) is the dependent A02 historical-status slice stacked on #95. It consumes the ordered normalized history contract; no prior event, malformed event, campaign-conflicting event, or discontinuity makes the affected submission unknown, and historical mode does not query current accepted state. Its 11 analytics/routes suites, creator-route checks, build and diff check pass. No migration or RBAC map changed. Keep #41/#42/#91/#92/#93/#95/#96 open; #68 and the missing loopback _test evidence remain blockers.