Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
d2aa1a5
fix(security): W0 — P0/P1 privacy, auth, and correctness wave
Jul 9, 2026
ffd0fd8
feat(golf): W1 — Fairway unconditional, legacy dual-tree deleted (gol…
Jul 9, 2026
84048a3
feat(baseball): W3+W4 — player nav to 8 tabs, Living Annual completion
Jul 9, 2026
5f49490
feat(golf): W2 — nav consolidated to 8 coach hubs / 8 player tabs
Jul 9, 2026
6866580
feat(baseball): W5 — Lift Lab chrome, a11y P1s, dead-code + manifest …
Jul 9, 2026
0a13f50
feat(golf+admin): W6+W9 — green ruled leaders, join-page fixes, admin…
Jul 9, 2026
3ebc803
Merge branch 'wave/w5-lift-a11y-deadcode' into integration/mission-ve…
Jul 9, 2026
c9935b6
fix(verify): Phase D round 1 — 19 adversarially-confirmed findings fixed
Jul 9, 2026
fbcac24
fix(verify): Phase D round 2 — 6 confirmed findings + follow-ups
Jul 9, 2026
2019db3
docs(matrix): W7 — truthful re-grade of all 22 readiness rows against…
Jul 9, 2026
afa2bfa
fix(verify): Phase D round 3 — final residue (glass in join/public/st…
Jul 9, 2026
70aa5da
fix: surface Signal Inbox mutation failures; unflash program-profile …
Jul 9, 2026
2f0eb19
fix: surface silent server-action failures across 7 mutation surfaces…
Jul 9, 2026
11180c5
feat: defect-sweep fixes + full taste-polish wave (Phase D mega-wave)
Jul 9, 2026
8f82063
fix: round-6 verification repairs — 26 confirmed findings across the …
Jul 10, 2026
c886c29
feat: tree-wide ink conversion + golf token sweep + Escape-bug class …
Jul 10, 2026
03e1aa8
docs: mission doc — Phase D final ledger + Phase E state (supersedes …
Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 22 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ SENTRY_READ_TOKEN=your-sentry-read-token-here
# SENTRY_READ_TOKEN is absent and the token has the read scopes above.
SENTRY_AUTH_TOKEN=your-auth-token-here

# -----------------------------------------------------------------------------
# Datadog RUM + Browser Logs (Optional — src/lib/datadog/index.ts)
# -----------------------------------------------------------------------------
# This module runs entirely client-side, so every var it reads MUST be
# NEXT_PUBLIC_-prefixed — un-prefixed vars are stripped at build time and
# read as undefined in the browser, silently falling back to defaults.
# Get application ID / client token from: https://app.datadoghq.com/organization-settings/rum
NEXT_PUBLIC_DD_APPLICATION_ID=YOUR_APPLICATION_ID
NEXT_PUBLIC_DD_CLIENT_TOKEN=your-datadog-client-token-here
# Datadog site (defaults to 'datadoghq.com'; use 'datadoghq.eu' etc for other regions).
# NEXT_PUBLIC_DD_SITE=datadoghq.com
# Service name tag (defaults to 'helm-sports-labs').
# NEXT_PUBLIC_DD_SERVICE=helm-sports-labs
# Env tag override. Leave unset to reuse NEXT_PUBLIC_VERCEL_ENV (production/
# preview/development) — Next.js inlines that one automatically, see next.config.mjs.
# NEXT_PUBLIC_DD_ENV=production

# -----------------------------------------------------------------------------
# Feature Flags (Optional)
# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -287,10 +304,9 @@ RLS_DIAGNOSTIC_TEST_PASSWORD=
# RINI_DEMO_FILLER_PASSWORD=

# -----------------------------------------------------------------------------
# Fairway redesign feature flag
# Fairway redesign feature flag (REMOVED — Wave W1, 2026-07-09)
# -----------------------------------------------------------------------------
# Gates the "Fairway" warm-premium design system (see ui-intelligence/
# DESIGN-SYSTEM.md). Default OFF — the current app is 100% unchanged; only
# redesigned components that opt in via src/lib/redesign/flag.ts + the
# `.fairway-ds` scope consume the new tokens/fonts. Accepts 1/true/on/yes.
# NEXT_PUBLIC_REDESIGN=false
# NEXT_PUBLIC_REDESIGN used to gate the "Fairway" warm-premium design system
# (see ui-intelligence/DESIGN-SYSTEM.md). Fairway is now the only dashboard
# tree — src/lib/redesign/flag.ts's isRedesignEnabled()/useRedesign() are
# hardcoded true — so this env var no longer has any effect. No action needed.
1 change: 0 additions & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ permissions:
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL || 'https://dummy-ci-build.supabase.co' }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'dummy-anon-key-ci-build-only' }}
NEXT_PUBLIC_REDESIGN: "true"
E2E_GOLF_EMAIL: ${{ secrets.E2E_GOLF_EMAIL }}
E2E_GOLF_PASSWORD: ${{ secrets.E2E_GOLF_PASSWORD }}
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/pr-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ permissions:
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL || 'https://dummy-ci-build.supabase.co' }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY || 'dummy-anon-key-ci-build-only' }}
NEXT_PUBLIC_REDESIGN: "true"
NODE_OPTIONS: --max-old-space-size=4096

