docs: create milestone v2.0 roadmap (5 phases)

This commit is contained in:
lorentz 2026-07-10 12:05:48 -04:00
parent e0a41da051
commit 25edff0462
3 changed files with 200 additions and 72 deletions

View file

@ -51,7 +51,24 @@ Requirements for this milestone. Each maps to a roadmap phase.
## Traceability
<!-- Filled in by the roadmapper when the roadmap is created. -->
| Requirement | Phase | Status |
|-------------|-------|--------|
| PAX8-01 | Phase 10 | Pending |
| PAX8-02 | Phase 10 | Pending |
| PAX8-03 | Phase 11 | Pending |
| PAX8-04 | Phase 11 | Pending |
| PAX8-05 | Phase 11 | Pending |
| PAX8-08 | Phase 11 | Pending |
| PAX8-06 | Phase 12 | Pending |
| PAX8-10 | Phase 12 | Pending |
| PAX8-11 | Phase 12 | Pending |
| PAX8-07 | Phase 13 | Pending |
| PAX8-09 | Phase 13 | Pending |
| PAX8-12 | Phase 14 | Pending |
| PAX8-13 | Phase 14 | Pending |
| PAX8-14 | Phase 14 | Pending |
**Coverage:** 14/14 v2.0 requirements mapped ✓
---
*Requirements defined: 2026-07-10*

View file

