Skip to content

feat: add published report assistant and charts#29

Merged
ECWireless merged 2 commits into
mainfrom
codex/published-report-assistant
Jun 29, 2026
Merged

feat: add published report assistant and charts#29
ECWireless merged 2 commits into
mainfrom
codex/published-report-assistant

Conversation

@ECWireless

@ECWireless ECWireless commented Jun 29, 2026

Copy link
Copy Markdown
Member

This pull request adds a new "Report Assistant" feature for published quarter reports, allowing users to ask questions and receive AI-generated analyses and rankings. It also introduces environment/configuration changes to support development behind HTTPS proxies, and improves the admin flow for publishing quarters with better error handling and feedback.

Key changes:

1. Report Assistant Feature

2. Development Environment Improvements

  • Updates .env.example and next.config.ts to support specifying allowed dev origins and running Next.js behind a local HTTPS proxy or remote tunnel. [1] [2]
  • Adds a new dev:proxy script for running the dev server on a proxy-friendly port/host, and documents the setup in README.md. [1] [2]

3. Admin Quarter Publishing UX

  • Refactors the quarter status update flow to use useActionState for better error handling and feedback, displaying errors to the user and closing the modal on success. [1] [2] [3] [4] [5]

Summary by CodeRabbit

  • New Features

    • Added a published report assistant with suggested prompts, reply history, pinning, and quick visual summaries.
    • Added report charts to make quarter metrics easier to scan.
    • Added support for using a local HTTPS proxy or development tunnel, plus a new proxy dev command.
  • Bug Fixes

    • Improved publish confirmation handling with clearer loading and error states.
    • Added better handling for restricted or unavailable report assistant requests.

Copilot AI review requested due to automatic review settings June 29, 2026 14:24
@vercel

vercel Bot commented Jun 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
raidguild-accounting Ready Ready Preview, Comment Jun 29, 2026 3:16pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ECWireless, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 23fe969a-0d31-4e99-ae99-34fb923dbea7

📥 Commits

Reviewing files that changed from the base of the PR and between caba88a and c88bc41.

📒 Files selected for processing (13)
  • README.md
  • drizzle/0018_workable_miss_america.sql
  • drizzle/meta/0018_snapshot.json
  • drizzle/meta/_journal.json
  • src/app/admin/quarters/actions.ts
  • src/app/api/reports/quarters/[id]/assistant/route.ts
  • src/app/reports/quarters/[id]/page.tsx
  • src/components/reports/report-assistant.tsx
  • src/db/schema.ts
  • src/lib/quarter-report.ts
  • src/lib/report-assistant/openai-planner.ts
  • src/lib/report-assistant/query-executor.ts
  • src/lib/report-assistant/rate-limit.ts
📝 Walkthrough

Walkthrough

Adds an AI-powered report assistant backed by OpenAI to published quarter report pages, along with static report charts. Extends QuarterReportData with expense breakdown and raid economics. Introduces server-side prompt guard, plan validator, OpenAI planner, and query executor. Adds a rate-limited API route and client-side ReportAssistant UI with localStorage-pinned responses. Also improves quarter publish confirmation with useActionState and adds a dev proxy setup.

Changes

Dev Proxy Setup

Layer / File(s) Summary
Dev proxy script, config, and docs
package.json, next.config.ts, .env.example, README.md
Adds dev:proxy npm script, parses NEXT_ALLOWED_DEV_ORIGINS into Next.js allowedDevOrigins, and documents the proxy workflow including required env variables and port binding.

Report Assistant & Charts

