Skip to content
Closed
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
ccb1e66
Wire free production readiness stack
njrini99-code Jun 30, 2026
cea85e3
fix(readiness): close route secret and dependency findings
njrini99-code Jun 30, 2026
399d664
fix(ops): close 24h GitHub issues for CI, secrets, and tooling
njrini99-code Jun 30, 2026
5a6cc85
fix(readiness): close 24h ops issues (#351–#365)
njrini99-code Jun 30, 2026
b9cda23
feat(routes): wire Next.js route bug catcher static checks
njrini99-code Jun 30, 2026
f2deea6
feat(routes): add route bug catcher playbook and hygiene hardening
njrini99-code Jun 30, 2026
19edb0e
fix(semgrep): document push token action revalidate exceptions
njrini99-code Jun 30, 2026
a3b487d
fix(ci): restore routes:check and clear semgrep on device-token path
njrini99-code Jun 30, 2026
69e4594
fix(golf): suppress semgrep on guarded round-submit fallback
njrini99-code Jun 30, 2026
8d271d4
fix(e2e): stabilize route crawler auth redirect waits
njrini99-code Jun 30, 2026
66c14b3
fix(ci): clear Review Gate semgrep on baseball games actions
njrini99-code Jun 30, 2026
fdb57f5
feat(ops): complete bug-discovery stack install
njrini99-code Jun 30, 2026
4479cc4
fix(ci): satisfy actionlint on Meticulous advisory workflow
njrini99-code Jun 30, 2026
26958c1
fix(ci): Meticulous advisory placeholder without unresolved action
njrini99-code Jun 30, 2026
e9b5b94
feat(ops): add visual baselines and verify:bugs entry points
njrini99-code Jun 30, 2026
2cbcf99
fix(ci): ZAP workflow env indirection for semgrep gate
njrini99-code Jun 30, 2026
ed2e716
fix(ci): supply Supabase env for visual regression job
njrini99-code Jun 30, 2026
cad174e
fix(ci): supply Supabase env for route crawler job
njrini99-code Jun 30, 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
16 changes: 0 additions & 16 deletions .cleanup/reports/secret-pattern-scan.txt

This file was deleted.

7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ NEXT_PUBLIC_SENTRY_DSN=https://your-sentry-dsn@sentry.io/your-project-id
SENTRY_ORG=your-org-name
SENTRY_PROJECT=your-project-name
SENTRY_AUTH_TOKEN=your-auth-token-here
# Optional release tag for error grouping (defaults to VERCEL_GIT_COMMIT_SHA in Vercel builds)
# NEXT_PUBLIC_SENTRY_RELEASE=

# Session Replay is enabled in src/instrumentation-client.ts:
# - replaysOnErrorSampleRate: 1.0 (100% of error sessions)
# - replaysSessionSampleRate: 0.1 (10% of all sessions in production)
# - maskAllText: true (PII masked in replay DOM)

# -----------------------------------------------------------------------------
# Feature Flags (Optional)
Expand Down
253 changes: 253 additions & 0 deletions .github/workflows/free-production-readiness.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
name: Free Production Readiness

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
business-contracts:
name: Business contracts
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Run low-gray business contracts
run: npm run verify:business

- name: Run advisory source-shape contracts
run: npm run test:business:advisory
continue-on-error: true

route-hygiene:
name: Route Hygiene P0/P1
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Check route hygiene
run: npm run routes:check

- name: Upload route hygiene reports
if: always()
uses: actions/upload-artifact@v7
with:
name: route-hygiene-reports
path: |
docs/operations/generated/route-inventory.json
docs/operations/generated/route-inventory.md
docs/operations/generated/route-hygiene-report.md
docs/operations/generated/route-link-report.json
docs/operations/generated/route-coverage-report.json
docs/operations/revealed-bugs/routes/**
if-no-files-found: ignore
retention-days: 14

route-crawler:
name: Route Crawler
runs-on: ubuntu-latest
continue-on-error: true
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Build route inventory
run: npm run routes:inventory

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

- name: Crawl routes
run: npm run routes:crawl

- name: Upload route crawler artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: route-crawler-artifacts
path: |
playwright-report/**
test-results/**
docs/operations/generated/route-crawler-report.md
if-no-files-found: ignore
retention-days: 14

prod-db-audit:
name: Production DB audit
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Run read-only production DB audit
env:
PROD_AUDIT_DATABASE_URL: ${{ secrets.PROD_AUDIT_DATABASE_URL }}
run: npm run prod:audit:db

- name: Upload production DB audit reports
if: always()
uses: actions/upload-artifact@v7
with:
name: prod-db-audit-reports
path: |
docs/operations/generated/prod-db-audit-findings.json
docs/operations/generated/prod-db-audit-report.md
if-no-files-found: ignore
retention-days: 14

visual-regression:
name: Visual regression
runs-on: ubuntu-latest
continue-on-error: true
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

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

- name: Run visual regression
run: npm run e2e:visual

- name: Upload visual diff artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: visual-regression-artifacts
path: |
playwright-report/**
test-results/**
if-no-files-found: ignore
retention-days: 14

schemathesis-advisory:
name: Schemathesis (advisory)
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Run Schemathesis advisory
run: npm run schemathesis:advisory

- name: Upload Schemathesis report
if: always()
uses: actions/upload-artifact@v7
with:
name: schemathesis-report
path: docs/operations/generated/schemathesis-report.json
if-no-files-found: ignore
retention-days: 14

static-radar:
name: Static radar advisory
runs-on: ubuntu-latest
continue-on-error: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep static radar steps running independently

In this workflow, static-radar is intended to collect Semgrep, dependency-cruiser, and jscpd advisory reports, but putting continue-on-error only on the job does not make later steps run after an earlier step fails; the default step condition remains success-only. In a fresh CI run, any nonzero exit from Semgrep prevents the dependency and duplicate-code reports from being generated or uploaded, so each radar step needs its own continue-on-error or the later report steps need if: always().

Useful? React with 👍 / 👎.

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Install Semgrep CE
run: python -m pip install semgrep

- name: Run Semgrep Helm rules
run: npm run analyze:semgrep
continue-on-error: true

- name: Run dependency-cruiser
run: npm run analyze:deps
continue-on-error: true

- name: Run duplicate-code radar
run: npm run analyze:duplicates
continue-on-error: true

- name: Run Helm auditor
if: always()
run: npm run auditor:all

- name: Upload static radar reports
if: always()
uses: actions/upload-artifact@v7
with:
name: static-radar-reports
path: |
docs/operations/generated/
docs/operations/revealed-bugs/production-readiness/
if-no-files-found: ignore
retention-days: 14
35 changes: 35 additions & 0 deletions .github/workflows/meticulous-advisory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Meticulous AI (Advisory)

# Meticulous requires a GitHub App install + project token.
# See docs/operations/integrations/METICULOUS.md for setup.
# This workflow skips until METICULOUS_API_TOKEN is configured.

on:
pull_request:
workflow_dispatch:

permissions:
contents: read
pull-requests: write

jobs:
meticulous:
name: Meticulous visual diff
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Meticulous status
env:
METICULOUS_API_TOKEN: ${{ secrets.METICULOUS_API_TOKEN }}
run: |
if [ -n "$METICULOUS_API_TOKEN" ]; then
echo "## Meticulous AI — token present"
echo ""
echo "Add the Meticulous GitHub Action step from \`docs/operations/integrations/METICULOUS.md\`"
echo "(upload-container or cloud-compute) once the project is linked."
exit 0
fi
echo "## Meticulous AI — skipped"
echo ""
echo "No \`METICULOUS_API_TOKEN\` repository secret. See \`docs/operations/integrations/METICULOUS.md\`."
echo "This job is advisory and does not block merge."
51 changes: 51 additions & 0 deletions .github/workflows/zap-scan-advisory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: ZAP Baseline Scan (Advisory)

on:
pull_request:
workflow_dispatch:
inputs:
target_url:
description: 'URL to scan (defaults to ZAP_TARGET_URL secret or production landing)'
required: false
type: string

permissions:
contents: read

jobs:
zap-baseline:
name: OWASP ZAP baseline
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Resolve scan target
id: target
env:
INPUT_URL: ${{ github.event.inputs.target_url }}
SECRET_URL: ${{ secrets.ZAP_TARGET_URL }}
DEFAULT_URL: https://helmsportslabs.com
run: |
if [ -n "$INPUT_URL" ]; then
echo "url=$INPUT_URL" >> "$GITHUB_OUTPUT"
elif [ -n "$SECRET_URL" ]; then
echo "url=$SECRET_URL" >> "$GITHUB_OUTPUT"
else
echo "url=$DEFAULT_URL" >> "$GITHUB_OUTPUT"
fi

- name: ZAP baseline scan
uses: zaproxy/action-baseline@v0.14.0
with:
target: ${{ steps.target.outputs.url }}
allow_issue_writing: false
fail_action: false
cmd_options: '-a'

- name: Upload ZAP report
if: always()
uses: actions/upload-artifact@v7
with:
name: zap-baseline-report
path: report_html.html
if-no-files-found: ignore
retention-days: 14
15 changes: 12 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,20 @@ scripts/rotate-demo-passwords.mjs
/test-results/
/playwright-report/

# Production-readiness generated reports.
/docs/operations/generated/
/.stryker-tmp/

# Cleanup agent raw/generated reports (never commit secret-scan output).
.cleanup/reports/secret-pattern-scan.txt
.cleanup/reports/secret-pattern-scan.redacted.txt

# Large generated showcase binaries (repo already ignores GolfHelm-Prospect-Deck.pptx).
GolfHelm-CoachHelm-Showcase.pdf
GolfHelm-Fairway-Guide.pdf
statsfixresults.pdf

# Local Playwright screenshot artifacts
e2e-screenshots/
.bugtest-screens/
# Capacitor iOS web bundle — regenerated by `npx cap sync ios` (see ios/App/ci_scripts/ci_post_clone.sh)
ios/App/App/public/
ios/App/App/config.xml

Loading
Loading