@ -1,17 +1,9 @@
# Roadmap: Pulse Mobile Shell Redesign
# Roadmap: Pulse
## Overview
## Milestones
Eight phases mirror the deliberate build order in the source spec
(`docs/superpowers/specs/2026-05-03-mobile-shell-design.md` §8). Each phase
ships independently to `master` — no big-bang merge. Phase 1 lays PWA
metadata and safe-area utilities. Phase 2 rebuilds `app/mobile/layout.tsx`
with the new header, 5-cell bottom nav, and More drawer (deleting
`/mobile/nav` in the same change). Once the shell lands, Phases 37 are
independent restyles/new pages and may be executed in parallel; Phase 8
follows Phase 7 because the user profile is reached from the Engagement
overview. All work happens in place under `/mobile/*` — no `/mobile-v2`,
no parallel routes.
- ✅ **v1.0 Mobile Shell Redesign** — Phases 1-9.1 (shipped 2026-07-10)
- 📋 **v2.0 PAX8 Integration** — Phases 10-14 (planned)
## Phases
@ -21,19 +13,30 @@ no parallel routes.
Decimal phases appear between their surrounding integers in numeric order.
- [ ] **Phase 1: PWA Scaffolding** — Manifest, viewport meta, and safe-area utilities so the shell installs and paints under the home indicator
- [ ] **Phase 2: Mobile Shell + More Drawer** — New `app/mobile/layout.tsx` (header + 5-cell bottom nav) and Sheet drawer that replaces `/mobile/nav`
- [ ] **Phase 3: Dashboard Restyle** — 2×2 KPI grid, Needs Attention strip, worker/backup status row (no charts)
- [ ] **Phase 4: Tickets Restyle** — Collapsible URL-synced filters, priority-bar rows, cursor-based infinite scroll, detail header reskin
- [x] **Phase 5: Finance Restyle** — Adopt new Card + typography scale, swap wide tables for stacked lists (completed 2026-05-03)
- [ ] **Phase 6: Analyzer Feed (NEW)**`/mobile/analyzer` read-only stream + `/api/mobile/analyzer/feed`
- [ ] **Phase 7: Engagement Overview (NEW)**`/mobile/engagement` phone-first overview reachable from the More drawer
- [ ] **Phase 7.1: User Timezone Fix (INSERTED — urgent)** — Per-user IANA timezone column + viewer-tz date math so dashboards and filters render the right "today"
- [ ] **Phase 8: Engagement User Profile (NEW)**`/mobile/engagement/[userId]` real-page profile that replaces the desktop modal pattern
- [ ] **Phase 9: User Profile & Preferences (NEW)**`/mobile/profile` settings page (timezone chooser, theme, mobile push, Teams + ntfy channels)
- [ ] **Phase 9.1: ntfy Backend Fix (INSERTED — urgent)** — Personal ntfy channels target the company ntfy server with bearer auth + `pulse-me-` prefix (UAT gap closure)
<details>
<summary>✅ v1.0 Mobile Shell Redesign (Phases 1-9.1) - SHIPPED 2026-07-10</summary>
## Phase Details
Eight phases mirror the deliberate build order in the source spec
(`docs/superpowers/specs/2026-05-03-mobile-shell-design.md` §8). Each phase
shipped independently to `master` — no big-bang merge. Phase 1 laid PWA
metadata and safe-area utilities. Phase 2 rebuilt `app/mobile/layout.tsx`
with the new header, 5-cell bottom nav, and More drawer (deleting
`/mobile/nav` in the same change). Once the shell landed, Phases 37 were
independent restyles/new pages; Phase 8 followed Phase 7 because the user
profile is reached from the Engagement overview. All work happened in place
under `/mobile/*` — no `/mobile-v2`, no parallel routes.
- [x] **Phase 1: PWA Scaffolding** — Manifest, viewport meta, and safe-area utilities so the shell installs and paints under the home indicator
- [x] **Phase 2: Mobile Shell + More Drawer** — New `app/mobile/layout.tsx` (header + 5-cell bottom nav) and Sheet drawer that replaces `/mobile/nav`
- [x] **Phase 3: Dashboard Restyle** — 2×2 KPI grid, Needs Attention strip, worker/backup status row (no charts)
- [x] **Phase 4: Tickets Restyle** — Collapsible URL-synced filters, priority-bar rows, cursor-based infinite scroll, detail header reskin
- [x] **Phase 5: Finance Restyle** — Adopt new Card + typography scale, swap wide tables for stacked lists (completed 2026-05-03)
- [x] **Phase 6: Analyzer Feed (NEW)**`/mobile/analyzer` read-only stream + `/api/mobile/analyzer/feed`
- [x] **Phase 7: Engagement Overview (NEW)**`/mobile/engagement` phone-first overview reachable from the More drawer
- [x] **Phase 7.1: User Timezone Fix (INSERTED — urgent)** — Per-user IANA timezone column + viewer-tz date math so dashboards and filters render the right "today"
- [x] **Phase 8: Engagement User Profile (NEW)**`/mobile/engagement/[userId]` real-page profile that replaces the desktop modal pattern
- [x] **Phase 9: User Profile & Preferences (NEW)**`/mobile/profile` settings page (timezone chooser, theme, mobile push, Teams + ntfy channels)
- [x] **Phase 9.1: ntfy Backend Fix (INSERTED — urgent)** — Personal ntfy channels target the company ntfy server with bearer auth + `pulse-me-` prefix (UAT gap closure)
### Phase 1: PWA Scaffolding
**Goal**: A manager who taps "Add to Home Screen" gets a standalone Pulse icon that opens to the mobile shell with content respecting the device safe areas.
@ -213,27 +216,122 @@ Decimal phases appear between their surrounding integers in numeric order.
- [x] 09.1-01-PLAN.md — Personal-channels regex/prefix/bearer + propagate to notify/approval/digest send paths + ProfileChannelsSection QR & copy
**UI hint**: no (backend-heavy; one component edit for QR/link target)
</details>
### 📋 v2.0 PAX8 Integration (Planned)
**Milestone Goal:** Sync PAX8 licensing/subscription data into Pulse, read-only,
mapped to Autotask companies, so managers can see subscription costs and seat
counts alongside existing company data.
This milestone follows the codebase's existing external-integration pattern
(`<name>-client.ts` + `<name>-factory.ts` + numbered migration + sync service +
scheduler entry + admin toggle). Phase 10 stands up auth + schema in isolation
so the OAuth2 client-credentials flow is proven before anything is built on
top of it. Phase 11 syncs the "current state" entities (companies, catalog,
subscriptions). Phase 12 adds historical cost data (orders/invoices) and the
fuzzy-name company-matching pass, since matching needs companies to already
exist. Phase 13 wires the combined sync into the daily scheduler and the
`/admin/integrations` toggle — deliberately last among the backend phases so
it schedules the *complete* sync, not a partial one. Phase 14 ships the
`/pax8` page, which needs Phase 12's data and match state to have something to
render, including the manual-resolution workflow for flagged companies.
- [ ] **Phase 10: PAX8 Client & Auth Foundation** — OAuth2 client-credentials auth, `isPax8Configured()`, and the PAX8 schema migration
- [ ] **Phase 11: Company, Catalog & Subscription Sync** — Read-only sync of current-state companies, product catalog, and subscriptions into Postgres
- [ ] **Phase 12: Orders/Invoices & Company Matching** — Historical cost sync plus fuzzy-name auto-matching (with flagging) of PAX8 companies to Autotask companies
- [ ] **Phase 13: Scheduler & Admin Toggle** — Daily `pax8-daily` cron entry and an on/off switch in `/admin/integrations`
- [ ] **Phase 14: /pax8 UI Surface** — New page listing companies/subscriptions/cost breakdown, plus manual resolution of flagged company matches
## Phase Details
### Phase 10: PAX8 Client & Auth Foundation
**Goal**: Pulse can authenticate to the PAX8 API via OAuth2 client-credentials, and the Postgres schema for all four PAX8 entities exists — proving the integration pattern before any sync logic is built on top of it.
**Depends on**: Nothing (first phase of v2.0)
**Requirements**: PAX8-01, PAX8-02
**Success Criteria** (what must be TRUE):
1. `lib/services/pax8-factory.ts` exports `isPax8Configured()`, returning `true` only when the PAX8 client ID and secret env vars are both set, `false` otherwise
2. `getPax8Client()` performs an OAuth2 client-credentials token exchange against `api.pax8.com/v1` and successfully calls a read-only endpoint (e.g., list companies) using the resulting bearer token
3. Calling the client with missing/invalid credentials throws a clear, typed error rather than failing silently or crashing the process — matching the existing `is<Name>Configured()` + throw-if-missing pattern used by other integrations
4. A new numbered migration creates the PAX8 tables (companies, subscriptions, products/catalog, orders, and a company-match/review table) using `IF NOT EXISTS`, ready for Phase 11+ to populate
**Plans**: TBD
**UI hint**: no
### Phase 11: Company, Catalog & Subscription Sync
**Goal**: PAX8 companies, the product catalog, and current subscriptions are synced into Postgres and are human-readable (not raw SKU IDs) — the "current state" half of the integration.
**Depends on**: Phase 10
**Requirements**: PAX8-03, PAX8-04, PAX8-05, PAX8-08
**Success Criteria** (what must be TRUE):
1. Running the sync populates a companies table with every PAX8 company (PAX8 ID, name, and other identifying fields)
2. Running the sync populates a product/catalog table (SKUs, categories) and a subscriptions table (product, seat count, billing term) per company
3. A synced subscription row displays a readable product name and category by joining to the catalog table — not a bare SKU/product ID
4. No code path in the PAX8 client or this sync service issues a write (POST/PUT/PATCH/DELETE) to the PAX8 API — every call is a read, verified by inspection of the client's exposed methods
**Plans**: TBD
**UI hint**: no
### Phase 12: Orders/Invoices & Company Matching
**Goal**: Pulse has historical PAX8 cost data for reconciliation over time, and every PAX8 company is automatically linked to its Autotask counterpart or explicitly flagged for review — never silently guessed.
**Depends on**: Phase 11
**Requirements**: PAX8-06, PAX8-10, PAX8-11
**Success Criteria** (what must be TRUE):
1. Running the sync populates an orders/invoices table with historical line items (not just current-state seat counts), enabling cost-over-time comparisons
2. At sync time, each PAX8 company is automatically matched to an Autotask company by fuzzy name similarity when a sufficiently confident match exists, and the match is persisted
3. A PAX8 company with no match, or with multiple similarly-scored Autotask candidates, is persisted with a flagged/needs-review status instead of being auto-assigned
4. Re-running the sync does not overwrite a match that has already been manually confirmed/resolved (idempotent with respect to human decisions)
**Plans**: TBD
**UI hint**: no
### Phase 13: Scheduler & Admin Toggle
**Goal**: PAX8 sync runs automatically once a day like every other Pulse integration, and can be turned on or off from `/admin/integrations` without a container restart.
**Depends on**: Phase 12
**Requirements**: PAX8-07, PAX8-09
**Success Criteria** (what must be TRUE):
1. A `pax8-daily` (or equivalently named) entry exists in the sync scheduler and fires once per day, running the full companies + catalog + subscriptions + orders sync in sequence
2. PAX8 appears as a toggleable row on `/admin/integrations`, backed by the `integration_settings` table like every other integration
3. Disabling PAX8 from that UI stops future scheduled sync runs (respecting the existing health-cache window, or immediately per the PATCH-clears-cache convention) and records `disabled_by`, `disabled_at`, and an optional `disabled_reason`
4. Re-enabling PAX8 resumes scheduled sync at the next cron tick with no code deploy or container restart required
**Plans**: TBD
**UI hint**: no
### Phase 14: /pax8 UI Surface
**Goal**: A manager can open `/pax8` and see PAX8 companies with their subscriptions and a cost breakdown, and an admin can resolve any flagged/ambiguous company match directly from that page — no psql required.
**Depends on**: Phase 12
**Requirements**: PAX8-12, PAX8-13, PAX8-14
**Success Criteria** (what must be TRUE):
1. `/pax8` lists PAX8 companies together with their current subscriptions
2. Each company shows a cost breakdown (e.g., by subscription/product) built from the synced subscription and order/invoice data
3. Flagged/ambiguous company matches appear in a distinct, clearly-labeled review section on `/pax8` rather than being mixed silently into the main list
4. From that review section, an admin can pick the correct Autotask company for a flagged PAX8 company; the resolution persists and is respected (not overwritten) by future syncs
**Plans**: TBD
**UI hint**: yes
## Progress
**Execution Order:**
Phases execute in numeric order. Phase 2 unblocks Phases 37 (any order, parallelizable). Phase 8 follows Phase 7.
Phases execute in numeric order. v1.0 (Phases 1-9.1) shipped 2026-07-10. v2.0 phases run 10 → 11 → 12 → 13 → 14 — each is a hard dependency on the previous within this milestone (no parallelization: auth → current-state sync → historical sync + matching → scheduling → UI, in that order).
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
| 1. PWA Scaffolding | 1/2 | Executing | - |
| 2. Mobile Shell + More Drawer | 0/TBD | Not started | - |
| 3. Dashboard Restyle | 0/2 | Not started | - |
| 4. Tickets Restyle | 0/3 | Not started | - |
| 5. Finance Restyle | 2/2 | Complete | 2026-05-03 |
| 6. Analyzer Feed | 0/3 | Not started | - |
| 7. Engagement Overview | 0/3 | Not started | - |
| 7.1. User Timezone Fix | 0/5 | Not started | - |
| 8. Engagement User Profile | 0/2 | Not started | - |
| 9. User Profile & Preferences | 0/5 | Not started | - |
| 9.1. ntfy Backend Fix | 0/1 | Not started | - |
| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
| 1. PWA Scaffolding | v1.0 | 2/2 | Complete | 2026-07-10 |
| 2. Mobile Shell + More Drawer | v1.0 | 2/2 | Complete | 2026-07-10 |
| 3. Dashboard Restyle | v1.0 | 2/2 | Complete | 2026-07-10 |
| 4. Tickets Restyle | v1.0 | 3/3 | Complete | 2026-07-10 |
| 5. Finance Restyle | v1.0 | 2/2 | Complete | 2026-05-03 |
| 6. Analyzer Feed | v1.0 | 3/3 | Complete | 2026-07-10 |
| 7. Engagement Overview | v1.0 | 3/3 | Complete | 2026-07-10 |
| 7.1. User Timezone Fix | v1.0 | 5/5 | Complete | 2026-07-10 |
| 8. Engagement User Profile | v1.0 | 2/2 | Complete | 2026-07-10 |
| 9. User Profile & Preferences | v1.0 | 6/6 | Complete | 2026-07-10 |
| 9.1. ntfy Backend Fix | v1.0 | 1/1 | Complete | 2026-07-10 |
| 10. PAX8 Client & Auth Foundation | v2.0 | 0/TBD | Not started | - |
| 11. Company, Catalog & Subscription Sync | v2.0 | 0/TBD | Not started | - |
| 12. Orders/Invoices & Company Matching | v2.0 | 0/TBD | Not started | - |
| 13. Scheduler & Admin Toggle | v2.0 | 0/TBD | Not started | - |
| 14. /pax8 UI Surface | v2.0 | 0/TBD | Not started | - |
---
*Roadmap created: 2026-05-03*
*Source spec: `docs/superpowers/specs/2026-05-03-mobile-shell-design.md`*
*v2.0 phases added: 2026-07-10*
*Source spec (v1.0): `docs/superpowers/specs/2026-05-03-mobile-shell-design.md`*
*Source seed (v2.0): `.planning/seeds/SEED-002-pax8-integration.md`*
</content>
</invoke>