Layer / File(s) Summary
Report assistant types and QuarterReportData extensions
src/lib/report-assistant/types.ts, src/lib/quarter-report.ts, .env.example
Defines all report assistant TypeScript types (ReportAssistantIntent, ReportAssistantPlan, ReportAssistantResponse, etc.) and extends QuarterReportData with expenseBreakdown and raidEconomics, adding getQuarterRaidEconomicsRows computation and new OpenAI env variable documentation.
Prompt guard and plan validator
src/lib/report-assistant/prompt-guard.ts, src/lib/report-assistant/query-validator.ts
Adds server-only prompt sanitization (blocked patterns, length limit, whitespace normalization) and plan validation (intent/chart/reason type guards, limit range normalization).
OpenAI planner
src/lib/report-assistant/openai-planner.ts
Implements planReportAssistantQuery with regex-based deterministic/unsupported heuristics, a strict JSON schema-constrained OpenAI Responses API call, response text extraction, and validated plan return.
Query executor
src/lib/report-assistant/query-executor.ts
Implements executeReportAssistantPlan branching by intent: unsupported messaging, quarter summary, top-N queries (raids/clients/subcontractors/providers), month breakdowns, and default category-totals aggregation with chart and provenance assembly.
Assistant API route with rate limiting
src/app/api/reports/quarters/[id]/assistant/route.ts
Adds the POST route with session auth, quarter access/publish checks, per-wallet rate limiting (12 req/60 s), prompt guard, OpenAI planning, report data fetch, plan execution, and error mapping to 429/400.
ReportCharts component
src/components/reports/report-charts.tsx
Adds ReportCharts composing QuarterFlowChart, OutflowMixChart, and TopRaidRevenueChart, each computing proportional bar widths from QuarterReportData, with shared ChartShell/EmptyChart presentational wrappers.
ReportAssistant client component
src/components/reports/report-assistant.tsx
Adds client-side ReportAssistant with localStorage-pinned responses, MiniChart (pie/bar), AssistantCard, client-side prompt validation, suggested prompts, async POST to the assistant API, and pending/toast state management.
Quarter publish action state and confirmation UI
src/app/admin/quarters/actions.ts, src/app/admin/quarters/publish-quarter-confirmation.tsx
Adds QuarterStatusFormState type and updateQuarterStatusWithState server action wrapper, then updates the publish confirmation dialog to use useActionState with pending, error display, and auto-close on success.
Quarter report page wiring
src/app/reports/quarters/[id]/page.tsx
Inserts ReportCharts and conditionally renders ReportAssistant (for published quarters only) keyed by quarter ID and wallet address.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ReportAssistant
  participant AssistantRoute as POST /assistant
  participant planReportAssistantQuery
  participant executeReportAssistantPlan

  User->>ReportAssistant: Submit prompt
  ReportAssistant->>ReportAssistant: Client-side prompt validation
  ReportAssistant->>AssistantRoute: POST { prompt }
  AssistantRoute->>AssistantRoute: Auth + rate limit check
  AssistantRoute->>AssistantRoute: guardReportAssistantPrompt
  AssistantRoute->>planReportAssistantQuery: sanitized prompt
  planReportAssistantQuery->>planReportAssistantQuery: Deterministic/unsupported heuristics
  planReportAssistantQuery-->>AssistantRoute: ReportAssistantPlan (or OpenAI call)
  AssistantRoute->>executeReportAssistantPlan: plan + quarter + report
  executeReportAssistantPlan-->>AssistantRoute: ReportAssistantResponse
  AssistantRoute-->>ReportAssistant: JSON response
  ReportAssistant->>ReportAssistant: Prepend to answers, update localStorage pins
  ReportAssistant-->>User: Render AssistantCard
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • raid-guild/accounting#2: Both PRs update .env.example with inline documentation for the Base64-encoded ENCRYPTION_KEY format.
  • raid-guild/accounting#9: The updateQuarterStatusWithState added here directly wraps updateQuarterStatus introduced in that PR's quarter admin status logic.
  • raid-guild/accounting#24: Both PRs modify updateQuarterStatus behavior and the publish confirmation flow in src/app/admin/quarters/actions.ts.

Poem

🐇 A rabbit asked the ledger: "Who earned the most?"
The assistant replied with a glowing toast.
Charts bloomed like clover across the screen,
Pinned responses stored, tidy and clean.
With guards and planners hopping through the code,
The quarter's secrets finally showed! 🌟

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main feature addition: a published report assistant with charts.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/published-report-assistant

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds an AI-powered “Report Assistant” experience for published quarter reports (API + UI) and introduces new report charts, alongside small dev/proxy configuration updates and improved admin publishing feedback.

