π Source Control, CI/CD & Development Practices
π Source Control, CI/CD & Development Practices
π Summary
The repository was supplied as a single squashed commit, so the actual history of how the software was built β branching, commit habits, code review, slowdowns β cannot be seen and must be requested. What the repository does reveal is a disciplined, well-automated local process: a single script runs six quality gates (tests, type-checking, linting, a confidentiality scrub, a route/test-harness contract check and a production build), and the same gates run in GitHub Actions on every push and pull request. The documented workflow, however, is trunk-based with changes merged straight to main by fast-forward, with no pull-request review step, and the process documents are written for AI coding "sessions" working under one owner's direction. There is no security or dependency scanning in the pipeline, no automated deployment or migration step visible in the repository, and no branch protection that the repository can evidence. For a buyer this means good automated hygiene but little evidence of independent human review.
π― Rating
π‘ βββββ 3 / 5 β Amber. Strong, mechanically enforced quality gates and CI, offset by no evidenced code review, no security scanning, hand-applied migrations, and a history that cannot be inspected.
π Findings
Repository structure and organisation
| Area | Contents | Assessment |
|---|---|---|
src/app | Next.js App Router pages, API routes (83 route files), QA harness (src/app/qa) | Conventional for Next.js [Observed] |
src/lib | Domain logic and helpers, co-located *.test.ts | Clean separation of pure logic [Observed] |
src/components, src/types | Shared UI, generated DB types | [Observed] |
supabase/ | 92 migrations, baseline.sql, RLS tests (supabase/tests/) | [Observed] |
e2e/ | Live-deployment specs, journey specs (harness), acceptance walk | [Observed] |
scripts/ | Gates, journeys runner, ops, scrub, harness contract, board tooling | [Observed] |
audits/ | Python UI audit scripts (contrast, a11y, tokens) | [Observed] |
design/, docs/, root *.md | Design compliance notes, handover, API reference, architecture | [Observed] |
Organisation is coherent and follows framework conventions. One oddity: a production route tree also contains the test harness (src/app/qa, gated at runtime by NEXT_PUBLIC_QA=1) β see Module 9.
Branching model
- Determined from history: [Unavailable] β one commit (
3789df6, 721 files, 125,806 insertions);git rev-parse --is-shallow-repositoryβfalse, so history was squashed deliberately rather than truncated by the clone. - Documented model: trunk-based with short-lived worktree branches, rebased on
mainand merged withgit merge --ff-onlythen pushed directly toorigin main; "Never force-push". [Observed]docs/HANDOVER.mdlines 26β60. SECURITY.md: "mainonly. There are no release branches or tags; every deployment builds frommain." [Observed]
Commit hygiene
[Unavailable] β commit size, message quality, frequency, dormant periods and recent slowdowns all require the unsquashed history. The documented convention (HANDOVER.md) requires a fixed committer identity, two trailers supplied by "the session reminder", "reasons not sources" in messages, and no model names. [Observed] This convention indicates commits are authored by AI coding sessions under the owner's identity. [Inferred]
Evidence of code review
- No PR template, CODEOWNERS, or review configuration in
.github/. [Observed]ls .githubβworkflows/only. - Documented landing path bypasses pull requests (fast-forward merge to
main). [Observed] HANDOVER.md. - Review appears to happen as owner inspection of a "build board" (screenshots published as a web page) and a "comment ledger", i.e. product/visual review rather than code review. [Observed] HANDOVER.md "Where things stand", "The board". [Inferred] that no second human reviews code.
- Branch protection settings live in GitHub, not the repository. [Unavailable β requires GitHub repository admin access.]
CI/CD
| Stage | Present? | Where | Notes |
|---|---|---|---|
| Install | β Yes | ci.yml | npm ci --legacy-peer-deps (flag flagged in-file as a workaround to remove) |
| Typecheck | β Yes | ci.yml | tsc --noEmit β passes locally (exit 0) |
| Unit tests | β Yes | ci.yml | Vitest β 687/687 pass locally |
| Confidentiality scrub | β Yes | ci.yml | scripts/scrub.js β passes (715 files) |
| Route β harness contract | β Yes | ci.yml | 125 handlers agree |
| Lint | β Yes | ci.yml | 0 errors / 0 warnings locally |
| Production build | β Yes | ci.yml | Placeholder Supabase env |
| Each gate reports independently | β Yes | if: ${{ !cancelled() }} | Good practice, deliberately chosen |
| Journey (browser) tests | β No β local only (~25β30 min) | scripts/journeys.sh | Comment in ci.yml explains why |
| Coverage threshold | β No | β | |
| Dependency / vulnerability scan | β No | β | 24 known vulns undetected by CI (Module 8) |
| SAST / secret scanning | β No | β | |
| Deploy | Not in repo | β | Presumably Vercel's Git integration [Inferred]; Vercel config not in repo |
| Database migrations | Manual | SQL Editor or scripts/ops.sh sql | CLAUDE.md records a migration found missing in production (035) and migrations "written and not yet run" (065, 088, 091) |
| Acceptance walk against live site | Manual dispatch | walk.yml | Writes to the target site; correctly never on push |
Workflow permissions are least-privilege (contents: read) and runs are de-duplicated with concurrency. [Observed] ci.yml.
Automated checks and bypassability
- Local:
npm run gates(scripts/gates.sh) runs six gates by exit code and stops on first red β explicitly designed after two incidents where a red gate was missed by piping throughgrep. [Observed] script header comment. - Custom static gates enforced through unit tests:
src/lib/write-results.test.ts(every awaited write must read its result),src/lib/schema-columns.test.ts(every column the code names must exist inbaseline.sql). These are unusually strong, project-specific guard rails. [Observed] - Bypass: because the documented flow pushes directly to
main, CI is after-the-fact; whethermainis protected so a red CI blocks deploy cannot be determined. [Unavailable β GitHub branch protection and Vercel "ignored build step" settings.] CLAUDE.md itself records "Three pushes tomainsat red β¦ on 2026-09-06". [Observed]
π§Ύ Evidence
git log --all --format=β¦β single commit;git show --stat HEADβ 721 files, 125,806 insertions.git rev-parse --is-shallow-repositoryβfalse.- Files:
.github/workflows/ci.yml,.github/workflows/walk.yml,scripts/gates.sh,docs/HANDOVER.md(lines 1β62),SECURITY.md,CLAUDE.md("Verification", "Migrations"). - Local runs:
npx tsc --noEmit(exit 0),npx eslint(exit 0),npx vitest run(687 passed),node scripts/scrub.js,node scripts/harness-contract.js.
β οΈ Risks
| Risk | Severity | Effort |
|---|---|---|
No evidenced human code review; changes land directly on main | π High | S (process) |
| No dependency/SAST/secret scanning in CI | π High | S |
| Squashed history removes the audit trail of who changed what and when | π High (diligence) | β |
| Manual, per-deployment migrations with a record of drift between code and database | π High | M |
| Browser journey suite not in CI; regressions in UI wiring are only caught if someone runs it locally | π‘ Medium | M |
| Process documentation is tailored to AI coding sessions (worktrees, ports, "session reminder") and to one owner's review style; a conventional team will need to re-establish its own workflow | π‘ Medium | SβM |
--legacy-peer-deps workaround in CI | βͺ Low | S |
β Recommendations
| Recommendation | Priority | Effort |
|---|---|---|
| Request the full, unsquashed git history (and GitHub PR/issue data) as a condition of diligence | P0 | β |
Introduce PR-based flow with required review and required status checks on main | P1 | S |
Add dependency scanning (Dependabot/Renovate + npm audit), CodeQL or Semgrep, and secret scanning | P1 | S |
Automate migrations (Supabase CLI) with a check that each deployment's schema matches baseline.sql | P1 | M |
| Run the journey suite in CI (nightly or on PR, sharded) | P2 | M |
| Rewrite HANDOVER.md for a human team; keep AI-session specifics separate | P3 | S |