View file

@ -6,7 +6,7 @@ status: planning
last_updated: "2026-07-10T15:53:23.273Z"
last_activity: 2026-07-10
progress:
total_phases: 0
total_phases: 5
completed_phases: 0
total_plans: 0
completed_plans: 0
@ -17,25 +17,27 @@ progress:
## Project Reference
See: .planning/PROJECT.md (updated 2026-05-03)
See: .planning/PROJECT.md (updated 2026-07-10)
**Core value:** A manager can open Pulse on their phone and, in under 30 seconds, see the state of the business and triage tickets — without ever needing to switch to desktop for read-only awareness.
**Current focus:** Phase 09.1 — ntfy-backend-fix
**Core value:** Managers can see PAX8 subscription costs and seat counts alongside existing Autotask company data in Pulse, without manually cross-referencing PAX8's own portal.
**Current focus:** Phase 10 — PAX8 Client & Auth Foundation
## Current Position
Phase: Not started (defining requirements)
Plan: —
Status: Defining requirements
Last activity: 2026-07-10 — Milestone v2.0 started
Phase: 10 of 14 (PAX8 Client & Auth Foundation)
Plan: — (not yet planned)
Status: Roadmap approved, ready to plan Phase 10
Last activity: 2026-07-10 — v2.0 ROADMAP.md created, Phases 10-14 defined
Progress: [░░░░░░░░░░] 0%
## Performance Metrics
**Velocity:**
- Total plans completed: 30
- Total plans completed: 30 (all from v1.0 Mobile Shell Redesign)
- Average duration: —
- Total execution time: 0.0 hours
- Total execution time: 0.0 hours (v2.0)
**By Phase:**
@ -51,15 +53,19 @@ Last activity: 2026-07-10 — Milestone v2.0 started
| 07.1 | 5 | - | - |
| 08 | 2 | - | - |
| 09 | 6 | - | - |
| 09.1 | 1 | - | - |
| 10 | TBD | - | - |
| 11 | TBD | - | - |
| 12 | TBD | - | - |
| 13 | TBD | - | - |
| 14 | TBD | - | - |
**Recent Trend:**
- Last 5 plans: —
- Last 5 plans: — (v1.0 closed; v2.0 not yet executed)
- Trend: —
*Updated after each plan completion*
| Phase 02-mobile-shell-more-drawer P02 | 8 | 4 tasks | 2 files |
| Phase 05-finance-restyle P02 | 2 | 2 tasks | 1 files |
## Accumulated Context
@ -68,15 +74,19 @@ Last activity: 2026-07-10 — Milestone v2.0 started
Decisions are logged in PROJECT.md Key Decisions table.
Recent decisions affecting current work:
- Roadmap: Phases mirror the spec's 8-step build order so each step ships independently to `master` (spec §8)
- Phase 2 unblocks Phases 37; Phases 37 are mutually independent and can be parallelized; Phase 8 depends on Phase 7
- All work happens in place under `/mobile/*` — no `/mobile-v2`, no parallel routes (spec §2)
- [Phase 02-mobile-shell-more-drawer]: Single useState in mobile layout.tsx for drawer open state — no Zustand/Context per CLAUDE.md constraint
- [Phase 02-mobile-shell-more-drawer]: Tailwind 4 pb-[calc(theme(spacing.16)+env(safe-area-inset-bottom))] arbitrary value works without inline-style fallback
- [Phase 02-mobile-shell-more-drawer]: No redirect on /mobile/nav deletion — standard 404 per DRAWER-06 spec
- [Phase 05-finance-restyle]: D-09: Monthly revenue renders as stacked list, not recharts bar chart (DASH-04 precedent — no charts on mobile)
- [Phase 05-finance-restyle]: D-02: Revenue YTD folded into Paid MTD caption; separate Revenue YTD card removed
- [Phase 05-finance-restyle]: D-08: Aging bucket palette locked: amber/orange/destructive token — no raw red/yellow Tailwind classes
- v2.0 roadmap: 5 phases (10-14), strictly sequential — auth foundation →
current-state sync → historical sync + company matching → scheduler/admin
toggle → UI — each phase is a hard dependency on the previous, no
parallelization within this milestone
- Phase 10 isolates OAuth2 client-credentials auth + the full PAX8 schema
migration before any sync logic is written, to de-risk the new external
integration early
- PAX8-08 (read-only guarantee) and PAX8-11 (flag don't guess) are treated as
constraints verified within their natural sync phase (11 and 12
respectively), not standalone phases
- PAX8-12 (admin resolves flagged matches) is delivered on the `/pax8` page
itself (Phase 14) rather than a separate `/admin` surface — `/pax8` is the
dedicated home for this integration's data and review workflow
### Pending Todos
@ -86,16 +96,19 @@ None yet.
None yet.
### Quick Tasks Completed
## Deferred Items
| # | Description | Date | Commit | Directory |
|---|-------------|------|--------|-----------|
| 260519-0oz | Add QBO createPayment + createDeposit + .FH reconciliation script | 2026-05-19 | 5497458 | [260519-0oz-add-qbo-createpayment-createdeposit-fh-r](./quick/260519-0oz-add-qbo-createpayment-createdeposit-fh-r/) |
| 260521-fci | Stopgap nightly reconciliation for stale open tickets in postgres mirror | 2026-05-21 | badd718 | [260521-fci-stopgap-nightly-reconciliation-for-stale](./quick/260521-fci-stopgap-nightly-reconciliation-for-stale/) |
| 260521-foj | Fix weekly-full FK error: widen Companies filter + defensive ticket company_id validation | 2026-05-21 | 62c529f | [260521-foj-fix-weekly-full-fk-error-widen-companies](./quick/260521-foj-fix-weekly-full-fk-error-widen-companies/) |
Items acknowledged and carried forward from previous milestone close:
| Category | Item | Status | Deferred At |
|----------|------|--------|-------------|
| Follow-up | Tablet breakpoint (`md:max-w-2xl`) on mobile shell | Deferred | v1.0 close |
| Follow-up | Real notification list behind Bell icon | Deferred | v1.0 close |
| Follow-up | Scroll restoration on Engagement profile back navigation (partial fix only) | Deferred | v1.0 close |
## Session Continuity
Last session: 2026-05-10T02:09:48.834Z
Stopped at: Phase 9 UI-SPEC approved
Resume file: .planning/phases/09-user-profile-preferences-new/09-UI-SPEC.md
Last session: 2026-07-10T15:53:23.273Z
Stopped at: v2.0 ROADMAP.md and REQUIREMENTS.md traceability written; awaiting `/gsd:plan-phase 10`
Resume file: None
</content>