Changelog - Dev - 08.30.2026 โ
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
Not on dev yet. Entries below are on feat/admin-and-merchant-portals behind draft pull request #976. This file was started by the ad-network lane; other lanes working today should append their own entries.
[Unreleased] - 2026-08-30 โ
Added โ
The admin Ad Network section has data to stand on:
npm run seed:adnet/npm run seed:adnet:cleanpopulate dev with clearly-fake ad-network fixtures, 8seed-adnet-*offers across every reviewable status in Firestore and 45 days of deterministic delivery history in BigQueryad_delivery_daily, so the Review queue, the Delivery dashboard, and the Report Builder's Offer funnel source can finally be worked on live. Because these metrics are the designed future billing inputs, the seed is fenced four ways: aseed-adnet-prefix on every id,environment: developmenton every row, a refusal to run against any project whose id containsprod, and venue ids that resolve to no venue doc, which the serving path drops before any real user can see the offer, approved or not. Clean deletes by prefix and fixed ids only, verified to leave the 17 real rollup rows untouched. Full run: ad-network-seed test plan. (#976)enhancementAd Network grows up: sidebar sub-nav, a drawer-first Review queue, live Placements, and an Economics report: The section's tab strip became sidebar sub-nav (Reports holding the Delivery and Economics tabs, Placements and Review as their own pages), matching how Analytics and Merchants structure their children. Review decisions moved into the standard right-side drawer, now codified as the admin-wide pattern in the rules so it stops being re-asked surface by surface; the queue's row buttons are gone (a hover-target Approve was a misclick from publishing), replaced by four queue-health cards and search/placement/audience filters. Placements shows live per-surface figures from a new aggregate endpoint, closing the issue that scaffolded them (feat(analytics): expose a per-placement aggregate, #998). The reporting window on every ad report is the same calendar widget Reports built. (#976)
enhancementThe Economics report speaks the real business model, and the retired one is scrubbed at the source: Revenue is the flat monthly rate per merchant, period (now a single shared constant); cost is our own platform infra spend from the billing pipeline; a campaign's outcome is the ad being shown and lanterns lit at its venue while the offer was live, via a new economics endpoint that clips lantern events to each offer's live span. Redemption messaging is retired from the ad UI entirely. The retired per-redemption model was then traced to its live carriers and corrected everywhere it still spoke: the public merchant signup copy (which was still selling "$1 per verified redemption"), four economics docs calling the SKU "planned", and pipeline comments calling delivery metrics "billed". (#976)
enhancementThe Schema Viewer is reachable, and Dashboards is gone:
/admin/analytics/schemarenders the BigQuery-sourced schema viewer built on 2026-08-28 and imported by nothing but its own story since: 9 datasets, 25 tables and 324 columns with the definitions BigQuery itself holds, plus the gaps stated as gaps (event_counts_dailyhas 7 of 7 columns described and no table description, and the page says so where the description would be). It ships unpolished on purpose, because every admin and merchant page is queued for a Claude Design pass. Dashboards left the nav in the same change: its last two entries, User Engagement and Conversion Funnels, had beenDashboardPlaceholderfor 123 days, which is the branch of #999's criterion that says a route either renders something real or comes off the nav. Every retired path redirects rather than 404ing, sodashboards/venue-activitystill reaches Venues anddashboards/adsstill reaches Ad Network. Analytics now reads Query Console, Schema Viewer, Event Tracking, Configurations. (#976)enhancement
Fixed โ
- The ad delivery endpoints could never return a row: both
/analytics/admin/ads/deliveryand the merchant-gated read bound their date bounds as plain strings carrying an explicitDATEparameter type, which the BigQuery client silently serializes as NULL, andday BETWEEN NULL AND NULLmatches nothing. No error, anywhere, ever: the bug shipped with the endpoints and was unobservable while the rollup table was empty, then surfaced the moment the seed gave the table rows the dashboard failed to show. Dates now travel as strings the SQL casts, and a regression test asserts no plain-string parameter ever carries a DATE/TIMESTAMP type again. Verified live on both the admin read (all in-window rows) and the merchant read (k-anon floor suppressing exactly the 10 below-floor cells). (#976)bug