Skip to content

Wire free production readiness stack#358

Closed
njrini99-code wants to merge 18 commits into
test-hardening/golf-stats-coachhelm-contractsfrom
test-hardening/free-production-readiness-stack
Closed

Wire free production readiness stack#358
njrini99-code wants to merge 18 commits into
test-hardening/golf-stats-coachhelm-contractsfrom
test-hardening/free-production-readiness-stack

Conversation

@njrini99-code

@njrini99-code njrini99-code commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • installs/wires the missing free readiness tools: Stryker, dependency-cruiser, jscpd, plus verified local Semgrep/Gitleaks/OSV/k6 CLIs
  • splits gray source-shape contracts into an advisory Vitest lane and adds low-gray product-trust state mappers plus GolfHelm fast-check property contracts
  • adds Semgrep CE rules, dependency-cruiser architecture firewall, route hygiene scripts, read-only DB audit, auditor issue factory, k6 smoke, critical/a11y Playwright starters, and a Free Production Readiness workflow
  • documents gate posture and adds safe issue drafts for redacted Gitleaks and OSV findings

Verification

  • npm run test:business
  • npm run test:business:advisory
  • npm run test:golf-stats && npm run test:coachhelm-truth && npm run test:product-trust
  • npm run routes:check
  • npm run analyze:semgrep (runs, reports 254 advisory findings)
  • npm run analyze:deps
  • npm run analyze:duplicates
  • npm run prod:audit:db (skips live DB without read-only URL, reports P3)
  • npm run auditor:all
  • npm run typecheck
  • npx actionlint .github/workflows/free-production-readiness.yml .github/workflows/ci.yml
  • git diff --check

Known radar findings

  • Gitleaks reported 81 redacted findings; raw report is ignored and not committed
  • OSV reported 1 vulnerability result group; needs reachability triage
  • route hygiene found 29 advisory stale-link candidates, no P0/P1 blockers
  • Semgrep reported 254 advisory findings; not a hard gate yet

Greptile Summary

This PR wires a free production-readiness stack across CI, scripts, tests, and docs. The main changes are:

  • New GitHub Actions workflow for business contracts, route hygiene, and static radar.
  • New Semgrep, dependency-cruiser, jscpd, Knip, Stryker, k6, Playwright, and auditor wiring.
  • New route hygiene, secret scan, read-only DB audit, and report aggregation scripts.
  • New business-contract and product-trust test coverage.
  • Updated operations docs for gate posture and local readiness checks.

Confidence Score: 4/5

This should wait until the remaining script failures are fixed.

  • The database audit can still connect through the generic app URL.
  • The auditor can still remove tracked or manually edited draft files.
  • Several report commands can still fail on a clean checkout before the tools run.

scripts/prod-audit/run-readonly-db-audit.mjs, scripts/auditor/run-helm-auditor.mjs, package.json

Security Review

The database audit script can still use the generic app database URL when the dedicated audit URL is missing, so the audit can run with the wrong credential.

Important Files Changed

Filename Overview
scripts/prod-audit/run-readonly-db-audit.mjs Adds the production database audit report, but the URL selection still allows the app database credential.
scripts/auditor/run-helm-auditor.mjs Adds report aggregation and draft generation, but the cleanup still deletes Markdown files from a tracked drafts path.
package.json Adds readiness commands, but several report-producing commands still fail on a fresh checkout when the generated directory is absent.
.github/workflows/free-production-readiness.yml Adds the production-readiness workflow for business contracts, route hygiene, and advisory static analysis.

Fix All in Claude Code

