Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ae379eb
devibe: remove dead files — knip batch 1/2 (mode-toggle, notification…
njrini99-code Jul 15, 2026
3011efa
devibe: remove dead files — knip batch 2/2 (golf/travel legacy, soren…
njrini99-code Jul 15, 2026
40e10a1
devibe: remove orphaned root scaffolding (.taskmaster, .full-stack-fe…
njrini99-code Jul 15, 2026
c4ec776
devibe: console triage — remove debug-leftover console.log in use-ser…
njrini99-code Jul 15, 2026
9c3a2f6
Build the /baseball public marketing page (was a bare redirect) (#865)
njrini99-code Jul 15, 2026
08251a3
Fix invisible names/numerals on public baseball profile pages (no Laz…
njrini99-code Jul 15, 2026
760d5bb
Add production visual-audit screenshot crawl (GHA, manual-only) (#867)
njrini99-code Jul 15, 2026
cafa746
db(baseball): write #379 legacy stats backfill migration (pending Nic…
njrini99-code Jul 15, 2026
d2bb014
baseball(engine): wire event-derived velocity into engine-run/outcome…
njrini99-code Jul 15, 2026
fe26e7c
Consolidate stats-upload wizard into Import Center (canonical) (#863)
njrini99-code Jul 15, 2026
3759cbe
ci(visual-audit): two spaces before inline version comments (yamllint…
Jul 15, 2026
e88f866
fix(migration): qualify digest() as extensions.digest — pgcrypto is n…
Jul 16, 2026
510cb3a
db(baseball): manifest-based rollback + concurrency lock for #379 bac…
Jul 16, 2026
a3b6f29
fix(baseball): validate invite code is alphanumeric before router.pus…
Jul 16, 2026
da60296
fix(baseball): suppressHydrationWarning on legacy-upload created_at c…
Jul 16, 2026
9f5e7b7
fix(baseball): hide Stats Center import actions for staff with neithe…
Jul 16, 2026
e51a3c0
fix(baseball): filter provenance to the reading-bearing rows sampleSi…
Jul 16, 2026
528ef83
fix(baseball): resolve capability requirement inside guarded flow + r…
Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 0 additions & 123 deletions .full-stack-feature/01-requirements.md

This file was deleted.

13 changes: 0 additions & 13 deletions .full-stack-feature/state.json

This file was deleted.

108 changes: 108 additions & 0 deletions .github/workflows/visual-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Visual Audit

# Manual-only production screenshot crawl (e2e/visual-audit.spec.ts). NOT part
# of any PR gate or push trigger — this hits a real, deployed base_url (prod
# by default) as both the baseball coach and player roles, discovers every
# visible nav route from the LIVE DOM, and captures full-page screenshots at
# phone (390x844) and desktop (1440x900) viewports for a human/follow-up
# review pass to look at. Screenshots are data capture, not assertions — the
# spec only fails this workflow on a login failure or a total navigation
# failure (see e2e/visual-audit.spec.ts's module doc for the exact contract).
#
# Runs ONLY the baseball auth setup + this spec — no build, no dev server, no
# seeding: PLAYWRIGHT_BASE_URL points playwright.config.ts at the deployed
# base_url, which makes its `webServer` block a no-op (only defined when
# PLAYWRIGHT_BASE_URL is unset), so there is nothing to boot locally.
#
# `--project=baseball-coach --project=baseball-player` alone is sufficient to
# also run the `setup` project (playwright/baseball-auth.setup.ts): both
# projects declare `dependencies: ['setup']` in playwright.config.ts, and
# Playwright always runs a project's dependencies with their own FULL,
# unfiltered test file set — the `e2e/visual-audit.spec.ts` file argument on
# the CLI only restricts the explicitly-requested top-level projects
# (baseball-coach/baseball-player), never a project pulled in purely as a
# dependency. Verified against the installed playwright package's runner
# source (collectProjectsAndTestFiles in lib/runner/index.js) before relying
# on it here. The `setup` project's testMatch is scoped to
# `baseball-auth.setup.ts` specifically, so Golf's `playwright/auth.setup.ts`
# is never pulled in.
#
# SECURITY: consumes ZERO untrusted user input — the only `${{ }}` expressions
# are a trusted workflow_dispatch string input, secrets, and github.run_number.

on:
workflow_dispatch:
inputs:
base_url:
description: Base URL to crawl (playwright.config.ts baseURL)
required: false
default: "https://helmsportslabs.com"
type: string
Comment on lines +30 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Block arbitrary audit origins before sending production credentials.

.github/workflows/visual-audit.yml:55 accepts any dispatch URL, then Playwright submits the coach/player secrets to that origin’s /baseball/login. A dispatcher can therefore direct production credentials to an external host. Remove configurability or validate an HTTPS hostname allowlist before the crawl.

Proposed allowlist guard
 jobs:
   visual-audit:
+    environment: production
     env:
       PLAYWRIGHT_BASE_URL: ${{ inputs.base_url }}
@@
     steps:
+      - name: Validate audit target
+        env:
+          AUDIT_URL: ${{ inputs.base_url }}
+        run: |
+          node -e '
+            const url = new URL(process.env.AUDIT_URL);
+            const allowed = new Set(["helmsportslabs.com"]);
+            if (url.protocol !== "https:" || !allowed.has(url.hostname)) {
+              throw new Error(`Unapproved visual-audit target: ${url.origin}`);
+            }
+          '

Also applies to: 54-63

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/visual-audit.yml around lines 30 - 40, Restrict the
workflow_dispatch base_url used by the visual audit before any credentials are
submitted. Update the base_url input and the crawl setup around the Playwright
configuration to either remove URL configurability or validate that it is HTTPS
and matches an explicit allowlist of approved production hostnames, rejecting
all other origins.


concurrency:
group: visual-audit-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
visual-audit:
name: Visual audit (coach + player)
runs-on: ubuntu-latest
timeout-minutes: 30
env:
PLAYWRIGHT_BASE_URL: ${{ inputs.base_url }}
VISUAL_AUDIT: "1"
# Fail loud (not a graceful skip) on missing/bad creds — this run is
# pointless without a real authenticated crawl.
PLAYWRIGHT_BASEBALL_REQUIRED: "1"
E2E_BASEBALL_COACH_EMAIL: ${{ secrets.E2E_BASEBALL_COACH_EMAIL }}
E2E_BASEBALL_COACH_PASSWORD: ${{ secrets.E2E_BASEBALL_COACH_PASSWORD }}
E2E_BASEBALL_PLAYER_EMAIL: ${{ secrets.E2E_BASEBALL_PLAYER_EMAIL }}
E2E_BASEBALL_PLAYER_PASSWORD: ${{ secrets.E2E_BASEBALL_PLAYER_PASSWORD }}
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm ci

- name: Cache Playwright browsers
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
playwright-${{ runner.os }}-

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

# Runs the `setup` project (baseball coach + player auth, persisting
# storageState) as a dependency, then this spec under baseball-coach
# and baseball-player — see the header comment above for why no
# explicit --project=setup is needed.
- name: Run visual-audit screenshot crawl
run: |
npx playwright test \
--project=baseball-coach \
--project=baseball-player \
e2e/visual-audit.spec.ts

- name: Upload visual-audit screenshots + manifests
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4
with:
name: visual-audit-${{ github.run_number }}
path: test-results/visual-audit
retention-days: 7
if-no-files-found: warn
124 changes: 0 additions & 124 deletions .taskmaster/README.md

This file was deleted.

Loading
Loading