jobs:
Expand Down
40 changes: 40 additions & 0 deletions docs/audits/BASEBALLHELM_LIFTLAB_GAP_MAP_2026-06-25.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,46 @@
**Source:** 5-reader parallel audit, 109 raw items → 71 deduped gaps
**Method:** Deduplicated near-duplicates, re-prioritized (P0=blocking/security/data-loss, P1=core unbuilt feature, P2=polish), grouped into 9 parallel build waves.

> **⚠️ Historical snapshot (2026-06-25) — superseded.** This gap map predates
> ~40 commits of remediation, including the Lift Lab unification train
> (completed 2026-07-08) and the W0–W9 production-readiness mission
> (2026-07-09). Most items below have shipped; the raw list is kept as-is
> for historical record rather than rewritten in place. See
> `docs/operations/BASEBALLHELM_FEATURE_READINESS_MATRIX.md` for the
> current, row-by-row readiness state (re-graded 2026-07-09).
>
> **Current state (2026-07-09):**
> - **W1 (DB foundation) — done.** All `helm_lifting_*` migrations
> (`20260625000000`–`20260625000030` and later hardening/drift-closure
> migrations) are confirmed applied to prod via `list_migrations`; types
> have been regenerated and the `as any`/`fromUntyped` casts flagged in W1
> are gone from the baseball performance page's core reads.
> - **W2 (DB security) — done.** The anon-EXECUTE SECDEF RPCs, the
> `baseball_notifications` `WITH CHECK (true)` policy, and the anon
> GRANT-ALL findings from this pass were all closed in later hardening
> migrations (`baseball_anon_revoke_wave1/2`, `baseball_notifications_revoke_anon`,
> `revoke_anon_secdef_rpc_drift_full`, and the 2026-07-08/09 gate-and-revoke
> passes) — verified via the live migration list, not just the repo.
> - **W7 (Lift Lab core) — built.** Exercise CRUD, program editor add/edit
> flows, player session execution (`/lifting/dashboard/lift` +
> `[sessionId]`), and a Today Board now exist; the baseball performance
> dashboard was rewired off legacy `baseball_lift_*` tables onto unified
> `helm_lifting_*` reads (the "W2-G REWIRE" banner in
> `src/app/baseball/(dashboard)/dashboard/performance/page.tsx`).
> - **Design system — applied.** The Living Annual (LA) chrome (W5 in the
> production-readiness mission) has been applied across baseball surfaces
> including Lift Lab-adjacent screens.
> - **Legacy tables — graveyarded**, not left dangling: three graveyard
> migrations (`graveyard_dead_tables_phase1`, `graveyard_dead_liftlab_tables_phase2`,
> `graveyard_legacy_liftlab_tables_phase3`) retired the superseded
> `baseball_lift_*`/legacy Lift Lab tables once the unified model took over.
> - **What's still open:** treat the readiness matrix (not this document) as
> the source of truth for exactly which BaseballHelm/Lift Lab surfaces
> still have a real, currently-tracked gap — several of the W9 UI-polish
> items (skeletons, off-brand colors) and some W6/W8 feature items below
> may still be outstanding and were not re-verified item-by-item as part
> of this pass.

---

## Summary Table
Expand Down
95 changes: 92 additions & 3 deletions docs/audits/PRODUCTION_READINESS_MISSION_2026-07-09.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
**Nav counts today** (primary+secondary rail destinations, Settings footer excluded):
| Surface | Today | Target |
|---|---|---|
| Baseball coach | **8 hubs** ✅ (Dashboard, Messages, Team, Stats & Performance, Development, Recruiting, Academics, Management) | keep |
| Baseball coach | **8 hubs** ✅ (8 standard: Dashboard, Messages, Team, Stats & Performance, Development, Recruiting, Academics, Management; 7 for High School — Recruiting hidden by design, `RECRUITING_PROGRAM_TYPES`; showcase variant has its own two-level org→team rail) | keep |
| Baseball player | **9** (7 primary + exposureNoun + Settings-in-rail) | **8** — move Settings to pinned footer (parity with coach shell) |
| Golf coach (Fairway, live) | **15** (7 primary + 8 secondary) | **8 hubs** |
| Golf player (Fairway, live) | **12** (8 primary + 4 secondary) | **8** |
Expand Down Expand Up @@ -101,7 +101,7 @@ policies on hot golf tables, 199 unindexed FKs, 256 unused indexes).

## Target IA (~8 tabs, owner directive)

### Baseball coach — unchanged (8 hubs) ✅
### Baseball coach — unchanged (8 hubs: 8 standard; 7 for HS — Recruiting hidden by design; showcase variant has its own two-level rail) ✅
### Baseball player — 8 (move Settings out of rail to pinned footer)
Today · Schedule · My Profile · Stats · Development · Team · Messages · [exposureNoun]

Expand All @@ -114,7 +114,7 @@ Today · Schedule · My Profile · Stats · Development · Team · Messages · [
6. **Messages** (Messages · Announcements)
7. **Operations** (Tasks · Documents)
8. **Courses**
Footer: Settings · Sign out. Mobile bottom bar: Home, CoachHelm, Roster, Calendar, Messages (unchanged).
Footer: Settings · Sign out. Mobile bottom bar: Home, CoachHelm, Team, Calendar, Messages (code renders label "Team", opening the Team hub — not "Roster"; unchanged from live behavior).

### Golf player — 8
1. **Dashboard** (merge Hub into Dashboard landing — two "homes" is duplicative)
Expand Down Expand Up @@ -193,3 +193,92 @@ Footer: Settings · Sign out.
- Workflow executors: always `model:'sonnet'`; capture real exit codes
(never `cmd | tail` as a gate).
- add columns BEFORE bulk-ingest; verify migrations via information_schema.

---

- **Phase D — adversarial verify loop** until 2 consecutive dry rounds
(ledger below; loop still open as of `8f820639`).
- **Phase E — advisors re-run + ONE production deploy + final report**
(checklist below; merge/deploy both pending Nick).

## Phase D — verification ledger

Six numbered adversarial-verify rounds plus one mega-wave have landed on
`integration/mission-verify` (15 commits ahead of `origin/main` as of
`8f820639`). Each round: an adversarial pass re-reads the diff/runtime
behavior against its own claims, fixes what it confirms, and gates before
merge — no round has yet come back dry.

| Round | Commit | Scope | Confirmed findings | Gates |
|---|---|---|---|---|
| 1 | `c9935b63` | P0 recruiting-guard trigger widened (flip-type-then-activate laundering closed); golf CoachHelm breadcrumb derivation; 16 baseball `loading.tsx` rebuilds; docs/registry truth | **19** | tsc 0, lint 0, unit 4614, build 0 |
| 2 | `fbcac248` | JUCO write-ordering fix (2nd `recruiting_activated` site the round-1 trigger note missed); golf mobile-nav active-state; glass purge on 46 baseball files + 14 more emerald-hue files; 3 pre-existing CodeQL findings; box-score colspan; stale e2e specs deleted | **6** + follow-ups | tsc 0, lint 0, unit green, build 0 |
| — | `2019db30` | **W7 re-grade** (docs, not an adversarial round): every one of 22 readiness-matrix rows re-verified against live source + prod migrations. Rollup moved **0 ready / 18 partial → 10 ready / 10 partial / 1 route-only / 1 hidden**. `check:readiness-matrix` exit 0; `readiness-matrix-routes` 204 tests passed | n/a | n/a |
| 3 | `afa2bfaa` | Final glass residue: `glass-standard/prominent/subtle` → **zero** under `src/app/baseball/**` (join/staff-join/demo-sessions/public-program); `EventsClient` badges onto `InkBadge` tone matrix | not itemized in commit trailer [verify] | tsc 0, lint 0, unit green, build 0 |
| 4 | `70aa5dab` | Signal Inbox silently discarded mutation results (toast now surfaces failures, convert-dialog stays open on failure); program-profile loading-header color flash fixed | **2** | tsc 0, lint 0, unit 4611/455 files |
| 5 | `2f0eb19f` | One finding-class, 7 sites: client awaits a server action and discards the result, so failures render as success (golf insight rate/dismiss ×3, baseball import approve, readiness check-in, lift program editor, recruiting pipeline) | **7** | tsc 0, lint 0, unit 4611/455 files |
| **mega** | `11180c54` | **"Phase D mega-wave"** — 4 fleets in one gated commit: Defect Sweep 1 (CRM unsubscribe false-ok, LLM spend-record logging, JUCO revert-only-if-it-flipped, 4 silent-failure fixes, double-submit guards, bounded chat fetch, paginated admin queries past the 1000-row cap, 4 tz day-bucketing fixes, round-submit a11y, 2 error boundaries); Defect Sweep 2 (email-route truth, HTML-injection escaping, 6 settings-stub regressions, Datadog client env, idempotent digest crons, registered refresh-engagement cron, batched golf N+1s, auth-redirect fallback chain, 2 mission tests made to actually gate); Authz Hardening (4 unauthenticated admin-client drivers de-exported from `'use server'` modules, zero client callers, coverage tripwire honestly re-derived **425 → 419**, −6 verified); Taste-Polish Wave (28 packets from a 15-cluster Opus design review: ~14 `loading.tsx` rewrites, legacy-island rebuilds onto Living Annual/Fairway, date/numeral unification) | **22 + 16** (Defect Sweeps 1+2); 28 polish packets not counted as "findings" | build 0, tsc 0, lint 0, unit 4616/455 files (4 test files repaired in-wave) |
| 6 | `8f820639` | Rebuild regressions from the mega-wave's own rewrites (Escape-key focus trap, overdue-task badge collision, deterministic aria-labels, off-by-one date anchoring, unearned "verified" checkmark, `InkNotice` error-ink var, Messages scroll guard + dead-component deletion, safe-area double-counting, 4 skeleton/board mismatches); missed-adjacent glass/color residue (PositionPlanner/PositionPlayerPill, 5 more components onto `InkBadge`/`InkNotice`, `CalendarFairway` event-ink map); 2 comment-terminator bugs from the fixer wave itself, caught by gates | **26** | build 0, tsc 0, lint 0, unit 0 (no count restated in trailer) |

Running total of discretely-counted confirmed findings across rounds 1, 2,
4, 5, 6 and the mega-wave's two defect sweeps: **19 + 6 + 2 + 7 + 22 + 16 +
26 = 98** [verify — sum of trailer-stated counts; round 3's residue batch
and the mega-wave's 28 taste packets are excluded as not discretely
numbered in their own commits].

**Status**: no round has come back dry yet, so the stated exit criterion
(2 consecutive dry rounds) is not met. A round-7 pass is in flight —
**uncommitted at HEAD** as of this ledger — touching
`snapshot-cards/shared.tsx`, `SnapshotHeaderBand.tsx`, `ProfileTimeline.tsx`,
`PlayerProfileClient.tsx`, and `PositionPlayerPill.tsx`: raw
`amber-*`/`warm-*`/`red-*` Tailwind swatches on the player-profile snapshot
cards and the position-planner pill are being converted to the ink system
(`--notice-error-ink` via `color-mix()`, `pursuit` clay-ink ramp), with
`PlayerNotesSection.tsx` and `PlayerPerformanceTab.tsx` explicitly
name-flagged in-code as deferred siblings still carrying raw color. This is
the same class of fix as round 6's residue sweep and overlaps the
ink-conversion follow-up wave below — it has not been gated or committed.

## Phase E — closeout checklist

- [x] **Advisors re-run** — Supabase advisors re-checked against live prod
post-Phase-D fixes.
- [ ] **Merge to `main`** — pending Nick. Branch `integration/mission-verify`
is 15 commits ahead of `origin/main` (`a3946332`); not yet opened/merged
as a PR.
- [ ] **Production deploy** — pending, and gated on the merge above. Standing
constraint: ONE intentional production deploy for the whole mission, no
incremental previews.
- [x] **Trigger apply sequenced** — `supabase/migrations/20260709010200_baseball_players_recruiting_guard.sql`
(the `BEFORE UPDATE` guard on `recruiting_activated`) carries a header
banner marking it **DEPLOY-SEQUENCED**: it must land together with, or
immediately after, the production deploy that ships W0a's
`activateRecruitingExposure`/`deactivateRecruitingExposure` rewrite in
`src/app/baseball/actions/player-access.ts` (now writing via
`createAdminClient()`/service_role). Applying the trigger before that
deploy lands would `42501` every legitimate activation/withdrawal on live
prod. Its two W0b siblings — `20260709010000` (public-view visibility
filters) and `20260709010100` (gate `get_admin_event_summary`) — have
**already been applied to prod**, independently, with no such dependency.
- [ ] **Final report** — not yet written; blocked on the merge/deploy above.

## Two follow-up waves (queued after Phase D/E close — both already have a down payment in flight)

- **Agent-legibility sweep** (repo map doc, stale-doc truth pass, dead-code
deletion) — tracked as not-yet-started, but the current uncommitted diff
already contains one instance of the stale-doc truth pass: `docs/operations/BASEBALLHELM_FEATURE_READINESS_MATRIX.md`'s
Stats/Box-Score row cited a nonexistent migration filename
(`20260709042343`); corrected in-flight to the real applied migration
(`20260708150000_baseball_box_score_upsert_and_error_detail.sql`).
- **Tree-wide red/amber → ink conversion remainder** — tracked at 182 hits /
57 baseball files [verify — this session's own broader grep for
`(bg|text|border)-...-(red|amber)-[0-9]+` under `src/app/baseball` +
`src/components/baseball` at HEAD returns a substantially higher count
(~470 hits / ~75 files); the tracked figure likely predates several
since-landed conversions (round 6, mega-wave taste-polish) or excludes
the deliberately-preserved graduated readiness/status-color legends —
reconcile scope before treating either number as authoritative]. In
flight uncommitted right now on the player-profile snapshot-card cluster
and `PositionPlayerPill` (see Phase D status above); `PlayerNotesSection.tsx`
and `PlayerPerformanceTab.tsx` are explicitly flagged in-code as the next
deferred targets.
16 changes: 13 additions & 3 deletions docs/baseball/ui-migration-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@
kit so the product reads as a single publication. No surface keeps a bespoke card, header,
empty state, or stat display once the kit covers it. Consistency is the deliverable.

Delivery mechanism = the existing **Fairway redesign layer** (`NEXT_PUBLIC_REDESIGN`,
`.fairway-ds` scope, `--fw-*` tokens). The Living-Annual kit is the **baseball-native
vocabulary layered on top of the Fairway tokens** — not a second design system.
Delivery mechanism = the existing **Fairway redesign layer** (`.fairway-ds` scope,
`--fw-*` tokens — unconditional, no flag). The Living-Annual kit is the
**baseball-native vocabulary layered on top of the Fairway tokens** — not a second
design system.

> **Update (2026-07-09, golf Wave W1):** `NEXT_PUBLIC_REDESIGN` no longer gates
> anything — `isRedesignEnabled()`/`useRedesign()` in `src/lib/redesign/flag.ts`
> are hardcoded `true` (the legacy `GolfDashboardShell`/`GolfSidebar` fork they
> used to gate was deleted). Setting the env var has zero effect. Baseball's
> `BaseballFairwayShell` renders unconditionally and was never flag-gated the
> way golf's dual tree was; `src/components/layout/header.tsx` still calls
> `isRedesignEnabled()` (always `true`) to suppress its own legacy chrome, but
> that is a hardcoded return, not env-driven behavior.

---

Expand Down
Loading
Loading