# gluecron

AI-native code intelligence platform — git hosting, automated CI, and push-time gate enforcement.

## Source of truth: Gluecron (self-canonical, no GitHub mirror)

This repository self-hosts on Gluecron itself. The one canonical remote is
`https://gluecron.com/ccantynz/Gluecron.com.git`. **Gluecron is self-canonical:
there is no GitHub mirror or fallback.** Durability comes from the offsite
backup (`scripts/backup-offsite.sh` → rclone), not from GitHub. A fresh host
re-seeds from a restored backup (`scripts/restore.sh`), never from GitHub.
(Cutover status + operator steps: `docs/CUTOVER_RUNBOOK.md`.)

**For any AI session working in this repo:**

- Use the Gluecron MCP server. It is declared in `.mcp.json` at the
  repo root (project scope — this is the file Claude Code actually
  loads MCP servers from, on both web/cloud sessions and the CLI; the
  old `mcpServers` block in `.claude/settings.json` was never read).
  Tools: `gluecron_create_pr`, `gluecron_merge_pr`,
  `gluecron_create_issue`, `gluecron_comment_pr`, etc. See
  `src/lib/mcp-tools.ts` for the full 15-tool surface.
- Push the feature branch straight to the canonical remote —
  `git push https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git HEAD:<branch>`
  (requires `gluecron.com` in the environment's network allowlist) —
  then open the PR with `gluecron_create_pr`. There is no GitHub fallback;
  if gluecron.com is unreachable, stop and surface it rather than pushing
  to GitHub.
- Do NOT call any `mcp__github__*` write tool. The settings file's
  `permissions.deny` already blocks them; if you encounter a deny
  error, switch to the equivalent `gluecron_*` tool.
- The `.claude/skills/gluecron-pr`, `gluecron-issue`, and
  `gluecron-review` skills are the highest-leverage entry points for
  routine work. Invoke them when the user mentions a PR, an issue,
  or wants a second AI review pass.
- Auth: the `GLUECRON_PAT` env var holds the user's personal access
  token. If it's missing, prompt the user to generate one at
  `/settings/tokens` (admin scope required for the merge tools).

**Deploys are self-driven now.** Push to the canonical Gluecron remote
and `src/hooks/post-receive.ts` fires `scripts/self-deploy.sh` directly.
The live site reflects the push in ~25 seconds. Watch `/admin/deploys`
for the live step stream.

**Server:** `gluecron.com` → `66.42.121.161` (Vultr VPS, not Fly.io or Hetzner —
both are decommissioned). Working tree lives at `/opt/gluecron` on that box.

**Operator access (AI sessions included):** the box is on the owner's
Tailscale tailnet as `jarvis` (`100.109.131.122`) with **Tailscale SSH
enabled** — from an owner machine, `ssh root@100.109.131.122` just works
(no key setup). Public-internet SSH (port 22) is password-only and the git
SSH server port (2222) is not exposed; always go via Tailscale.

**Runtime layout on the box (verified 2026-07-12):**
- App runs via `docker compose -f docker-compose.standalone.yml` in
  `/opt/gluecron` (services: `gluecron`, `postgres`, `autoheal`).
- **Database is Neon** (managed Postgres, `ep-solitary-fog-...aws.neon.tech`).
  The app's `DATABASE_URL` (in `/opt/gluecron/.env`) points at Neon, so ALL
  reads/writes and migrations go there — Neon provides PITR. NOTE: the compose
  also starts a local `postgres` (pgvector/pg16) container, but the app IGNORES
  it (it's leftover/unused dead weight, like the caddy service). Do NOT back up
  or query the local container thinking it's production — target Neon via the
  app's `DATABASE_URL`. (Verified 2026-07-13.)
- Bare repos live in the docker volume `gluecron_git-repos`
  (host path `/var/lib/docker/volumes/gluecron_git-repos/_data`), mounted
  into the container at `/data/repos`. The host-side `/data/repos` dir is
  NOT the live store — always go through the volume path.
- Auto-deploy: `gluecron-update.timer` (60s) runs `scripts/auto-update.sh`
  — fetches `origin main` in `/opt/gluecron` and rebuilds on change.
  `origin` = the canonical Gluecron repo. If the timer is disabled, deploys
  silently stop — check `systemctl list-timers 'gluecron-*'` first when the
  live build looks stale (compare `/api/version` builtAt vs latest commit).
- Manual deploy: `cd /opt/gluecron && git fetch <src> main && git reset
  --hard FETCH_HEAD && docker compose -f docker-compose.standalone.yml up
  -d --build`, then `... exec -T gluecron bun run db:migrate`.

**To deploy:**
```bash
git push gluecron main
# or first-time setup:
git remote add gluecron https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git
```

**Do NOT use Vercel** — it has been disconnected.

**GitHub reality check (2026-07-12):** the old GitHub repo
(`ccantynz-alt/Gluecron.com`) is NOT frozen and is still writable — the
cutover runbook (docs/CUTOVER_RUNBOOK.md) was designed but its operator
phases were never fully executed. GitHub remains the emergency deploy
source (`git fetch https://github.com/ccantynz-alt/Gluecron.com.git main`
on the box) until offsite backups are armed and a restore drill has
passed. Do not delete or archive the GitHub repo before that. Prefer the
canonical Gluecron remote for normal work; keep GitHub in sync until the
runbook's Phase 4 criteria are actually met.

## READ FIRST — every session

**`BUILD_BIBLE.md` is mandatory reading for every Claude agent before any code changes.**

It contains:
- Agent policy (do-not-undo rule, continuous-build rule)
- GitHub parity scorecard (what's shipped vs missing)
- Numbered build plan (Blocks A–H)
- Locked components that cannot be altered without owner permission
- Session workflow

Do not skip it. Do not refactor locked files. Do not stop mid-block.

## Stack

- **Runtime:** Bun
- **Framework:** Hono (with JSX for server-rendered views)
- **Database:** Drizzle ORM + Neon (managed Postgres) in prod
- **Git:** Smart HTTP protocol via git CLI subprocesses

## Development

```bash
bun install        # install dependencies
bun dev            # start dev server (hot reload)
bun test           # run tests
bun run db:migrate # run database migrations
```

## Architecture

> Note (2026-06-10): the tree below is illustrative, not exhaustive — the
> platform has grown to ~190 route files in `src/routes/` and 161 tables in
> `src/db/schema.ts`. `BUILD_BIBLE.md` §2 is the authoritative feature map.

```
src/
  index.ts                Entry point (Bun server)
  app.tsx                 Hono app composition + error handlers
  lib/
    config.ts             Environment config (getters, reads env at access time)
    auth.ts               Password hashing (bcrypt), session tokens
    highlight.ts          Syntax highlighting (highlight.js, 40+ languages)
    markdown.ts           Markdown rendering (GFM + syntax highlighting)
  db/
    schema.ts             Drizzle schema (all tables)
    index.ts              Lazy DB connection (proxy pattern)
    migrate.ts            Migration runner
  git/
    repository.ts         Git operations (tree, blob, commits, diff, branches, blame, search, raw)
    protocol.ts           Smart HTTP protocol (pkt-line, service RPC)
  hooks/
    post-receive.ts       GateTest + optional deploy webhook on push
  middleware/
    auth.ts               softAuth + requireAuth middleware
  routes/
    git.ts                Git HTTP endpoints (clone/push)
    api.ts                REST API (repo CRUD, setup)
    auth.tsx              Register, login, logout (web + API)
    web.tsx               Web UI (file browser, commits, diffs, search, blame, raw)
    issues.tsx            Issue tracker (CRUD, comments, close/reopen)
    pulls.tsx             Pull requests (create, review, merge, close)
    editor.tsx            Web file editor (create/edit via git plumbing)
    compare.tsx           Branch comparison (diff + commit list)
    settings.tsx          User settings (profile, SSH keys)
    repo-settings.tsx     Repository settings (description, visibility, delete)
    webhooks.tsx          Webhook management + delivery engine
    fork.ts               Repository forking
    explore.tsx           Explore/discover public repos
    tokens.tsx            Personal access tokens
    contributors.tsx      Contributor list + commit activity graph
  views/
    layout.tsx            HTML shell + CSS (dark theme) + auth-aware nav
    components.tsx        UI components (file table, commit list, diff viewer, etc.)
```

## Database Schema

- `users` — accounts with bcrypt password hashing
- `sessions` — cookie-based auth sessions (30 day expiry)
- `repositories` — repos with fork tracking, star/fork/issue counts
- `stars` — user-repo star relationships
- `issues` — issue tracker with open/closed state
- `issue_comments` — threaded comments on issues
- `labels` + `issue_labels` — issue categorization
- `pull_requests` — PRs with base/head branches, open/closed/merged state
- `pr_comments` — PR comments with AI review flag + file/line annotations
- `activity_feed` — event log for repos
- `webhooks` — registered webhook URLs with HMAC secret + event filtering
- `api_tokens` — personal access tokens with SHA-256 hashing
- `repo_topics` — repository tags for discoverability
- `ssh_keys` — user SSH public keys

## Integrations

- **GateTest (optional):** third-party security scanner. When `GATETEST_URL` is set, `git push` POSTs to it; inbound results accepted at `POST /api/hooks/gatetest`.
- **Outbound deploy webhook (optional):** when `VAPRON_DEPLOY_URL` is set (legacy `CRONTECH_DEPLOY_URL` honored), pushes to the default branch POST to Vapron (formerly Crontech).
- **Webhooks:** POST to user-registered URLs on push/issue/PR/star events with HMAC signatures.

## Environment Variables

See `.env.example` for required variables. Key ones:
- `DATABASE_URL` — PostgreSQL connection string (prod: Neon; set in `/opt/gluecron/.env`)
- `GIT_REPOS_PATH` — directory for bare git repos (default: `./repos`)
- `PORT` — HTTP port (default: 3000)

## Deployment

- **Production server:** `66.42.121.161` (`gluecron.com`) — VPS running Bun directly via systemd.
- **Deploy trigger:** `git push gluecron main` → `post-receive.ts` → `scripts/self-deploy.sh` → systemd reload.
- **Fly.io:** decommissioned (fly.toml kept for reference, not active).
- **Vercel:** disconnected — do not reconnect.
- **Database:** Neon (managed Postgres) via `DATABASE_URL`; has built-in PITR.
- **Logs:** `/var/log/gluecron-self-deploy.log` on the server; live stream at `/admin/deploys`.

## Skills available for this project

Claude Code skill bundle for the Gluecron MCP write surface lives in
`.claude/skills/`. The install script (`scripts/install.sh`) copies these
into `~/.claude/skills/` so they are available across all projects:

- **`gluecron-pr`** — open, list, fetch, comment on, merge, or close pull
  requests on a Gluecron-hosted repository.
- **`gluecron-issue`** — create, list, comment on, close, or reopen issues
  on a Gluecron-hosted repository.
- **`gluecron-review`** — act as a secondary AI code reviewer on a
  Gluecron PR; complements the built-in `src/lib/ai-review.ts` pass.

All three skills drive the K1 MCP write tools defined in
`src/lib/mcp-tools.ts` (`gluecron_create_issue`, `gluecron_create_pr`,
`gluecron_merge_pr`, etc.). They auto-invoke when the active repo's
origin URL contains `gluecron.com` or matches `$GLUECRON_HOST`.