Changes:

  • Added a new report assistant backend pipeline (prompt guard → OpenAI planning → validated plan execution over published report data).
  • Added new report UI components for assistant Q&A (with pinning) and new chart visuals, wired into the quarter report page.
  • Improved local dev ergonomics (allowed dev origins + proxy-friendly dev script) and enhanced quarter publishing UX with useActionState.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/lib/report-assistant/types.ts Defines assistant intents, plan, and response payload types.
src/lib/report-assistant/query-validator.ts Validates/normalizes the planned query structure coming from the planner.
src/lib/report-assistant/query-executor.ts Executes validated assistant plans against QuarterReportData to produce answers/tables/charts.
src/lib/report-assistant/prompt-guard.ts Sanitizes/blocks unsafe or irrelevant prompts and enforces length limits.
src/lib/report-assistant/openai-planner.ts Uses OpenAI Responses API to turn prompts into structured assistant plans (with deterministic shortcuts).
src/lib/quarter-report.ts Extends quarter report data shape (expense breakdown + raid economics) used by new UI/assistant features.
src/components/reports/report-charts.tsx Adds new chart components to visualize quarter flow, outflow mix, and top raids.
src/components/reports/report-assistant.tsx Adds the client-side assistant UI with suggested prompts, tables/charts rendering, and pinned responses.
src/app/reports/quarters/[id]/page.tsx Integrates the new charts and assistant into the published quarter report page.
src/app/api/reports/quarters/[id]/assistant/route.ts Implements the assistant API endpoint (authz, prompt guard, plan, execute, basic rate limit, logging).
src/app/admin/quarters/publish-quarter-confirmation.tsx Refactors publish confirmation modal to use useActionState and surface errors/pending state.
src/app/admin/quarters/actions.ts Adds a stateful action wrapper returning {saved,error} for useActionState.
README.md Documents dev/proxy workflow and configuration for allowed dev origins.
package.json Adds dev:proxy script for proxy-friendly dev server settings.
next.config.ts Adds allowedDevOrigins configuration from env.
.env.example Documents new env vars (allowed dev origins + OpenAI configuration).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lib/report-assistant/query-executor.ts Outdated
Comment thread src/lib/report-assistant/query-executor.ts Outdated
Comment thread src/lib/quarter-report.ts
Comment thread src/components/reports/report-assistant.tsx Outdated
Comment thread src/app/api/reports/quarters/[id]/assistant/route.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 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 `@README.md`:
- Around line 29-45: The proxy connection target in the README is inconsistent
with the dev server binding used by dev:proxy. Update the documented host
reference to match the actual bind address, or change the package.json dev:proxy
script to bind to localhost instead; keep the README and the dev server
definition aligned by referencing the same host in both places.

In `@src/app/admin/quarters/actions.ts`:
- Around line 257-264: The catch in updateQuarterStatus is mapping every thrown
Error into QuarterStatusFormState, which hides non-validation failures. Update
the updateQuarterStatus/formData flow to only convert known business-rule
failures into the returned form state, and rethrow unexpected errors so DB,
audit, or runtime issues are not treated as normal validation errors.

In `@src/app/api/reports/quarters/`[id]/assistant/route.ts:
- Around line 15-33: The current rate limiting in checkRateLimit uses an
in-memory Map, which is only per process and can be bypassed across instances.
Replace the local rateLimits store in this route with a shared backend-backed
limiter keyed by wallet + quarter, and update the checkRateLimit flow in the
assistant route to read/write through that shared store before allowing OpenAI
access.
- Around line 89-91: The error handling in the assistant route is leaking
internal planner/provider details through errorResponse, so update the logic in
the route handler to only return explicit validation or rate-limit messages to
clients. In the relevant error mapping around errorResponse, treat known
rate-limit cases as 429, return user-safe validation messages when intentionally
thrown, and map all other unexpected errors from the assistant/planner flow to a
generic 500 response instead of error.message.
- Around line 69-86: The report assistant logs in the route handler are exposing
a persistent user identifier via actorWalletAddress. Update the logging in the
query and error paths in the assistant route to avoid raw wallet addresses by
redacting, hashing, or omitting the value entirely. Keep the existing
report_assistant_query and report_assistant_error logging structure, but replace
the direct session.address usage with a non-identifying representation.

