Skip to content

feat: WANT tier — GitHub hygiene, Dependabot, security CI, /api/health#7

Open
bryansayler wants to merge 8 commits into
mainfrom
claude/want-infra
Open

feat: WANT tier — GitHub hygiene, Dependabot, security CI, /api/health#7
bryansayler wants to merge 8 commits into
mainfrom
claude/want-infra

Conversation

@bryansayler
Copy link
Copy Markdown
Contributor

Summary

First half of the WANT tier from the original plan. Focuses on repo hygiene, supply-chain security, and a working example API route. UI items (dark mode, more shadcn primitives) deferred to a separate PR since they need visual verification.

What landed

GitHub repo hygiene

  • CODEOWNERS — default + explicit ownership for auth/env/db/CI/security
  • PULL_REQUEST_TEMPLATE.md — enforces summary/changes/test-plan structure
  • ISSUE_TEMPLATE/bug.yml + feature.yml — structured GitHub form schema
  • ISSUE_TEMPLATE/config.yml — disables blank issues, routes security to Advisories flow

Dependency management

  • .github/dependabot.yml — weekly Monday updates; groups related deps (react, next, drizzle, testing, tailwind, linting) so PRs arrive in coherent batches; conventional commit prefixes match commitlint

Editor / IDE

  • .editorconfig — charset, line endings, indentation, final newlines
  • .vscode/extensions.json — recommends ESLint, Prettier, Tailwind, Bun, Vitest, Playwright, Pretty TS Errors, etc.
  • .vscode/settings.json — format-on-save, ESLint fix-on-save, workspace TS SDK, Tailwind IntelliSense for cva()/cn()
  • Updated .gitignore to track shared .vscode files while ignoring user-specific ones

Security CI

  • New security job in ci.yml running bun audit --prod + gitleaks-action
  • Bumped drizzle-orm 0.38.3 → 0.45.2 — patches high-severity SQL injection (GHSA-gpj5-g38j-94v9)
  • Added postcss override ^8.5.10 — forces patched version across all transitive consumers (next/tailwind/vite), resolving GHSA-qx2v-qp2m-jg93
  • bun audit --prod now reports 0 vulnerabilities

Health endpoint

  • GET /api/health — returns JSON with ok, status, version, uptimeMs, ISO timestamp, and per-check map (currently DB ping via SELECT 1); 200 on healthy, 503 on degraded; dynamic = "force-dynamic" so it isn't cached at build time
  • Unit test (src/__tests__/health.test.ts) calls GET directly
  • E2E test (e2e/health.spec.ts) hits the running server

Misc fix

Test plan

  • bun run validate passes locally (lint + type-check + unit tests + build)
  • bun audit --prod → 0 vulnerabilities
  • /api/health registered in build output, returns 200 in unit test
  • All commits pass Lefthook hooks + commitlint
  • CI: validate + e2e + security + CodeQL all green
  • Manual: bun run dev, curl localhost:3000/api/health{ "ok": true }

Notes for reviewer

  • Doesn't conflict with PR fix: close scaffold gaps — auth, drizzle, env, coverage, zustand #6 — both touch package.json and eslint.config.mjs but on different lines/concerns. Should auto-merge.
  • The drizzle bump from 0.38 → 0.45 is a meaningful jump but the API surface used by the scaffold (just the SQLite schema + db client) is unchanged. Builds clean.
  • Security job uses bun audit rather than npm audit since Bun is the runtime. Same advisory DB.

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH


Generated by Claude Code

claude added 7 commits May 19, 2026 13:17
Adds the standard GitHub repository hygiene files:

- CODEOWNERS routes review requests; flags auth/env/db/CI as sensitive
- PULL_REQUEST_TEMPLATE.md enforces summary/changes/test-plan structure
- ISSUE_TEMPLATE/bug.yml and feature.yml use the structured form schema
- ISSUE_TEMPLATE/config.yml disables blank issues and routes security
  reports to the GitHub Security Advisories flow

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
Weekly updates on Monday. Groups related deps (react, next, drizzle,
testing, tailwind, linting) so PRs land in coherent batches rather
than 20 single-package noise PRs.

Conventional commit prefixes match commitlint config: chore(deps),
chore(deps-dev), chore(ci).

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
EditorConfig pins charset, line endings, indentation, and final
newline behavior across editors. Markdown opts out of trailing
whitespace trim (line breaks via two spaces).

.vscode/extensions.json recommends the standard set for this stack:
ESLint, Prettier, Tailwind, Bun, Vitest, Playwright, Pretty TS Errors,
Docker, GitHub Actions.

.vscode/settings.json wires format-on-save, ESLint fix-on-save,
workspace TypeScript SDK, and Tailwind IntelliSense for cva()/cn().

Updates .gitignore to allow these shared files while keeping
user-specific .vscode/ files (launch.json, tasks.json) ignored.

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
Adds a 'security' job to CI that runs:
- `bun audit --prod` to catch known CVEs in production deps
- gitleaks-action to scan for committed secrets

Bumps drizzle-orm from 0.38.3 to 0.45.2 (patches a high-severity SQL
injection vuln via improperly escaped identifiers — GHSA-gpj5-g38j-94v9).

Adds a postcss override (^8.5.10) to force the patched version across
all transitive consumers (next, tailwindcss, vite), resolving the
moderate XSS advisory GHSA-qx2v-qp2m-jg93.

After this commit: `bun audit --prod` reports 0 vulnerabilities.

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
Returns JSON with overall ok flag, status (healthy/degraded), version
(from npm_package_version), uptime in ms, ISO timestamp, and a
per-check map. Currently checks: database connectivity via SELECT 1.

Returns 503 if any check fails; 200 otherwise. Marked
`dynamic = "force-dynamic"` so Next.js doesn't try to cache it at
build time.

Adds:
- src/app/api/health/route.ts — the handler
- src/__tests__/health.test.ts — unit test calling GET directly
- e2e/health.spec.ts — Playwright HTTP test against the running server

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
next-env.d.ts is generated by `next build` and trips the
@typescript-eslint/triple-slash-reference rule. Add it to the
eslint ignores so local and CI lint stays green.

(Same fix as PR #6, included here in case PR #6 hasn't merged yet.)

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
Two fixes to the security CI job:

1. `bun.lock` was gitignored, so CI's `bun install --frozen-lockfile`
   produced no lockfile, which meant `bun audit` errored with
   "Lockfile not found". Lockfiles belong in version control for
   reproducible installs and audit support — un-ignoring and
   committing the lockfile resolves both.

2. gitleaks-action requires a paid GITLEAKS_LICENSE secret for
   org-owned private repos. Swapped to TruffleHog (trufflesecurity/
   trufflehog@main), which is free for all repo types and detects
   verified + unknown credential patterns.

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
Copy link
Copy Markdown

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

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: 727c6588ef

ℹ️ 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".

Comment thread .github/workflows/ci.yml
with:
bun-version: latest

- run: bun install --frozen-lockfile
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 Badge Commit bun.lock before using frozen installs

This new job runs bun install --frozen-lockfile, but I checked the repository and there is no tracked bun.lock while .gitignore still ignores it. Bun's official install docs state that bun ci/--frozen-lockfile installs exact versions from bun.lock and that you must commit bun.lock to version control, so this security job will fail before it ever reaches bun audit --prod on fresh GitHub runners.

Useful? React with 👍 / 👎.

Comment thread src/app/api/health/route.ts Outdated
@@ -0,0 +1,35 @@
import { NextResponse } from "next/server";
import { sql } from "drizzle-orm";
import { db } from "@/lib/db";
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 Initialize the DB inside the health check

When the SQLite connection itself cannot be opened, for example DATABASE_URL points at a missing or unwritable directory, new Database(...) throws while evaluating this top-level import before GET() enters its try block. In that degraded-database scenario the health route returns a framework 500 or fails to load instead of the intended JSON body with checks.database.ok=false and HTTP 503.

Useful? React with 👍 / 👎.

Addresses Codex P2: when `new Database(...)` throws at module load
(e.g. DATABASE_URL points at a missing/unwritable path), the previous
top-level `import { db }` caused the entire route to fail to load
with a framework 500 rather than the intended JSON 503 with
`checks.database.ok=false`.

Now `db` is dynamically imported inside the try/catch, so connection
errors surface as failed checks. Added a test covering the degraded
path: when the db module throws on import, the route returns 503 with
`ok=false`, `status=degraded`, and a non-empty error string.

https://claude.ai/code/session_012Mh4xLVoCPRt2pNacxpPtH
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.

2 participants