Reviews (3): Last reviewed commit: "fix(ops): close 24h GitHub issues for CI..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Context used (5)

  • Context used - .greptile/instructions.md (source)
  • Context used - .greptile/config.json (source)
  • Context used - CLAUDE.md (source)
  • Context used - .cursorrules (source)
  • Context used - AGENTS.md (source)

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (3)
  • main
  • develop
  • release/*

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 70001731-dfe5-4c35-89c5-ef4b3d27222f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test-hardening/free-production-readiness-stack

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
helmv3 Ready Ready Preview, Comment Jun 30, 2026 2:58am

Request Review

const outDir = join(process.cwd(), 'docs/operations/generated');
mkdirSync(outDir, { recursive: true });

const connectionString = process.env.PROD_AUDIT_DATABASE_URL || process.env.DATABASE_URL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Production Audit Uses App URL

When PROD_AUDIT_DATABASE_URL is unset but DATABASE_URL exists, npm run prod:audit:db connects to the generic application database instead of skipping. That breaks the documented read-only audit contract and can run the production audit against a writable primary connection while reporting it as read-only.

Suggested change
const connectionString = process.env.PROD_AUDIT_DATABASE_URL || process.env.DATABASE_URL;
const connectionString = process.env.PROD_AUDIT_DATABASE_URL;

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment on lines +8 to +10
for (const file of readdirSync(draftsDir)) {
if (file.endsWith('.md')) unlinkSync(join(draftsDir, file));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Tracked Drafts Are Deleted

docs/operations/revealed-bugs/production-readiness/ is a tracked directory in this PR, but npm run auditor:all deletes every Markdown file there before regenerating only current P0/P1 findings. Any edited draft or manually added follow-up in that tracked path is silently removed when the auditor runs.

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment thread package.json
"routes:check:coverage": "node scripts/route-hygiene/check-route-coverage.mjs",
"routes:check": "npm run routes:inventory && npm run routes:check:duplicates && npm run routes:check:links && npm run routes:check:boundaries && npm run routes:check:coverage && npm run routes:check:dead",
"analyze:semgrep": "semgrep scan --config .semgrep --json --output docs/operations/generated/semgrep.json",
"analyze:deps": "depcruise src --config dependency-cruiser.config.cjs --output-type json > docs/operations/generated/dependency-cruiser.json",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Missing Report Directory Breaks Analysis

docs/operations/generated/ is gitignored, so it will not exist after a fresh checkout. Shell redirection cannot create that parent directory, so npm run analyze:deps fails before dependency-cruiser runs unless another command happened to create the directory first.

Fix in Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ccb1e66adc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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 👍 / 👎.

Comment thread package.json
"routes:check:coverage": "node scripts/route-hygiene/check-route-coverage.mjs",
"routes:check": "npm run routes:inventory && npm run routes:check:duplicates && npm run routes:check:links && npm run routes:check:boundaries && npm run routes:check:coverage && npm run routes:check:dead",
"analyze:semgrep": "semgrep scan --config .semgrep --json --output docs/operations/generated/semgrep.json",
"analyze:deps": "depcruise src --config dependency-cruiser.config.cjs --output-type json > docs/operations/generated/dependency-cruiser.json",

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 Create the report directory before redirecting output

When npm run analyze:deps is run on a fresh checkout or in an independent CI job, docs/operations/generated/ is ignored and absent, so the shell redirection fails with “Directory nonexistent” before depcruise starts. Add a mkdir -p docs/operations/generated wrapper or write the report from a script so this documented standalone lane actually produces its artifact.

Useful? React with 👍 / 👎.

Comment on lines +8 to +9
for (const file of readdirSync(draftsDir)) {
if (file.endsWith('.md')) unlinkSync(join(draftsDir, file));

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 Do not delete tracked readiness issue drafts

Running npm run auditor:all unconditionally removes every Markdown file in docs/operations/revealed-bugs/production-readiness, but this commit also adds tracked redacted Gitleaks/OSV drafts in that directory. If the matching generated inputs are unavailable or change, the auditor deletes committed documentation and leaves the worktree dirty, so the cleanup should be limited to ignored/generated files or only overwrite drafts it is about to regenerate.

Useful? React with 👍 / 👎.

const outDir = join(process.cwd(), 'docs/operations/generated');
mkdirSync(outDir, { recursive: true });

const connectionString = process.env.PROD_AUDIT_DATABASE_URL || process.env.DATABASE_URL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Audit URL Fallback

prod:audit:db still falls back to the generic app DATABASE_URL when PROD_AUDIT_DATABASE_URL is unset. In a normal production or CI environment where DATABASE_URL exists, the documented skip path is bypassed and the audit connects with the app database credential instead of a dedicated read-only audit credential.

Suggested change
const connectionString = process.env.PROD_AUDIT_DATABASE_URL || process.env.DATABASE_URL;
const connectionString = process.env.PROD_AUDIT_DATABASE_URL;

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment on lines +8 to +10
for (const file of readdirSync(draftsDir)) {
if (file.endsWith('.md')) unlinkSync(join(draftsDir, file));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Draft Cleanup Scope

auditor:all deletes every Markdown file under docs/operations/revealed-bugs/production-readiness/, but that path is not ignored like docs/operations/generated/. A tracked or manually edited draft in that directory can be removed before the script regenerates only the current blocking findings, so some drafts are silently lost instead of updated.

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment thread package.json
Comment on lines +59 to +60
"analyze:deps": "depcruise src --config dependency-cruiser.config.cjs --output-type json > docs/operations/generated/dependency-cruiser.json",
"analyze:knip": "knip --reporter json > docs/operations/generated/knip.json",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Report Directory Missing

analyze:deps and analyze:knip still redirect into docs/operations/generated/, which is ignored and absent on a fresh checkout. The shell opens the redirect target before starting depcruise or knip, so these commands fail immediately unless another command happened to create the directory first.

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment thread package.json
"secrets:scan": "node scripts/security/run-gitleaks-current-tree.mjs",
"secrets:scan:history": "gitleaks git . --redact --report-format json --report-path docs/operations/generated/gitleaks-history.json",
"deps:audit:npm": "npm audit --audit-level=high",
"deps:audit:osv": "osv-scanner --lockfile package-lock.json --format json > docs/operations/generated/osv.json",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 OSV Report Directory

deps:audit:osv redirects stdout to docs/operations/generated/osv.json without creating the ignored parent directory first. On a clean checkout the shell fails before osv-scanner runs, so the OSV report is never produced for the auditor to consume.

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Remediate gitleaks findings, add redacted cleanup secret-scan, move team-switcher constants into lib, retire .helm live-queue references, and document resolved follow-ups.

Co-authored-by: Cursor <cursoragent@cursor.com>
const outDir = join(process.cwd(), 'docs/operations/generated');
mkdirSync(outDir, { recursive: true });

const connectionString = process.env.PROD_AUDIT_DATABASE_URL || process.env.DATABASE_URL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Audit URL Fallback

prod:audit:db still falls back to the generic app DATABASE_URL when PROD_AUDIT_DATABASE_URL is unset. In a production or CI environment where DATABASE_URL is present, the documented skip path is bypassed and this audit connects with the app database credential while the report marks the run as read_only: true.

Suggested change
const connectionString = process.env.PROD_AUDIT_DATABASE_URL || process.env.DATABASE_URL;
const connectionString = process.env.PROD_AUDIT_DATABASE_URL;

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment on lines +7 to +9
mkdirSync(draftsDir, { recursive: true });
for (const file of readdirSync(draftsDir)) {
if (file.endsWith('.md')) unlinkSync(join(draftsDir, file));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Draft Cleanup Scope

auditor:all deletes every Markdown file under docs/operations/revealed-bugs/production-readiness/ before regenerating only current blocking drafts. That directory is not ignored like docs/operations/generated/, so a tracked or manually edited draft in this path is silently removed when the auditor runs.

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Comment thread package.json
Comment on lines +59 to +66
"analyze:deps": "depcruise src --config dependency-cruiser.config.cjs --output-type json > docs/operations/generated/dependency-cruiser.json",
"analyze:knip": "knip --reporter json > docs/operations/generated/knip.json",
"analyze:duplicates": "jscpd src --reporters json,markdown --output docs/operations/generated/jscpd",
"secrets:scan": "node scripts/security/run-gitleaks-current-tree.mjs",
"cleanup:secret-scan": "node scripts/cleanup/run-secret-pattern-scan.mjs",
"secrets:scan:history": "gitleaks git . --redact --report-format json --report-path docs/operations/generated/gitleaks-history.json",
"deps:audit:npm": "npm audit --audit-level=high",
"deps:audit:osv": "osv-scanner --lockfile package-lock.json --format json > docs/operations/generated/osv.json",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Report Directory Missing

analyze:deps, analyze:knip, and deps:audit:osv still redirect output into docs/operations/generated/ without creating the ignored parent directory first. On a fresh checkout, the shell opens the redirect target before starting depcruise, knip, or osv-scanner, so these commands fail immediately unless another command happened to create the directory.

Context Used: .greptile/instructions.md (source)

Fix in Claude Code

Resolve dependency-cruiser violations (25→0), tune Semgrep/JSCPD noise,
untrack Capacitor iOS bundle, migrate dense raw-button surfaces to
design-system primitives where feasible, and wire prod DB audit skip path.

Co-authored-by: Cursor <cursoragent@cursor.com>
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown

Too many files changed for review. (189 files found, 100 file limit)

njrini99-code and others added 6 commits June 29, 2026 21:46
Add route normalizer, inventory/report scripts, Playwright crawler,
Semgrep companion rules, and ownership matrix. Route hygiene passes
with 0 P0/P1 blockers; branch protection and lint baseline updated.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expand route inventory/normalizer checks, Playwright route crawler, Semgrep
route rules, and revealed-bug drafts; fix stale Baseball mobile nav example
links and remove tracked secret-pattern scan artifact.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add nosemgrep annotations for device-token registry actions that do not
serve cached pages and therefore intentionally skip revalidatePath.

Co-authored-by: Cursor <cursoragent@cursor.com>
Revert accidental routes:report dependency from package.json and move
device-token mutations into lib so review-gate semgrep stays clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
Document nosemgrep for the snapshot-restore RPC fallback path in
submitRoundDirectFallback so Review Gate passes without weakening
the destructive-write rule elsewhere.

Co-authored-by: Cursor <cursoragent@cursor.com>
Wait for network idle and main landmark before body checks so client-side
redirects and auth gates do not false-positive in the route crawler.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expose auth and revalidate to static rules after requireCoachAuth, suppress
public demo-request and box-score replace patterns with targeted nosemgrep.

Co-authored-by: Cursor <cursoragent@cursor.com>
njrini99-code and others added 4 commits June 29, 2026 22:09
Add BUG_DISCOVERY_STACK map, verify:bugs:* npm scripts, Playwright visual
and Schemathesis advisory lanes, ZAP/Meticulous workflows, and setup docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
Detect token via step output instead of secrets in job-level if conditions.

Co-authored-by: Cursor <cursoragent@cursor.com>
Skip until token is set; document upload-container step for post-setup wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
Wire e2e:visual scripts, generate public-route snapshot baselines,
expand BUG_DISCOVERY_STACK.md with Greptile TREX/Qodo and Sentry replay
docs, and document OpenAPI stub path for Schemathesis.

Co-authored-by: Cursor <cursoragent@cursor.com>
Pass target URL through env vars instead of interpolating github context in run steps.

Co-authored-by: Cursor <cursoragent@cursor.com>
Golf and baseball landing routes require Supabase client init; without
NEXT_PUBLIC_SUPABASE_* the dev server renders error pages and Playwright
screenshots fail against existing marketing/login baselines.

Co-authored-by: Cursor <cursoragent@cursor.com>
Route crawler starts the dev server and hits landing routes that require
Supabase client init; without NEXT_PUBLIC_SUPABASE_* the crawl fails the
same way visual regression did before ed2e716.

Co-authored-by: Cursor <cursoragent@cursor.com>
@njrini99-code

Copy link
Copy Markdown
Owner Author

Closing as superseded: this June-30 omnibus touches dozens of app files (baseball auth/onboarding/actions, golf pages) that PR #650 rebuilt on 2026-07-02 — merging it now would regress the shipped surfaces. The good infra pieces (route-hygiene scripts, advisory workflows, contract docs) should be re-cut cleanly on current main. Branch preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant