Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

BUILD_BIBLE.md

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

BUILD_BIBLE.mdBlame444 lines · 1 contributor
9ab6971Claude1# GLUECRON BUILD BIBLE
2
3**This file is the single source of truth for the GlueCron build.**
4
5**Every Claude agent MUST read this file in full before touching code. No exceptions.**
6
7GlueCron is a GitHub replacement — AI-native code intelligence, green ecosystem enforcement, git hosting, automated CI. It is production infrastructure for multiple downstream platforms. Production cannot stop.
8
9---
10
11## 1. AGENT POLICY (READ FIRST, FOLLOW ALWAYS)
12
13### 1.1 Required reads at session start
141. `BUILD_BIBLE.md` (this file) — complete
152. `CLAUDE.md` — stack + architecture
163. `README.md` — user-facing overview
174. Most recent commit on the current branch (`git log -1 --stat`)
18
19### 1.2 Do-not-undo rule
20- Anything listed in **§4 LOCKED BLOCKS** is shipped and must not be deleted, renamed, or semantically altered without the owner's explicit written permission in the current session.
21- "Refactor" is not permission. "Clean up" is not permission. "Simplify" is not permission.
22- If a locked file seems wrong, open an issue in the plan and keep going on a new block.
23
24### 1.3 Continuous-build rule
25- The owner runs many parallel projects. Do not stop work to ask for clarification that can be inferred from this file.
26- Default behaviour when a block is partially complete: **finish it, run tests, commit, push, start the next block**.
27- Only stop for genuinely blocking decisions: destructive operations, architectural reversals, requests outside this plan, or repeated test failures you can't diagnose.
28- Never stop because "the session might run out." Commit what works and keep building.
29
30### 1.4 Branch + commit rules
31- Development branch: whatever the current session was told (check session opening message). Fall back to `main` if none given.
32- One commit per completed block. Message format: `feat(BLOCK-ID): <summary>`.
33- Push after every commit with `git push -u origin <branch>`.
34- Never force-push. Never `--no-verify`. Never amend published commits.
35
36### 1.5 Quality bars (non-negotiable)
37- `bun test` must pass before every commit.
38- New features ship with tests in `src/__tests__/`.
39- New routes use `softAuth` or `requireAuth` middleware.
40- New DB tables have a corresponding migration in `drizzle/`.
41- AI features use `isAiAvailable()` guards and degrade gracefully without `ANTHROPIC_API_KEY`.
42- Every user-facing failure mode has a fallback — no 500s reach the UI.
43
44### 1.6 Green-ecosystem-by-default
45- Every new repo auto-configures: gates on, branch protection on, labels seeded, CODEOWNERS synced, welcome issue posted.
46- Users can opt out per feature but defaults are maximum-green.
47- Nothing broken ever reaches production, the website, or the customer.
48
15e65d2Claude49### 1.7 Parallelism rule (added per owner request)
50- **Default to spawning sub-agents whenever work can be parallelised.** Owner-cost of an idle main thread is high; owner-cost of an extra agent is near-zero.
51- Independent files = parallel agents. Schema-only edits, new route files, doc updates, test additions, codebase research — all of these run in parallel by default unless they collide.
52- Coordinate file ownership: one agent per file. Never let two agents edit the same file. Mounting + middleware integration stay on the main thread to avoid merge conflicts.
53- When launching multiple agents, send them in a single message with multiple Agent tool calls so they actually run concurrently.
54- The main thread is responsible for: reviewing each agent's output before integrating, running the test suite, and committing. Trust-but-verify — read the changes, don't just rely on the agent's summary.
55
9ab6971Claude56---
57
58## 2. GITHUB PARITY SCORECARD
59
60Legend: ✅ shipped · 🟡 partial · ❌ not built
61
62### 2.1 Repository hosting
63| Feature | Status | Notes |
64|---|---|---|
65| Git Smart HTTP (clone / push / fetch) | ✅ | `src/routes/git.ts`, `src/git/protocol.ts` |
66| SSH keys | ✅ | `ssh_keys` table, `src/routes/settings.tsx` |
67| Public / private visibility | ✅ | `repositories.isPrivate` |
68| Forking | ✅ | `src/routes/fork.ts` |
69| Stars | ✅ | `stars` table, `/:owner/:repo/star` |
70| Topics | ✅ | `repo_topics` table |
71| Archive / disable repo | ❌ | schema has flags; no UI |
72| Repository transfer | ❌ | — |
73| Template repositories | ❌ | — |
74| Repository mirroring | ❌ | — |
75
76### 2.2 Code browsing
77| Feature | Status | Notes |
78|---|---|---|
79| File tree browser | ✅ | `src/routes/web.tsx` |
80| Syntax highlighting | ✅ | 40+ languages, `src/lib/highlight.ts` |
81| Commit history | ✅ | |
82| Diffs | ✅ | |
83| Blame | ✅ | |
84| Raw file download | ✅ | |
85| Branch switcher | ✅ | |
86| Tag listing | ✅ | new this build |
87| Code search (ILIKE) | ✅ | per-repo + global |
88| Semantic / embedding search | ❌ | pgvector not wired |
89| Symbol / xref navigation | ❌ | — |
90
91### 2.3 Collaboration
92| Feature | Status | Notes |
93|---|---|---|
94| Issues (CRUD / comments / labels / close) | ✅ | |
95| Milestones | ✅ | `src/routes/insights.tsx` |
96| Pull requests (CRUD / review / merge) | ✅ | |
97| PR inline comments | ✅ | file+line anchored |
6fc53bdClaude98| Draft PRs | ✅ | create as draft, ready-for-review toggle, dedicated tab, merge blocked until ready |
99| Reactions (emoji) | ✅ | 8 reactions, toggle via `POST /api/reactions/:t/:id/:emoji/toggle` on issues + PRs + comments |
9ab6971Claude100| Mentions + notifications | ✅ | `src/routes/notifications.tsx` |
101| Code owners | ✅ | `src/lib/codeowners.ts` |
24cf2caClaude102| Issue templates | ✅ | `.github/ISSUE_TEMPLATE.md` auto-prefills new issues; frontmatter stripped; `src/lib/templates.ts` |
103| PR templates | ✅ | `.github/PULL_REQUEST_TEMPLATE.md` auto-prefills new PRs; `src/lib/templates.ts` |
104| Saved replies | ✅ | per-user canned comments, unique-shortcut, `/settings/replies`, `/api/user/replies` |
9ab6971Claude105| Discussions / forums | ❌ | |
106| Wikis | ❌ | |
107| Projects / kanban | ❌ | |
108
109### 2.4 Automation + AI
110| Feature | Status | Notes |
111|---|---|---|
ad6d4adClaude112| Webhooks (outbound, HMAC signed) | ✅ | `src/routes/webhooks.tsx` |
113| GateTest inbound callback | ✅ | `POST /api/hooks/gatetest`, bearer or HMAC |
114| Backup PAT-auth gate ingest | ✅ | `POST /api/v1/gate-runs` |
9ab6971Claude115| Gate runs (test / secret / AI review) | ✅ | `gate_runs` table, `src/routes/gates.tsx` |
116| Branch protection | ✅ | `branch_protection` table + UI |
117| Auto-repair engine | ✅ | `src/lib/auto-repair.ts` |
118| Secret scanner | ✅ | 15 patterns, `src/lib/security-scan.ts` |
119| AI security review | ✅ | Sonnet 4, `src/lib/security-scan.ts` |
120| AI commit messages | ✅ | `src/lib/ai-generators.ts` |
121| AI PR summaries | ✅ | |
122| AI changelogs | ✅ | auto on release create |
123| AI code review | ✅ | `src/lib/ai-review.ts` |
124| AI merge conflict resolver | ✅ | `src/lib/merge-resolver.ts` |
125| AI chat (global + repo) | ✅ | `src/routes/ask.tsx` |
5e888b7Claude126| GitHub Actions equivalent (workflow runner) | ✅ | `src/lib/workflow-parser.ts`, `src/lib/workflow-runner.ts`, `src/routes/workflows.tsx`; `.gluecron/workflows/*.yml` auto-discovered on push; Bun subprocess executor, per-step timeouts, size-capped logs |
9ab6971Claude127| Dependabot equivalent (AI dep bumper) | ❌ | |
128| Code scanning UI | 🟡 | data exists, no dedicated UI page |
129| Copilot code completion | ❌ | |
130
131### 2.5 Platform
132| Feature | Status | Notes |
133|---|---|---|
134| Dashboard | ✅ | `src/routes/dashboard.tsx` |
135| Explore / discover | ✅ | |
136| Global search | ✅ | repos / users / issues / PRs |
137| Insights (graph, contributors, green rate) | ✅ | `src/routes/insights.tsx` |
138| Releases + tags | ✅ | AI changelog |
139| Personal access tokens | ✅ | SHA-256 hashed |
058d752Claude140| OAuth app provider | ✅ | `src/routes/oauth.tsx`, `src/routes/developer-apps.tsx`, `src/lib/oauth.ts`; `oauth_apps` + `oauth_authorizations` + `oauth_access_tokens` tables |
9ab6971Claude141| GitHub Apps equivalent | ❌ | |
142| GraphQL API | ❌ | REST only |
058d752Claude143| Organizations + teams | ✅ | B1+B2+B3 shipped: `src/routes/orgs.tsx`, `src/lib/orgs.ts`; org-owned repos (`repositories.orgId`); team-based CODEOWNERS (`@org/team` resolution) |
9ab6971Claude144| Enterprise SAML / SSO | ❌ | |
058d752Claude145| 2FA / TOTP | ✅ | `src/routes/settings-2fa.tsx`, `src/lib/totp.ts`; `user_totp` + `user_recovery_codes` tables |
146| Passkeys / WebAuthn | ✅ | `src/routes/passkeys.tsx`, `src/lib/webauthn.ts`; `user_passkeys` + `webauthn_challenges` tables |
25a91a6Claude147| Packages registry (npm / docker / etc) | ✅ | `src/lib/packages.ts`, `src/routes/packages-api.ts`, `src/routes/packages.tsx`; npm protocol (packument, tarball, publish, yank); PAT (`glc_`) auth via Authorization header; container registry deferred |
148| Pages / static hosting | ✅ | `src/lib/pages.ts`, `src/routes/pages.tsx`; serves blobs from bare git at latest `gh-pages` commit; per-repo settings (source branch/dir, custom domain); short-cache headers |
9ab6971Claude149| Gists | ❌ | |
150| Sponsors | ❌ | |
151| Marketplace | ❌ | |
25a91a6Claude152| Environments / deployment tracking | ✅ | `src/routes/deployments.tsx` — grouped by env, success-rate rollup, per-deploy detail. Protected environments (`src/routes/environments.tsx`, `src/lib/environments.ts`) with reviewer-gated approval, branch-glob restrictions, approve/reject decisions recorded in `deployment_approvals` |
9ab6971Claude153| Merge queues | ❌ | |
154| Required checks matrix | 🟡 | branch_protection has single flag, no matrix |
155
156### 2.6 Observability + safety
157| Feature | Status | Notes |
158|---|---|---|
159| Rate limiting | ✅ | `src/middleware/rate-limit.ts` |
160| Request-ID tracing | ✅ | `src/middleware/request-context.ts` |
161| Health / readiness / metrics | ✅ | `/healthz` `/readyz` `/metrics` |
162| Audit log (table) | ✅ | `audit_log` table |
6fc53bdClaude163| Audit log UI | ✅ | `/settings/audit` (personal) + `/:owner/:repo/settings/audit` (per-repo, owner-only) |
9ab6971Claude164| Traffic analytics per repo | ❌ | |
24cf2caClaude165| Email notifications | ✅ | opt-in per kind (mention/assign/gate-fail) via `/settings`; provider-pluggable `src/lib/email.ts` (log default, resend in prod) |
9ab6971Claude166| Email digest | ❌ | |
167| Mobile PWA | 🟡 | responsive CSS, no manifest |
168| Native mobile apps | ❌ | |
6fc53bdClaude169| Dark mode | ✅ | default |
170| Light-mode toggle | ✅ | `/theme/toggle` + `theme` cookie, pre-paint script avoids FOUC, nav sun/moon icon |
9ab6971Claude171| Keyboard shortcuts | ✅ | `/shortcuts` page |
172| Command palette | 🟡 | Cmd+K → Ask AI, no generic palette |
173
174---
175
176## 3. BUILD PLAN (BLOCKS)
177
178Each block is a self-contained unit. Order matters for dependencies. Each block ends with tests + commit + push.
179
180### BLOCK A — Hardening the current surface
181Polish what's shipped before adding more. **Priority: do this first if parity gaps are minor.**
6fc53bdClaude182- **A1** — Dark/light theme toggle (cookie, CSS variable swap) ✅
183- **A2** — Audit log UI page (`/settings/audit` + `/:owner/:repo/settings/audit`) ✅
184- **A3** — Reactions UI on issues / PRs / comments (data exists) ✅
185- **A4** — Draft PR toggle + filter ✅
24cf2caClaude186- **A5** — Issue + PR templates (`.github/*_TEMPLATE.md` auto-prefill) ✅
187- **A6** — Saved replies per user ✅
188- **A7** — Environments + deployment history UI (`deployments` table) ✅
189- **A8** — Email notifications (opt-in, provider-pluggable) ✅
190
191**BLOCK A COMPLETE.** Next: BLOCK B (Identity + orgs).
9ab6971Claude192
193### BLOCK B — Identity + orgs
058d752Claude194- **B1** — Organizations (schema: `organizations`, `org_members`, `teams`, `team_members`) → ✅ shipped (`6563f0a`)
6563f0aClaude195 - Helpers in `src/lib/orgs.ts`: slug validation, role rank, reserved-slug set, loaders
196 - Routes in `src/routes/orgs.tsx`: list / create / profile / people / teams / team detail
197 - Role-based guards: admin adds members, owner grants owner, last-owner demote/remove blocked
198 - All sensitive actions `audit()`'d (org.create, member.add/role/remove, team.create, team.member.add/remove)
058d752Claude199- **B2** — Repos owned by orgs (nullable `repositories.orgId`) → ✅ shipped (`7437605`)
200- **B3** — Team-based CODEOWNERS (`@org/team` resolution) → ✅ shipped (`40d3e3f`)
201- **B4** — 2FA / TOTP (enroll, recovery codes) → ✅ shipped (`7298a17`)
202- **B5** — WebAuthn / passkeys → ✅ shipped (`2df1f8c`)
203- **B6** — OAuth 2.0 provider (third-party apps can request access) → ✅ shipped (pending final commit)
9ab6971Claude204
205### BLOCK C — Runtime + hosting
5e888b7Claude206- **C1** — Actions-equivalent workflow runner → ✅ shipped (`eafe8c6`)
207 - Workflow YAML parser (`src/lib/workflow-parser.ts`) — hand-rolled subset
208 - Background worker (`src/lib/workflow-runner.ts`) — Bun.spawn, size-capped logs, SIGTERM→SIGKILL timeouts
209 - Auto-discovery from `.gluecron/workflows/*.yml` on default-branch push
210 - UI at `/:owner/:repo/actions` with manual trigger + cancel
25a91a6Claude211- **C2** — Package registry (npm protocol) → ✅ shipped
212 - Packument + tarball + publish + yank via `PUT /npm/<name>` + `GET /npm/<name>`
213 - PAT (`glc_`) bearer auth for CLI clients; add `//host/npm/:_authToken=<PAT>` to .npmrc
214 - Container registry deferred (schema ready for it)
215- **C3** — Pages / static hosting → ✅ shipped
216 - Serves `/:owner/:repo/pages/*` from the latest successful `pages_deployments` row
217 - Auto-records on push to the repo's configured source branch (default `gh-pages`)
218 - Settings UI at `/:owner/:repo/settings/pages` + manual redeploy
219- **C4** — Environments with protected approvals → ✅ shipped
220 - Per-repo `environments` with reviewer list + branch-glob allowlist
221 - Auto-deploy on main is gated by `requiresApprovalFor()`; pending rows show status `pending_approval`
222 - Approve/reject at `POST /:owner/:repo/deployments/:id/approve|reject`
9ab6971Claude223
224### BLOCK D — AI-native differentiation
225This is where GlueCron beats GitHub outright. **Priority: ship these loud.**
226- **D1** — Semantic code search (pgvector + Claude embeddings)
227- **D2** — AI dependency updater (reads lockfile, opens PRs, verifies green)
228- **D3** — AI PR triage agent (auto-assigns reviewers, labels, milestones)
229- **D4** — AI incident responder (on deploy failure, opens issue with root cause)
230- **D5** — AI code reviewer that blocks merges (enforced via branch protection "AI approval required")
231- **D6** — AI "explain this codebase" on repo landing (auto-generated, cached)
232- **D7** — AI changelog for every commit range (`/:owner/:repo/ai/changelog?from=...&to=...`)
233- **D8** — AI-generated test suite (reads public API, generates failing tests)
234- **D9** — Copilot-style completion endpoint for IDE plugins
235
236### BLOCK E — Collaboration parity
237- **E1** — Projects / kanban boards (`projects`, `project_items`, `project_fields`)
238- **E2** — Discussions (forum threads per repo)
239- **E3** — Wikis (git-backed, separate bare repo per repo)
240- **E4** — Gists (user-owned tiny repos)
241- **E5** — Merge queues (serialised merge with re-test)
242- **E6** — Required status checks matrix (multiple named checks per branch protection rule)
243- **E7** — Protected tags
244
245### BLOCK F — Observability + admin
246- **F1** — Traffic analytics per repo (views, clones, unique visitors)
247- **F2** — Org-wide insights (green rate across all repos)
248- **F3** — Admin / superuser panel (user moderation, repo audit)
249- **F4** — Billing + quotas (storage, AI tokens, bandwidth)
250
251### BLOCK G — Mobile + client
252- **G1** — PWA manifest + service worker
253- **G2** — GraphQL API mirror of REST
254- **G3** — Official CLI (`gluecron` binary in Bun)
255- **G4** — VS Code extension
256
257### BLOCK H — Marketplace
258- **H1** — App marketplace (install third-party apps against a repo)
259- **H2** — GitHub Apps equivalent (bot identities with scoped permissions)
260
261---
262
263## 4. LOCKED BLOCKS (DO NOT UNDO)
264
265Everything below is committed, tested, and load-bearing. **Do not delete, rename, or semantically change without owner permission.**
266
267### 4.1 Infrastructure (locked)
268- `src/app.tsx` — route composition, middleware order, error handlers
269- `src/index.ts` — Bun server entry
270- `src/lib/config.ts` — env getters (late-binding)
271- `src/db/schema.ts` — 27 tables. New tables only via new migration.
272- `src/db/index.ts` — lazy proxy DB connection
273- `src/db/migrate.ts` — migration runner
274- `drizzle/0000_initial.sql`, `drizzle/0001_green_ecosystem.sql` — migrations
058d752Claude275- `drizzle/0004_org_owned_repos.sql` (Block B2) — migration, never edited in place
276- `drizzle/0005_totp_2fa.sql` (Block B4) — migration, never edited in place
277- `drizzle/0006_webauthn_passkeys.sql` (Block B5) — migration, never edited in place
278- `drizzle/0007_oauth_provider.sql` (Block B6) — migration, never edited in place
5e888b7Claude279- `drizzle/0008_workflows.sql` (Block C1) — migration, never edited in place
25a91a6Claude280- `drizzle/0009_packages.sql` (Block C2) — migration, never edited in place
281- `drizzle/0010_pages.sql` (Block C3) — migration, never edited in place
282- `drizzle/0011_environments.sql` (Block C4) — migration, never edited in place
9ab6971Claude283
284### 4.2 Git layer (locked)
285- `src/git/repository.ts` — tree / blob / commits / diff / branches / blame / search / raw / tags / commitsBetween
286- `src/git/protocol.ts` — Smart HTTP pkt-line
287- `src/hooks/post-receive.ts` — CODEOWNERS sync, gates, auto-deploy, webhook fan-out
288
289### 4.3 Auth + security (locked)
290- `src/lib/auth.ts` — bcrypt, session tokens
25a91a6Claude291- `src/middleware/auth.ts` — softAuth + requireAuth. Accepts three auth inputs: session cookie (web), OAuth access token (`glct_` prefix, Block B6), and personal access token (`glc_` prefix, Block C2). Invalid bearer → 401 JSON. Cookie flow → /login redirect.
9ab6971Claude292- `src/middleware/rate-limit.ts` — fixed-window limiter
293- `src/middleware/request-context.ts` — request-ID
294- `src/lib/security-scan.ts` — `SECRET_PATTERNS` (exported) + `scanForSecrets` + `aiSecurityScan`
058d752Claude295- `src/lib/codeowners.ts` — parser + `ownersForPath` (last-match-wins); team expansion helpers for `@org/team` (Block B3)
296- `src/lib/totp.ts` (Block B4) — TOTP enroll / verify / recovery codes
297- `src/lib/webauthn.ts` (Block B5) — WebAuthn registration + assertion helpers
298- `src/lib/oauth.ts` (Block B6) — OAuth 2.0 provider: authorization code grant, token issuance, scope enforcement
5e888b7Claude299- `src/lib/workflow-parser.ts` (Block C1) — YAML subset parser for `.gluecron/workflows/*.yml`. Exports `parseWorkflow(src)` returning `{ ok, workflow | error }`. Never throws.
300- `src/lib/workflow-runner.ts` (Block C1) — shell executor. Exports `executeRun`, `drainOneRun`, `enqueueRun`, `startWorker`. Clones repo to tmpdir, runs each job via `Bun.spawn(["bash","-c",step.run])` with SIGTERM→SIGKILL timeouts, size-capped stdout/stderr, cleans up in `finally`.
25a91a6Claude301- `src/lib/packages.ts` (Block C2) — npm protocol helpers: `parsePackageName`, `computeShasum` (sha1), `computeIntegrity` (sha512 base64), `buildPackument`, `resolveRepoFromPackageJson`, `parseRepoUrl`, `tarballFilename`. Pure functions.
302- `src/lib/pages.ts` (Block C3) — `onPagesPush` (never throws), `resolvePagesPath` (probe list including pretty URLs + traversal strip), `contentTypeFor` (MIME).
303- `src/lib/environments.ts` (Block C4) — `matchGlob`, `listEnvironments`, `getOrCreateEnvironment`, `getEnvironmentByName`, `isReviewer`, `reviewerIdsOf`, `allowedBranchesOf`, `computeApprovalState`, `reduceApprovalState`, `recordApproval`, `requiresApprovalFor`. Empty reviewers list → repo owner approves. Any rejection hard-stops.
9ab6971Claude304
305### 4.4 AI layer (locked)
306- `src/lib/ai-client.ts` — Anthropic client + model constants
307- `src/lib/ai-generators.ts` — commit / PR / changelog / issue-triage
308- `src/lib/ai-chat.ts` — conversational chat
309- `src/lib/ai-review.ts` — PR code review
310- `src/lib/auto-repair.ts` — worktree-backed repair commits
311- `src/lib/merge-resolver.ts` — AI merge conflict resolution
312
313### 4.5 Platform (locked)
24cf2caClaude314- `src/lib/notify.ts` — notification creation + audit log (swallow-failures pattern). Also fans out email to opted-in recipients for `mention|review_requested|assigned|gate_failed`. Exports `__internal` for tests.
315- `src/lib/email.ts` — provider-pluggable email sender (`log`|`resend`). `sendEmail()` never throws. `absoluteUrl()` joins paths against `APP_BASE_URL`.
316- `src/lib/templates.ts` — `loadIssueTemplate` / `loadPrTemplate`. Checks standard paths (`.github/`, `.gluecron/`, root, `docs/`) on the default branch, strips YAML frontmatter, 16KB cap, returns null on any failure.
9ab6971Claude317- `src/lib/unread.ts` — unread count helper (never throws)
318- `src/lib/repo-bootstrap.ts` — green defaults on repo creation
319- `src/lib/gate.ts` — gate orchestration + persistence
320- `src/lib/cache.ts` — LRU cache, git-cache invalidation
6fc53bdClaude321- `src/lib/reactions.ts` — `summariseReactions`, `toggleReaction`, `ALLOWED_EMOJIS`, `EMOJI_GLYPH`, `isAllowedEmoji`, `isAllowedTarget`
9ab6971Claude322
323### 4.6 Routes (locked endpoints — behaviour must be preserved)
324- `src/routes/git.ts` — Smart HTTP (clone/push)
325- `src/routes/api.ts` — REST (`POST /api/repos`, `GET /api/users/:u/repos`, `GET /api/repos/:o/:n`, `POST /api/setup`)
ad6d4adClaude326- `src/routes/hooks.ts` — `POST /api/hooks/gatetest` (bearer/HMAC), `GET /api/hooks/ping`, `POST /api/v1/gate-runs` (PAT backup), `GET /api/v1/gate-runs`. See `GATETEST_HOOK.md`.
6fc53bdClaude327- `src/routes/theme.ts` — `GET /theme/toggle`, `GET /theme/set?mode=`. Writes `theme` cookie (`dark`|`light`, 1-year). Layout reads via pre-paint inline script.
328- `src/routes/audit.tsx` — `GET /settings/audit` (personal) + `GET /:owner/:repo/settings/audit` (owner-only).
24cf2caClaude329- `src/routes/saved-replies.tsx` — `GET/POST /settings/replies`, `POST /settings/replies/:id`, `POST /settings/replies/:id/delete`, `GET /api/user/replies`. Unique constraint `saved_replies_user_shortcut`.
330- `src/routes/deployments.tsx` — `GET /:owner/:repo/deployments` (grouped by env, success-rate rollup), `GET /:owner/:repo/deployments/:id` (detail).
6fc53bdClaude331- `src/routes/reactions.ts` — `POST /api/reactions/:targetType/:targetId/:emoji/toggle` (authed, form- or fetch-compatible), `GET /api/reactions/:targetType/:targetId`. Targets: `issue|pr|issue_comment|pr_comment`. Emojis: 8 canonical.
9ab6971Claude332- `src/routes/auth.tsx` — register / login / logout
333- `src/routes/web.tsx` — home / new / browse / blob / commits / raw / blame / star / search / profile
334- `src/routes/issues.tsx` — issue CRUD + comments + labels + lock
335- `src/routes/pulls.tsx` — PR CRUD + review + merge + close
336- `src/routes/editor.tsx` — web file editor
337- `src/routes/compare.tsx` — base...head diff
24cf2caClaude338- `src/routes/settings.tsx` — profile + password + email notification preferences (`POST /settings/notifications`)
9ab6971Claude339- `src/routes/repo-settings.tsx` — repo settings + delete
340- `src/routes/webhooks.tsx` — webhook CRUD + test + `fireWebhooks`
341- `src/routes/fork.ts` — fork
342- `src/routes/explore.tsx` — discover
343- `src/routes/tokens.tsx` — personal access tokens
344- `src/routes/contributors.tsx` — contributor list
345- `src/routes/notifications.tsx` — inbox + unread API
346- `src/routes/dashboard.tsx` — authed home (`renderDashboard` exported)
347- `src/routes/ask.tsx` — global + repo AI chat + explain
348- `src/routes/releases.tsx` — tags + AI changelog
349- `src/routes/gates.tsx` — history + settings + branch protection UI
350- `src/routes/insights.tsx` — insights + milestones
351- `src/routes/search.tsx` — global search + `/shortcuts`
352- `src/routes/health.ts` — `/healthz` `/readyz` `/metrics`
6563f0aClaude353- `src/routes/orgs.tsx` — `/orgs` list, `/orgs/new` create, `/orgs/:slug` profile, `/orgs/:slug/people` + add/role/remove, `/orgs/:slug/teams` + create, `/orgs/:slug/teams/:teamSlug` + member add/remove. All require auth. Role guards via `orgRoleAtLeast`; last-owner cannot be demoted or removed; every write path `audit()`'d.
058d752Claude354- `src/lib/orgs.ts` (Block B1) — `isValidSlug` (rejects reserved + too-short/long + consecutive/leading/trailing hyphens), `normalizeSlug`, `orgRoleAtLeast` (owner>admin>member), `isValidOrgRole`, `isValidTeamRole`, `loadOrgForUser`, `listOrgsForUser`, `listOrgMembers`, `listTeamsForOrg`, `listTeamMembers`, `__test` export for unit tests.
355- `src/routes/settings-2fa.tsx` (Block B4) — TOTP enroll / verify / disable + recovery codes UI. All require auth.
356- `src/routes/passkeys.tsx` (Block B5) — WebAuthn passkey registration / assertion / management. All require auth.
357- `src/routes/oauth.tsx` (Block B6) — OAuth 2.0 authorize + token + userinfo endpoints.
358- `src/routes/developer-apps.tsx` (Block B6) — developer-facing OAuth app CRUD (`/settings/developer/apps`), client secret rotation, audit-logged.
5e888b7Claude359- `src/routes/workflows.tsx` (Block C1) — Actions UI. `GET /:owner/:repo/actions`, `GET /:owner/:repo/actions/runs/:runId`, `POST /:owner/:repo/actions/:workflowId/run` (auth+owner), `POST /:owner/:repo/actions/runs/:runId/cancel` (auth+owner). Manual runs are `event=manual`, ref=default branch.
25a91a6Claude360- `src/routes/packages-api.ts` (Block C2) — npm protocol: `GET/PUT/DELETE /npm/*` (packument, tarball, publish, yank); JSON helpers at `/api/packages/:owner/:repo/...`. PAT (`glc_`) bearer auth.
361- `src/routes/packages.tsx` (Block C2) — UI: `/:owner/:repo/packages` list + `/:owner/:repo/packages/:pkgName` detail.
362- `src/routes/pages.tsx` (Block C3) — `GET /:owner/:repo/pages/*` serves static files from latest gh-pages commit (binary via `getRawBlob`, text via `getBlob`). `GET/POST /:owner/:repo/settings/pages` settings + redeploy.
363- `src/routes/environments.tsx` (Block C4) — settings CRUD at `/:owner/:repo/settings/environments`; approval endpoints at `/:owner/:repo/deployments/:id/{approve,reject}`.
9ab6971Claude364
365### 4.7 Views (locked contracts)
366- `src/views/layout.tsx` — `Layout` accepts `title`, `user`, `notificationCount`
5e888b7Claude367- `src/views/components.tsx` — `RepoHeader`, `RepoNav` (active: `code|issues|pulls|commits|releases|actions|gates|insights|...`), `RepoCard`, etc.
6fc53bdClaude368- `src/views/reactions.tsx` — `ReactionsBar` (no-JS compatible, form-per-emoji)
369- Nav links: logo · search · theme-toggle · Explore · Ask · Notifications · New · Profile (or Sign in / Register)
9ab6971Claude370- Keyboard chords: `/`, `Cmd+K`, `?`, `n`, `g d`, `g n`, `g e`, `g a`
371
372### 4.8 Tests (locked)
373- `src/__tests__/green-ecosystem.test.ts` — secret scanner, codeowners, AI fallback, health, rate-limit headers, `/shortcuts`, `/search`
374- All other existing test files — do not delete without owner permission
375
376### 4.9 Invariants (never break these)
377- `isAiAvailable()` guard returns true fallback strings when no ANTHROPIC_API_KEY. AI features degrade gracefully.
378- `getUnreadCount` never throws; returns 0 on any error.
379- Rate-limit middleware adds `X-RateLimit-Limit` + `X-RateLimit-Remaining` to every response, including 500s.
380- `c.header("X-Request-Id", ...)` set by request-context on every response.
381- Secret scanner skips binary/lock paths (`shouldSkipPath`).
382- `SECRET_PATTERNS` is an exported array. Its shape is `{ type, regex, severity }`.
6fc53bdClaude383- Theme routes live outside `/settings/*` (they must work for logged-out visitors). Cookie name: `theme`, values: `dark|light`.
384- Draft PRs cannot be merged — `/pulls/:n/merge` returns a redirect with the draft error when `pr.isDraft=true`.
385- Reactions API accepts only `ALLOWED_EMOJIS` and `ALLOWED_TARGETS`. Toggle is idempotent per (user, target, emoji).
24cf2caClaude386- `sendEmail()` never throws — always resolves to `{ ok, provider, ... }`. Email failures never break notification delivery or the primary request path.
387- Email fan-out in `notify()` is scoped to kinds in `EMAIL_ELIGIBLE` (mention / review_requested / assigned / gate_failed). Each eligible kind maps to exactly one user preference column.
388- Issue + PR template loading must return `null` on any git-subprocess failure (templates are a convenience, not a requirement). Forms always render.
9ab6971Claude389
390---
391
392## 5. OPERATIONAL NOTES
393
394### 5.1 Running locally
395```bash
396bun install
397bun dev # hot reload
24cf2caClaude398bun test # 99 tests currently pass
9ab6971Claude399bun run db:migrate
400```
401
402### 5.2 Environment
403- `DATABASE_URL` — Neon Postgres
404- `ANTHROPIC_API_KEY` — unlocks AI features
405- `GIT_REPOS_PATH` — default `./repos`
406- `PORT` — default 3000
24cf2caClaude407- `EMAIL_PROVIDER` — `log` (default, stderr-only) or `resend`
408- `EMAIL_FROM` — sender address for outbound mail
409- `RESEND_API_KEY` — required when `EMAIL_PROVIDER=resend`
410- `APP_BASE_URL` — canonical URL used to build absolute links in emails
9ab6971Claude411
412### 5.3 Models
413- `claude-sonnet-4-20250514` — code review, security, chat
414- `claude-haiku-4-5-20251001` — commit messages, summaries, light tasks
415- Swap via `MODEL_SONNET` / `MODEL_HAIKU` constants in `src/lib/ai-client.ts`
416
417### 5.4 Deployment
418- `railway.toml` / `fly.toml` present
419- Crontech deploy on green push to default branch (can opt out via `autoDeployEnabled`)
420
421---
422
423## 6. SESSION WORKFLOW (WHAT THE NEXT AGENT DOES)
424
4251. Read this file, `CLAUDE.md`, `README.md`, `git log -1 --stat`.
4262. Check `git status` + current branch.
4273. Pick the next unfinished block from §3 (lowest letter + number first, unless owner specifies).
4284. Create a todo list that mirrors the sub-items of that block.
4295. Build. Write tests. Run `bun test`.
4306. Commit with `feat(<BLOCK-ID>): ...`.
4317. Push.
4328. Update this file:
433 - Move the block's row in §2 to ✅ where applicable.
434 - Add the block's files to §4 LOCKED BLOCKS.
435 - Commit + push again.
4369. Start the next block. **Do not stop to ask.**
437
438If a block is too large for a single session, split it into a sub-plan at the top of the session, ship what you can, and document what's left at the end of this file under a `## 7. IN-FLIGHT` section.
439
440---
441
442## 7. IN-FLIGHT
443
444(Intentionally empty. Add here if a block is partially complete at session end.)