Corrections is Signal's data-quality ticket queue, at route /corrections, visible to Admin-tier users and above (Admin, Gandalf, Sauron). It answers the question "which numbers in Signal have been reported as wrong, and what happened to those reports?" Anyone with drill-down access can flag a suspicious figure (revenue, outsource costs, gross profit/MGP, division, department, or other) via the "Flag Data Issue" form; admins triage each flag through a Pending → Reviewed → Resolved workflow. Everything on this screen — the queue, counts, and detail fields — comes exclusively from Signal's own records (a data_corrections table populated by users in Signal). Corrections never changes financial data itself; the underlying fix happens in the upstream source system (Vena), and resolving a flag in Signal is the human attestation that it was handled.
Field | Value |
Route | /corrections |
Access | Admin+ (route guard AdminRoute: requires isAdmin or isGandalf; non-qualifying users are redirected to /summary) |
Nav section | Admin — "Corrections" is the first link and the default landing route of the Admin nav section |
Primary data sources | Signal's own records (entered by users in Signal): the data_corrections table. No revenue system, payroll system, or external API is queried by this view. |
Writes | Signal's own records: insert new flags, update flag status/reviewer fields, delete pending flags — all in data_corrections |
Key code refs | src/views/CorrectionsView.tsx, src/components/FlagIssueModal.tsx, src/services/supabase.ts (getDataCorrections, submitDataCorrection, updateDataCorrection, deleteDataCorrection), src/App.tsx (AdminRoute, Admin nav section), supabase/migrations/20260312_data_corrections.sql, supabase/migrations/20260506_data_corrections_delete.sql |
Last verified | staging @ 98df0c4, verified 2026-07-07 |
Purpose
Signal displays financial and organizational data that originates in systems the app does not control — chiefly Vena, the source of the revenue, outsource-cost, and gross-profit figures shown across Signal. When someone spots a wrong number (a client's revenue looks inflated, a department is mislabeled, outsource costs are missing), Corrections gives them a structured "Flag Data Issue" path instead of scattered Slack messages or emails, and gives admins one accountable queue to review, annotate, and close those reports. The database schema comment states the intent: the flags are user-submitted reports of incorrect Vena revenue data, reviewed from this queue by the finance data owners (the migration comment names "Rodolfo's team — Amalia/Alexandra"; the submission form tells users "The finance team will review this").
Corrections does not change any financial number. It is a workflow and audit trail only. The actual data fix happens upstream in Vena; marking a flag "Resolved" in Signal is a human attestation that the issue was handled — the app never verifies that the upstream value actually changed.
Access & visibility
Route guard: /corrections is wrapped in AdminRoute in src/App.tsx. AdminRoute allows users where isAdmin OR isGandalf is true; everyone else is redirected to /summary. (Sauron, the super-admin tier, auto-sets both flags, so Sauron users also pass.)
How the flag is granted: isAdmin and isGandalf are read from Signal's own records — the app_users table (columns is_admin, is_gandalf, matched on the user's Google email) — by checkAdminStatus in src/context/AuthContext.tsx. Results are cached in sessionStorage; a hardcoded fallback super-admin email list exists in AuthContext.tsx if the database check fails. Admin status is never revoked on an ambiguous/slow database check — only on an explicit is_admin: false.
Nav flag: the Admin nav section is marked adminOnly in src/App.tsx, which resolves to isAdmin || isGandalf. Within that section, "Corrections" itself carries no extra per-link gate (unlike its neighbors Assignment History, Hiring Pipeline, and JD Sheet Sync, which are Gandalf-only, and Analytics, which is Sauron-only). /corrections is the defaultRoute of the Admin section.
Read-only edge case: inside the view, the Actions column (Review / Resolve / Delete buttons) and the inline review form render only when isAdmin is true. A user who has is_gandalf but not is_admin in the app_users table can open the page (the route guard passes) but sees the queue read-only, with no Actions column.
Who can submit flags (broader than who can see this page): the same "Flag Data Issue" form (FlagIssueModal) also opens from the Summary view's drill-down tables via a per-row flag icon. Any user who can open Summary drill-downs can submit a flag. Members (the base tier with no elevated role) cannot: Summary drill-downs are disabled for members (clickable={!isMember} in src/views/SummaryView.tsx), and members are restricted to the Summary and Employees views only.
Local dev: VITE_DEV_BYPASS_AUTH=true sets all role flags to true and bypasses the gate entirely (development environments only).
Data sources & lineage
Everything the Corrections view shows reads from a single table in Signal's own records: data_corrections (rows entered by users in Signal). Uniquely among Signal modules, this view never calls the Express backend at all — the browser reads and writes Signal's records directly through src/services/supabase.ts.
On-screen element | Origin system | Code path | Refresh | Caveat |
Corrections table rows (client, field, department, month, status, submitter, timestamps) | Signal's own records (data_corrections, entered by users in Signal) | CorrectionsView.tsx → getDataCorrections() in src/services/supabase.ts | Live read on page load and whenever the status tab changes; sorted newest-first; 10-second query timeout guard (code constant as of Jul 2026) | Rows are human reports, not verified data facts |
Status tab count badges (Pending / Reviewed / Resolved) | Signal's own records (data_corrections) | Separate getDataCorrections({}) call fetching all rows; counted client-side in CorrectionsView.tsx | Recomputed after every status change; counts cover the whole queue regardless of the active tab | Counts fetch the full table into the browser; a dedicated getDataCorrectionCounts() helper exists in supabase.ts but is unused as of Jul 2026 |
Search box filtering | In-memory (browser) | Client-side filter over already-fetched rows: client name, department, reason text, submitter email | Instant | Only searches rows already loaded for the active status tab |
Expanded row detail (Current Value, Expected Value, Reason, Reviewed By, Reviewer Notes, Resolved timestamp) | Signal's own records (data_corrections columns) | Same rows as the table | Same as table | "Current Value" is a text snapshot of what the submitter saw or typed — it is not a live link to the Vena number and does not update when the source data changes |
"Flag Data Issue" form submission | Writes to Signal's own records | FlagIssueModal.tsx → submitDataCorrection() in supabase.ts (insert, status pending) | Immediate; queue refetches on submit | Client name is free text (no picker), so client_id is null for flags submitted from this page; submitted_by is the logged-in user's Google email |
Review / Resolve actions | Writes to Signal's own records | updateDataCorrection() in supabase.ts | Immediate row update in place | Resolving stamps resolved_at with the current time; reviewed_by records the acting admin's email |
Delete action (pending rows only) | Writes to Signal's own records | deleteDataCorrection() in supabase.ts | Immediate; row removed from list and pending count decremented locally | Database policy (20260506_data_corrections_delete.sql) permits deleting only rows still in pending; reviewed/resolved rows are immutable to preserve the audit trail |
Indirect context (not queried by this view): the numbers being disputed — revenue, outsource costs, gross profit (MGP), division, department — originate in Vena and appear elsewhere in Signal (Summary, client and revenue views). The Corrections module itself never reads those figures; it only stores what the human reported.
Metrics & definitions
The Corrections view computes no financial metrics. Its on-screen numbers are queue-management counts and timestamps:
Pending / Reviewed / Resolved count badges — the number of flags in each status across the entire queue (not just the visible page or active tab). Basis: all rows of the data_corrections table in Signal's own records, counted in the browser after every load and status change. Origin: Signal's own records (entered by users in Signal).
Status — the lifecycle state of a flag. Pending = submitted, not yet triaged. Reviewed = an admin acknowledged it (typically meaning investigation in progress or handed to finance). Resolved = closed, with a resolved_at timestamp. The state machine is enforced by the UI (Pending → Reviewed or Resolved; Reviewed → Resolved; no reopen action exists); the operational meaning of Reviewed vs Resolved is a team convention, not defined in the app repo.
Submitted (relative time) — how long ago the flag was created, shown next to the submitter's name (the part of their email before the @). Formula (code constants as of Jul 2026, in CorrectionsView.tsx): under 1 minute = "just now"; under 60 minutes = "Xm ago"; under 24 hours = "Xh ago"; under 30 days = "Xd ago"; otherwise the calendar date. Hovering shows the full timestamp. Origin: created_at in Signal's own records.
Current Value / Expected Value — free-text snapshots typed (or pre-filled from the screen) by the submitter: what the number showed vs what they believe it should be. These are claims, not computed values. Origin: Signal's own records.
Field — which data element is disputed. Allowed values (dropdown in FlagIssueModal.tsx): Revenue, Outsource Costs, Gross Profit (MGP), Division, Department, Other.
Pagination — the list renders 50 rows at a time (code constant PAGE_SIZE = 50 as of Jul 2026) with a "Load more" button showing how many remain.
How it's used
Report a wrong number you spotted. While reviewing a client's revenue in the Summary view, a leader notices it looks inflated. From the Summary drill-down table they click the flag icon next to that client (pre-fills the client name and the on-screen value), or an admin opens Corrections and clicks "Flag Issue". They pick the field ("Revenue"), the month, type the expected value and why they believe the current one is wrong, and submit. The flag lands in the Pending queue for the finance team.
Work the Pending queue (admin triage). Periodically, an admin opens Corrections (the default landing page of the Admin nav section), scans the Pending tab, expands each flag to read the reason, and either: clicks Review → adds a note (e.g. "Confirmed with finance, Vena entry pending") → Mark Reviewed; resolves it immediately if trivially answered; or deletes it if it is a duplicate or mistaken flag.
Close the loop after the source fix. Once the underlying data is corrected in Vena and flows back into Signal's revenue views, the admin returns to the Reviewed tab and clicks Resolve, which stamps the resolution time — keeping an auditable record that reported issues were actually fixed, not just acknowledged.
Answer "is this number trustworthy?" Before presenting a client's financials, an admin can search the Corrections queue for that client to see whether open flags dispute the figures for the months in question, and caveat or delay a business review while the data is contested.
Spot systemic data problems. If the same field (e.g. repeated Department mislabels) or the same client keeps appearing across flags, that pattern indicates an upstream process problem in Vena data entry rather than a one-off — grounds to escalate to the finance data owners and fix the pipeline, not just the row.
What users can change here
All writes go to the data_corrections table in Signal's own records. Nothing on the Corrections page modifies revenue, KPIs, or any Vena-sourced figure anywhere in Signal.
Create a flag (any user who can reach the "Flag Data Issue" form — from this page or from Summary drill-downs): inserts a new row with status pending, stamped with the submitter's Google email. Required fields: Client or Employee name (free text) and Reason. Optional: Department, Month, Current Value, Expected Value. Side effect: none beyond the new queue row — no notification is sent to anyone (no email, no Slack; confirmed absent in the code as of Jul 2026).
Update a flag's status (Admin only, via Review/Resolve buttons): Pending → Reviewed or Resolved; Reviewed → Resolved. Records the acting admin's email in reviewed_by, optional free-text reviewer_notes, and stamps resolved_at when resolving. There is no "reopen" action in the UI.
Delete a flag (Admin only, pending rows only): permanent, behind a browser confirmation dialog. The database policy itself blocks deleting reviewed or resolved rows, so the audit trail of triaged issues cannot be erased from the UI.
Enforcement note: the admin-only nature of update/delete is enforced by the UI (route guard plus isAdmin check on the Actions column). At the database layer, the row-level security policies are permissive by design (any authenticated user could technically update rows or delete pending ones via direct API access) — documented in migration 20260312_data_corrections.sql.
Caveats & data quality
Flags are claims, not facts. A row in Corrections means a person reported a discrepancy; nothing in the code validates the "Current Value" or "Expected Value" against the actual Vena-sourced figure, and nothing verifies the upstream fix landed before a flag is marked Resolved. Resolution is on the honor system.
No notifications. Nothing emails or Slacks the finance team when a flag is submitted (confirmed absent in the code as of Jul 2026). The submission form's promise "The finance team will review this" relies on admins checking the queue. Who monitors the queue today and on what cadence is not defined in the app repo; the March 2026 migration comment names Rodolfo's team (Amalia/Alexandra) as reviewers.
Client field is free text. There is no client picker, so spelling varies and flags are not reliably linked to client records (client_id is null for flags submitted from the Corrections page; the Summary drill-down flag button also passes only the client name and displayed value, not a client id).
"Reviewed" vs "Resolved" meaning is convention. The code enforces only the state transitions, not their operational definitions. Not defined in the app repo.
Counts are computed client-side by fetching the entire table (an unused getDataCorrectionCounts() helper exists in supabase.ts); with a very large backlog this implementation could change. Cosmetic.
Code constants as of Jul 2026: page size 50 rows per "Load more"; 10-second timeout on the queue query; delete restricted to pending status at the database policy level; allowed field values revenue, outsource, mgp, division, department, other.
Employee flags are informally supported. The form label is "Client or Employee" and department/division are flaggable fields, but the table schema is client-centric (client_id, client_name). Whether people-data issues are officially routed through Corrections is not defined in the app repo.
Flag volume and turnaround time (flags per month, pending-to-resolved duration) are production-data questions; not answerable from the app repo.
Related views
Summary (/summary): the main organic intake path for the Corrections queue. Each row in Summary's drill-down tables (top/new/churned clients) carries a flag icon that opens the same "Flag Data Issue" form with the client name and displayed value pre-filled. Members (base tier) cannot open Summary drill-downs and therefore cannot flag from there.
Revenue/KPI views (Summary, client views, RPE, retention): the screens whose Vena-sourced numbers get disputed. Corrections is the feedback channel for all of them but has no live data link back — a resolved flag does not automatically confirm the number changed.
Revenue Split Overrides (managed elsewhere in Signal, stored in the revenue_split_overrides table of Signal's own records): a different mechanism that actually changes how revenue is allocated inside Signal. Corrections only reports problems for humans to fix upstream in Vena — do not conflate the two.
Admin nav neighbors: Assignment History (/audit-log, Gandalf-only), Hiring Pipeline (/hiring, Gandalf-only), JD Sheet Sync (/jd-sync, Gandalf-only), Analytics (/analytics, Sauron-only). Corrections is the only Admin-section page available at plain Admin tier. User access management lives in a separate "Access" nav section (General Access at /users, Gandalf-only; Growth Access at /growth/access for delegated Growth managers), not under Admin.
FAQ
Q: What is the Corrections page in Signal? A: Corrections (/corrections) is Signal's data-quality ticket queue. When someone believes a number in Signal is wrong — revenue, outsource costs, gross profit (MGP), division, or department — they submit a "Flag Data Issue" form describing what they see and what they expected. Admins then work each flag through Pending → Reviewed → Resolved. It is a workflow and audit trail only; it never changes any financial data.
Q: Who can see the Corrections page? A: Admin tier and above. The route is wrapped in an admin guard that requires the is_admin or is_gandalf flag on your user record in Signal's own records (app_users table); anyone else who navigates to /corrections is redirected to Summary. Admin flags are managed by Signal's platform owners — if you believe you need access, ask a Signal admin (Gandalf-tier users manage access on the General Access page).
Q: Can I flag a data issue if I'm not an admin? A: Yes — the "Flag Data Issue" form is also reachable from the Summary view: open a drill-down table and click the small flag icon next to a client row. That pre-fills the client name and the displayed value. Only viewing and triaging the queue requires Admin access. Base-tier Members cannot flag issues, because Summary drill-downs are disabled for the Member tier.
Q: If I flag a data issue, does the number get fixed automatically? A: No. Flagging creates a report in Signal's own records; the actual fix has to happen in the upstream source system (Vena, where the revenue and cost figures originate). Once the fix lands upstream and flows back into Signal's views, an admin marks the flag Resolved. Signal does not verify the fix — resolution is a human attestation.
Q: Does the finance team get notified when I submit a flag? A: No automatic notification exists — no email and no Slack message is sent when a flag is submitted (confirmed in the code as of Jul 2026). The confirmation message "The finance team will review this" relies on admins periodically checking the Pending queue. If your issue is urgent, follow up with the finance data owners directly.
Q: What's the difference between "Reviewed" and "Resolved" on a correction? A: Mechanically, Reviewed means an admin acknowledged the flag (and may have added notes), and Resolved means it was closed, with a timestamp recorded. By convention Reviewed typically means "investigation in progress or handed to finance" and Resolved means "fixed upstream," but the app enforces only the state transitions, not the meaning. There is no way to reopen a resolved flag in the UI.
Q: Can I delete a flagged issue I submitted by mistake? A: Only an admin can delete flags, and only while the flag is still Pending — a database policy blocks deleting Reviewed or Resolved flags so the audit trail can't be erased. If you submitted a flag by mistake, ask a Signal admin to delete it from the Pending tab (deletion is permanent and confirmation-gated).
Q: Why doesn't the "Current Value" on a correction match what Signal shows now? A: The Current Value is a free-text snapshot of what the submitter saw or typed at the time of flagging. It is not live-linked to the underlying figure, so if the data has since been corrected upstream in Vena (or the submitter typed it differently), the snapshot and the live view will diverge. That divergence is often exactly the signal that the fix landed.
Q: Where does the data on the Corrections page come from? A: Entirely from Signal's own records — a data_corrections table populated by users submitting and triaging flags in Signal. The Corrections page never queries Vena, payroll, or any external system; even the disputed values shown in a flag's detail are text the submitter provided, not live figures.
Q: Does resolving a correction change revenue numbers or KPIs anywhere in Signal? A: No. Corrections is purely a reporting and audit workflow. If you need revenue allocation actually changed inside Signal, that is a different mechanism (Revenue Split Overrides, managed elsewhere in Signal); corrections to source-of-truth figures must be made upstream in Vena by the finance team.
