From d80c08306c32ce226f231271384b43c06ca2b0c4 Mon Sep 17 00:00:00 2001 From: Sam Rolfe Date: Mon, 10 Aug 2026 09:17:11 +1000 Subject: [PATCH] openspec: admin-insights-pages change --- .../admin-insights-pages/.openspec.yaml | 2 + .../changes/admin-insights-pages/README.md | 3 ++ .../changes/admin-insights-pages/design.md | 39 +++++++++++++++++++ .../changes/admin-insights-pages/proposal.md | 30 ++++++++++++++ .../specs/admin-dashboard-users/spec.md | 22 +++++++++++ .../specs/public-pages-customer-pause/spec.md | 19 +++++++++ .../changes/admin-insights-pages/tasks.md | 17 ++++++++ 7 files changed, 132 insertions(+) create mode 100644 openspec/changes/admin-insights-pages/.openspec.yaml create mode 100644 openspec/changes/admin-insights-pages/README.md create mode 100644 openspec/changes/admin-insights-pages/design.md create mode 100644 openspec/changes/admin-insights-pages/proposal.md create mode 100644 openspec/changes/admin-insights-pages/specs/admin-dashboard-users/spec.md create mode 100644 openspec/changes/admin-insights-pages/specs/public-pages-customer-pause/spec.md create mode 100644 openspec/changes/admin-insights-pages/tasks.md diff --git a/openspec/changes/admin-insights-pages/.openspec.yaml b/openspec/changes/admin-insights-pages/.openspec.yaml new file mode 100644 index 0000000..d77f64e --- /dev/null +++ b/openspec/changes/admin-insights-pages/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-08-09 diff --git a/openspec/changes/admin-insights-pages/README.md b/openspec/changes/admin-insights-pages/README.md new file mode 100644 index 0000000..bffdf15 --- /dev/null +++ b/openspec/changes/admin-insights-pages/README.md @@ -0,0 +1,3 @@ +# admin-insights-pages + +Admin dashboard revenue/customers stats, users->tags relation, pause customer (gate alerts), public About/What-is-this/Contact pages diff --git a/openspec/changes/admin-insights-pages/design.md b/openspec/changes/admin-insights-pages/design.md new file mode 100644 index 0000000..d7341f9 --- /dev/null +++ b/openspec/changes/admin-insights-pages/design.md @@ -0,0 +1,39 @@ +## Context + +Four quick wins (tuxedo board): dashboard insights, users→tags, customer pause, public pages. All small; no new external deps. + +## Goals / Non-Goals + +**Goals:** +- Dashboard shows customers + revenue (needs orders.amount). +- Admin sees each customer's tags; can pause a customer. +- Public About/What-is-this/Contact pages exist. + +**Non-Goals:** +- Fancy contact form backend (mailto suffices until email infra exists). +- Revenue breakdowns by period/tag (later). +- Pause ≠ billing automation (still manual; renewals are a later slice). + +## Decisions + +1. **`users.paused`** (idempotent bool, default false): simplest customer-level kill switch. `shouldAlert` loads the owner (`GetUserByID` on `tag.OwnerID`) and returns false when paused; the contact path checks the same. Scan recording continues. +2. **`orders.amount NUMERIC(10,2) DEFAULT 0`** (idempotent): revenue = `SUM(amount) WHERE status='paid'` (Eloquent aggregate). OrderResource gains an amount input. Existing orders default 0 → revenue is accurate going forward. +3. **Public pages**: three templates extending `base.html` (about / what-is-this / contact), handlers mirroring `Home`, routes in main.go. Contact = contact details + `mailto:` (no email system yet). +4. **Admin**: StatsOverview adds Customers + Revenue stats; UserResource gains a `paused` Toggle + a `TagsRelationManager` (Filament v3 auto-discovers `UserResource/RelationManagers/*`). + +## Risks / Trade-offs + +- [Pause is all-or-nothing per customer] → matches the 2014 model; per-tag suspend already exists separately. +- [Revenue 0 for existing orders] → accepted; going forward the admin enters amounts. +- [Public pages minimal] → intentional; expand with the info-tag/multilingual work later. + +## Migration Plan + +1. `make db-up` (two ALTERs); sqlc regen. +2. Go: pause gate + 3 pages; build. +3. Admin: stats, relation manager, pause toggle, order amount. +4. Verify (new suite + regressions); deploy (frontend binary+templates; admin rebuild). + +## Open Questions + +- None blocking. diff --git a/openspec/changes/admin-insights-pages/proposal.md b/openspec/changes/admin-insights-pages/proposal.md new file mode 100644 index 0000000..7cc86a7 --- /dev/null +++ b/openspec/changes/admin-insights-pages/proposal.md @@ -0,0 +1,30 @@ +## Why + +Four small, high-visibility gaps from the tuxedo board: the admin dashboard lacks customer/revenue numbers, the Users resource doesn't show a customer's tags, there's no way to pause an unpaid customer (alerts continue), and the public site has no About/Contact pages. All quick wins that make the product feel complete while testing. + +## What Changes + +- **Dashboard insights**: StatsOverview gains **Customers** (users) and **Revenue** (sum of `orders.amount` where status `paid`). Requires an `orders.amount` column (idempotent, default 0) + an amount field in the Order resource. +- **Customers → Tags**: UserResource gains a **Tags relation manager** (lists the customer's tags with status). +- **Pause customer**: `users.paused` flag (idempotent) + a toggle in UserResource; paused owners' tags record scans but send **no alerts** (Go `shouldAlert` + contact path). +- **Public pages**: `/about`, `/what-is-this`, `/contact` static pages (Go templates, base layout). Contact is contact details + mailto for now. + +## Capabilities + +### New Capabilities + +- `public-pages`: About / What-is-this / Contact pages. +- `customer-pause`: admin pause flag gating owner alerts. + +### Modified Capabilities + +- `admin-dashboard`: ADDED — customers + revenue stats. +- `admin-users`: ADDED — tags relation manager + pause toggle. +- `database`: ADDED — `users.paused`, `orders.amount`. + +## Impact + +- **Schema**: two idempotent ALTERs; `make db-up`; sqlc regen. +- **Go**: `shouldAlert` + contact notify check owner paused; 3 page handlers + templates + routes. +- **Admin**: StatsOverview, OrderResource amount, UserResource paused + relation manager. +- No changes to the alert pipeline beyond the pause gate. diff --git a/openspec/changes/admin-insights-pages/specs/admin-dashboard-users/spec.md b/openspec/changes/admin-insights-pages/specs/admin-dashboard-users/spec.md new file mode 100644 index 0000000..0a9d57a --- /dev/null +++ b/openspec/changes/admin-insights-pages/specs/admin-dashboard-users/spec.md @@ -0,0 +1,22 @@ +## ADDED Requirements + +### Requirement: Dashboard revenue and customers +The admin dashboard SHALL show total customers and total revenue (sum of paid order amounts). + +#### Scenario: View stats +- **WHEN** an admin opens the dashboard +- **THEN** customer count and revenue (paid orders) are displayed + +### Requirement: Customer tags in admin +The Users resource SHALL show a customer's tags (code, status, item type). + +#### Scenario: Open a customer +- **WHEN** an admin views a user +- **THEN** their tags are listed + +### Requirement: orders.amount +The `orders` table SHALL have an `amount` column (numeric, default 0) editable in the Order resource. + +#### Scenario: Set an order amount +- **WHEN** an admin sets an amount on an order +- **THEN** revenue reflects it once the order is paid diff --git a/openspec/changes/admin-insights-pages/specs/public-pages-customer-pause/spec.md b/openspec/changes/admin-insights-pages/specs/public-pages-customer-pause/spec.md new file mode 100644 index 0000000..e4e58b6 --- /dev/null +++ b/openspec/changes/admin-insights-pages/specs/public-pages-customer-pause/spec.md @@ -0,0 +1,19 @@ +## ADDED Requirements + +### Requirement: Public info pages +The site SHALL serve `/about`, `/what-is-this`, and `/contact` as styled pages sharing the site layout, with contact details on the contact page. + +#### Scenario: Visit each page +- **WHEN** a visitor opens /about, /what-is-this, or /contact +- **THEN** a styled page renders with the site header/footer + +### Requirement: Customer pause gates alerts +When a user is paused (admin flag), scans on their tags SHALL be recorded but no alert SMS SHALL be sent (alert or contact paths). + +#### Scenario: Paused owner +- **WHEN** a scan arrives on a tag whose owner is paused +- **THEN** the scan is recorded with `alert_sent = false` and no SMS is sent + +#### Scenario: Unpaused owner +- **WHEN** the owner is unpaused +- **THEN** normal alert rules apply diff --git a/openspec/changes/admin-insights-pages/tasks.md b/openspec/changes/admin-insights-pages/tasks.md new file mode 100644 index 0000000..5d956e1 --- /dev/null +++ b/openspec/changes/admin-insights-pages/tasks.md @@ -0,0 +1,17 @@ +## 1. Schema & Go + +- [ ] 1.1 `db/schema.sql`: idempotent `users.paused` + `orders.amount`; `make db-up`; `make generate` +- [ ] 1.2 `scan.go`: `shouldAlert` + FinderContact — load owner, return false when paused +- [ ] 1.3 Static pages: `about.go` handlers (About/WhatIsThis/Contact) + templates + routes + template sets + +## 2. Admin + +- [ ] 2.1 StatsOverview: Customers + Revenue stats +- [ ] 2.2 OrderResource: `amount` input + column; UserResource: `paused` toggle + column +- [ ] 2.3 `UserResource/RelationManagers/TagsRelationManager.php` (code, status, item type) + +## 3. Verification + +- [ ] 3.1 New suite: paused owner → no alert (scan recorded); unpaused → alert; /about /what-is-this /contact render 200 +- [ ] 3.2 Regressions (72) green; deploy (frontend binary+templates; admin rebuild/restart) +- [ ] 3.3 `openspec validate admin-insights-pages`; commit