In `@src/components/reports/report-assistant.tsx`:
- Around line 38-48: `getStoredPinnedResponses` currently returns any parsed
array as `ReportAssistantResponse[]`, so malformed localStorage entries can
later break `getResponseKey()` or `AssistantCard` rendering. Update this
function in `report-assistant.tsx` to validate each parsed item with a runtime
guard before returning it, filtering out entries missing required fields like
`plan` or `provenance` and only storing validated responses in state.

In `@src/lib/report-assistant/openai-planner.ts`:
- Around line 195-236: Add a request timeout to the OpenAI planner fetch so the
assistant route cannot hang indefinitely. In openai-planner.ts, update the
response request around the fetch call to use an AbortController (or equivalent
timeout helper) and pass its signal into the OpenAI request, then clear the
timer afterward. If the timeout fires, abort the request and return a controlled
planner error from the same flow that handles fetch failures so callers get a
predictable response instead of waiting for platform aborts.

In `@src/lib/report-assistant/query-executor.ts`:
- Around line 216-224: The monthly breakdown sorting in
summarizeCategoriesByMonth currently orders all results by value, which is only
correct when selecting a single winner. Update the sorting logic so
revenue_by_month and expenses_by_month with limit === 1 keep the value-based
descending sort, but when limit is null or greater than 1, return results in
chronological monthKey order instead. Make the change in
summarizeCategoriesByMonth and apply the same rule to the related monthly result
handling around the referenced block so the month breakdown remains
chronological.
- Around line 403-439: Handle the expenses-by-category query before the generic
fallback aggregation in query-executor’s category summary logic, so
`expenses_by_category` does not reuse `REPORT_TOTAL_CATEGORIES` and return
revenue-style rows. Update the branching in `query-executor.ts` around the
category table construction to route `expenses_by_category` to its own
expense-only category mapping/labels first, then keep the existing fallback for
other category questions. Use the existing symbols `REPORT_TOTAL_CATEGORIES`,
`getCategoryLabel`, and the `makeResponse`/`chartFromRows` flow to keep the fix
localized.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: cf7b8fbf-ce29-470c-9d13-cf94f6e1bc14

📥 Commits

Reviewing files that changed from the base of the PR and between 95905e3 and caba88a.

📒 Files selected for processing (16)
  • .env.example
  • README.md
  • next.config.ts
  • package.json
  • src/app/admin/quarters/actions.ts
  • src/app/admin/quarters/publish-quarter-confirmation.tsx
  • src/app/api/reports/quarters/[id]/assistant/route.ts
  • src/app/reports/quarters/[id]/page.tsx
  • src/components/reports/report-assistant.tsx
  • src/components/reports/report-charts.tsx
  • src/lib/quarter-report.ts
  • src/lib/report-assistant/openai-planner.ts
  • src/lib/report-assistant/prompt-guard.ts
  • src/lib/report-assistant/query-executor.ts
  • src/lib/report-assistant/query-validator.ts
  • src/lib/report-assistant/types.ts

Comment thread README.md
Comment thread src/app/admin/quarters/actions.ts Outdated
Comment thread src/app/api/reports/quarters/[id]/assistant/route.ts
Comment thread src/app/api/reports/quarters/[id]/assistant/route.ts
Comment thread src/app/api/reports/quarters/[id]/assistant/route.ts Outdated
Comment thread src/components/reports/report-assistant.tsx Outdated
Comment thread src/lib/report-assistant/openai-planner.ts Outdated
Comment thread src/lib/report-assistant/query-executor.ts
Comment thread src/lib/report-assistant/query-executor.ts
@ECWireless ECWireless merged commit 36d8895 into main Jun 29, 2026
5 checks passed
@ECWireless ECWireless deleted the codex/published-report-assistant branch June 29, 2026 15:32
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.

2 participants