Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
e47bd25
beads: plan hyperindex-49s — GraphQL filtering, sorting & query compl…
daviddao Feb 18, 2026
6b2c6ad
feat: add composite DB index for keyset pagination performance (hyper…
daviddao Feb 18, 2026
c18791b
Add did and rkey fields to typed record GraphQL types (hyperindex-49s.5)
daviddao Feb 18, 2026
bbfdf23
Add max page size limit and ClampPageSize helper (hyperindex-49s.6)
daviddao Feb 18, 2026
f3de82e
feat: scaffold shared filter input types (hyperindex-49s.1)
daviddao Feb 18, 2026
2140d47
Add per-collection sort enum and sortBy/sortDirection arguments (hype…
daviddao Feb 18, 2026
6050b63
Generate per-collection WhereInput types in schema builder (hyperinde…
daviddao Feb 18, 2026
264d333
Add LIKE-based cross-collection search query (hyperindex-49s.13)
daviddao Feb 18, 2026
8d786ca
Add FieldFilter struct and filtered query to RecordsRepository (hyper…
daviddao Feb 18, 2026
110e36d
Wire WHERE filters from GraphQL args into resolvers and repository (h…
daviddao Feb 18, 2026
140f601
feat: populate totalCount on public connections opt-in (hyperindex-49…
daviddao Feb 18, 2026
8986495
Add sorted query method tests to RecordsRepository (hyperindex-49s.9)
daviddao Feb 18, 2026
7d5f062
Wire sorting into resolvers and generalize cursor encoding (hyperinde…
daviddao Feb 18, 2026
a4a38bc
feat: add backward pagination support (last/before) (hyperindex-49s.12)
daviddao Feb 18, 2026
c179d86
Add integration tests for filter/sort/search end-to-end (hyperindex-4…
daviddao Feb 18, 2026
d9e9512
beads: all 14 tasks complete for hyperindex-49s, mark for integration…
daviddao Feb 18, 2026
5bf2b53
docs: update README with filtering, sorting, search, pagination examples
daviddao Feb 18, 2026
26976b4
docs: update API docs with filtering, sorting, search reference
daviddao Feb 18, 2026
aaebb0b
beads: plan hyperindex-q00 — bug fixes from code review (11 tasks)
daviddao Feb 18, 2026
09fd2a3
fix: remove DefaultValue from records query first arg to fix backward…
daviddao Feb 18, 2026
0af843c
Add search query timeout and concurrency control (hyperindex-q00.4)
daviddao Feb 18, 2026
6c2350d
Fix cursor pipe delimiter collision with JSON encoding (hyperindex-q0…
daviddao Feb 18, 2026
99b68c3
Fix search minimum length to use rune count and increase to 3 (hyperi…
daviddao Feb 18, 2026
ff5e7f5
Add MaxINListSize limit to prevent SQLite parameter overflow (hyperin…
daviddao Feb 18, 2026
d60d85d
Skip lexicon properties that collide with reserved field names (hyper…
daviddao Feb 18, 2026
c9d2dc3
fix: escape LIKE wildcards in contains/startsWith filter operators (h…
daviddao Feb 18, 2026
b149838
fix: expand DID filter to support eq and in operators (hyperindex-q00.6)
daviddao Feb 18, 2026
fff01bd
Add MaxFilterConditions cap to prevent filter abuse (hyperindex-q00.10)
daviddao Feb 18, 2026
56a3c6f
test: add unit tests for ClampPageSize, sortFieldValueForRecord, empt…
daviddao Feb 18, 2026
afad71a
beads: close hyperindex-q00 — all 11 bug fixes complete
daviddao Feb 18, 2026
434720d
beads: plan hyperindex-2hm — Tap sidecar integration epic (8 tasks)
daviddao Feb 18, 2026
68efb07
Add Tap config env vars to config package (hyperindex-2hm.1)
daviddao Feb 18, 2026
7e1d850
feat: add internal/tap package with event types and JSON parser (hype…
daviddao Feb 18, 2026
85ed81f
feat: implement Tap HTTP admin client (hyperindex-2hm.3)
daviddao Feb 18, 2026
5ac3f2e
Implement Tap IndexHandler that stores records and publishes to PubSu…
daviddao Feb 18, 2026
8469c62
feat: implement Tap WebSocket consumer with ack support (hyperindex-2…
daviddao Feb 18, 2026
f781a70
Wire Tap consumer into main.go with TAP_ENABLED feature flag (hyperin…
daviddao Feb 18, 2026
6b6f4c0
Add Tap deployment docs and docker-compose sidecar config (hyperindex…
daviddao Feb 18, 2026
5dfe636
feat: add Tap health check to /health and /stats endpoints (hyperinde…
daviddao Feb 18, 2026
28b47bd
beads: close hyperindex-2hm — Tap sidecar integration complete
daviddao Feb 18, 2026
1ec7bd0
beads: plan hyperindex-md3 — fix 10 Tap review bugs (B1-B10)
daviddao Feb 18, 2026
db029dc
fix: use Basic auth in README Tap curl example (hyperindex-md3.9)
daviddao Feb 18, 2026
ee9d022
Add nil guard for PubSub in IndexHandler to prevent nil-pointer panic…
daviddao Feb 18, 2026
7b362ca
security: require SECRET_KEY_BASE and TAP_ADMIN_PASSWORD, bind tap to…
daviddao Feb 18, 2026
c763c4f
validate required fields in ParseEvent to prevent garbage URIs (hyper…
daviddao Feb 18, 2026
788e1cf
fix: remove concurrent WriteMessage in Stop() to eliminate data race …
daviddao Feb 18, 2026
9271968
beads: close wave 1 of hyperindex-md3 (.1,.4,.5,.8,.9)
daviddao Feb 18, 2026
9525b34
return error from records.Delete failure instead of silently swallowi…
daviddao Feb 18, 2026
692e95b
fix: reset backoff to minBackoff after successful reconnection (hyper…
daviddao Feb 18, 2026
0a6c57e
beads: close wave 2 of hyperindex-md3 (.2,.6)
daviddao Feb 18, 2026
ecc2c69
Add WebSocket SetReadLimit to prevent OOM from oversized messages (hy…
daviddao Feb 18, 2026
2563e72
capture activity ID and update status to completed after record proce…
daviddao Feb 18, 2026
b28087c
suppress spurious context.Canceled error log on graceful shutdown (hy…
daviddao Feb 18, 2026
3e35d01
beads: close hyperindex-md3 — all 10 Tap review bugs fixed
daviddao Feb 18, 2026
58e156f
beads: plan hyperindex-xuq — 7 follow-up fixes from reviewer feedback
daviddao Feb 18, 2026
c72322b
fix: use admin username in README curl Basic auth example (hyperindex…
daviddao Feb 18, 2026
75b4d24
fix: require SECRET_KEY_BASE via :? syntax in compose files (hyperind…
daviddao Feb 18, 2026
8f394aa
test: rename DeleteError test and add delete activity status test (hy…
daviddao Feb 18, 2026
6c73f1a
fix: reject nil-payload and empty-body events in ParseEvent (hyperind…
daviddao Feb 18, 2026
a8ea6bb
fix: reset backoff only on successful connection, add escalation test…
daviddao Feb 18, 2026
5d24874
fix: guard else branch with ctx.Err() check before reconnect log (hyp…
daviddao Feb 18, 2026
f3b7ba1
beads: close hyperindex-xuq — all reviewer follow-up fixes complete
daviddao Feb 18, 2026
7e2e8e1
beads: plan hyperindex-0nk — Frontend Design Overhaul (13 tasks)
daviddao Feb 18, 2026
3e6b656
docs: rename branding to Hyperindex in agents route (hyperindex-0nk.12)
daviddao Feb 18, 2026
dbacf8f
feat: rewrite globals.css with OKLCH design tokens + dark mode (hyper…
daviddao Feb 18, 2026
d39a509
rename Hypergoat → Hyperindex in user-visible strings and client conf…
daviddao Feb 18, 2026
4143af6
simplify GeometricBackground with theme-aware colors and hypercerts l…
daviddao Feb 18, 2026
812315d
feat: add ThemeProvider and ThemeToggle components (hyperindex-0nk.3)
daviddao Feb 18, 2026
e0029c7
feat: update Card, Button, Input, Alert for dark mode + CSS tokens (h…
daviddao Feb 18, 2026
a6db65d
Layout: Wire ThemeProvider, update body/html, replace logo, update fo…
daviddao Feb 18, 2026
78649fb
redesign Header with glass-panel, hypercerts logo, Hyperindex brandin…
daviddao Feb 18, 2026
dffe0f3
feat: update lexicons and backfill pages for dark mode (hyperindex-0n…
daviddao Feb 18, 2026
4b86216
feat: update Dashboard page and sub-components for dark mode (hyperin…
daviddao Feb 18, 2026
6033c8f
feat: update settings and onboarding pages for dark mode (hyperindex-…
daviddao Feb 18, 2026
0198d61
docs page: update branding, font-syne, dark mode CSS vars (hyperindex…
daviddao Feb 18, 2026
7ccd9a4
beads: mark hyperindex-0nk for integration review — all 13 tasks closed
daviddao Feb 18, 2026
c4ecd14
feat: add client Dockerfile + standalone output for Railway deployment
daviddao Feb 18, 2026
1ca7f43
fix: use dynamic backend URL for GraphiQL links and API docs
daviddao Feb 18, 2026
981a312
fix: GraphiQL redirect route and Dockerfile build arg for NEXT_PUBLIC…
daviddao Feb 18, 2026
4035050
beads: plan hyperindex-a10 — make dashboard public
daviddao Feb 19, 2026
9e8acfc
Make statistics, activityBuckets, recentActivity public (hyperindex-a10)
daviddao Feb 19, 2026
f2748e4
docs: add deploy-railway skill for frontend/backend deployment
daviddao Feb 19, 2026
d96ad45
beads: plan hyperindex-2rz — batch lexicon registration
daviddao Feb 19, 2026
6275449
feat: support batch lexicon registration via comma/newline-separated …
daviddao Feb 19, 2026
4241da8
beads: plan hyperindex-vz7 — fix NonNull GraphQL violations for requi…
daviddao Feb 19, 2026
7fc19ad
Add ZeroValueForType and RequiredProperties to lexicon package (hyper…
daviddao Feb 19, 2026
fb5c723
Add coerceRequiredFields to schema builder and wire into resolvers (h…
daviddao Feb 19, 2026
ae64fae
test: add integration tests for null coercion of required fields (hyp…
daviddao Feb 19, 2026
c15ebb9
beads: mark hyperindex-vz7 for integration review — all children closed
daviddao Feb 19, 2026
e30e889
beads: close hyperindex-vz7 — NonNull coercion complete
daviddao Feb 19, 2026
68e95da
beads: spec review follow-ups hyperindex-5ar, bn7, 3gm
daviddao Feb 19, 2026
18c6350
test: add TestCoerceRequiredFields_SingleRecordResolver for ByUri pat…
daviddao Feb 19, 2026
e706083
Remove unused format parameter from ZeroValueForType (hyperindex-bn7)
daviddao Feb 19, 2026
659483d
Merge pull request #35 from hypercerts-org/tap-feature
daviddao Feb 20, 2026
be7492a
fix: resolve 7 golangci-lint v2 issues blocking PR #34
daviddao Mar 5, 2026
3097549
Merge pull request #1 from GainForest/filter-feature
daviddao Mar 5, 2026
2b2e684
ci: run on any pr
Kzoeps Apr 14, 2026
ec510b8
ci: run integration tests with race
Kzoeps Apr 14, 2026
94e221b
Merge pull request #7 from GainForest/ci-workflow-fix
Kzoeps Apr 14, 2026
0e7e0f1
fix: send Basic Auth header on TAP WebSocket handshake
Kzoeps Apr 6, 2026
4979c66
fix: resolve TAP_DISABLE_ACKS=false health check failure and silent r…
Kzoeps Apr 7, 2026
0bfedbf
fix: send JSON acks to Tap server and reconnect immediately on write …
Kzoeps Apr 7, 2026
f99981a
fix: tests after lexicons update
Kzoeps Apr 9, 2026
1783601
make delete obvious
Kzoeps Apr 9, 2026
a4376ae
fix: prioritize NEXT_PUBLIC_CLIENT_URL for client URL
Kzoeps Apr 9, 2026
9562089
fix: rename client public URL env accessor
Kzoeps Apr 9, 2026
770c389
fix: normalize vercel branch url fallback
Kzoeps Apr 9, 2026
fa7d2c2
feat: add log
Kzoeps Apr 9, 2026
b435be5
add more logs
Kzoeps Apr 9, 2026
f1bc5d0
fix: read NEXT_PUBLIC client URL directly
Kzoeps Apr 9, 2026
dc4f4c8
fix: improve lexicon delete icon visibility
Kzoeps Apr 9, 2026
5e32065
increate railway toml config
Kzoeps Apr 9, 2026
7972666
fix: pagination cursor issue
Kzoeps Apr 10, 2026
bb2f59e
refactor: modernize DPoP key handling and clean tap consumer signature
Kzoeps Apr 14, 2026
6a558bb
ci: precommit local hook run
Kzoeps Apr 14, 2026
279d5c1
fix: normalize SQLite indexed_at ordering for keyset pagination
Kzoeps Apr 14, 2026
afd2844
fix: resolve coderabbit issues for hook compatibility and key handling
Kzoeps Apr 14, 2026
ca01651
ci: bump pakage version
Kzoeps Apr 14, 2026
5e45e01
fix: normalize client URL metadata and bound Tap sidecar health probe
Kzoeps Apr 14, 2026
9a3040e
fix: return JWKS server errors with request IDs
Kzoeps Apr 14, 2026
44210a0
fix: emit fixed-width DPoP JWK coordinates
Kzoeps Apr 14, 2026
7443216
chore: enforce gofmt checks in pre-commit hook
Kzoeps Apr 14, 2026
1c0d51d
fix: reconnect immediately after Tap ack write failures
Kzoeps Apr 14, 2026
1f23b66
Merge pull request #8 from GainForest/fix/tap-ack-issue
Kzoeps Apr 14, 2026
8715fd8
fix: redact Tap sidecar errors from stats
Kzoeps Apr 14, 2026
82141c1
feat: add batched admin DID picker with Bluesky typeahead
Kzoeps Apr 15, 2026
67df7ae
refactor: call Bluesky typeahead directly from client
Kzoeps Apr 15, 2026
92e2992
feat: show admin handles and avatars in settings
Kzoeps Apr 15, 2026
3a83cdb
feat: enrich pending admin chips with profile details
Kzoeps Apr 15, 2026
96c02e2
Merge pull request #12 from GainForest/add-admin-dids-page
Kzoeps Apr 15, 2026
ec13dcf
Merge pull request #13 from GainForest/main
Kzoeps Apr 15, 2026
bc80d7c
Merge pull request #14 from GainForest/staging
Kzoeps Apr 15, 2026
57126f9
docs: add env var reference and align Railway skill naming
Kzoeps Apr 16, 2026
de7ec98
fix: purge inactive identities from indexed actor data
Kzoeps Apr 16, 2026
13a40b4
feat: add admin actor purge flow with safety preview
Kzoeps Apr 16, 2026
135bd49
fix: remove removeFromTap from purgeActor and address CodeRabbit feed…
Kzoeps Apr 16, 2026
6c7d2fc
refactor: rename NEXT_PUBLIC_API_URL to NEXT_PUBLIC_HYPERINDEX_URL an…
Kzoeps Apr 16, 2026
7bc790b
fix: use PUBLIC_CLIENT_URL for OAuth callback redirects on Railway
Kzoeps Apr 16, 2026
b926892
fix: normalize EXTERNAL_BASE_URL to add https:// when scheme is missing
Kzoeps Apr 16, 2026
3081a19
fix: apply fallback after normalization for HYPERINDEX_URL env vars
Kzoeps Apr 16, 2026
3562648
fix: trim whitespace and use case-insensitive scheme check for Extern…
Kzoeps Apr 17, 2026
c7de4cd
Merge pull request #15 from GainForest/delete-by-did
Kzoeps Apr 17, 2026
88663c0
fix: fail fast on client backend url mixup
Kzoeps Apr 17, 2026
d163436
Merge pull request #17 from GainForest/env-var-validation
Kzoeps Apr 17, 2026
bb049fb
chore: stop tracking local Beads runtime files
Kzoeps Apr 21, 2026
c5b0680
Merge pull request #19 from GainForest/fix-beads-daemon
Kzoeps Apr 21, 2026
7536679
fix: gate settings UI to configured admin DIDs
Kzoeps Apr 21, 2026
593fcc9
docs: clarify NEXT_PUBLIC_ADMIN_DIDS usage
Kzoeps Apr 21, 2026
bf8163a
Merge pull request #21 from GainForest/admin-validation
Kzoeps Apr 21, 2026
c8d76bd
feat: add coderabbit yaml
Kzoeps Apr 21, 2026
c9f6450
chore: remove docs for design env vars
Kzoeps Apr 21, 2026
dbe0b56
remove coderabbit config
Kzoeps Apr 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions .agents/skills/deploy-railway/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
name: deploy-railway
description: Deploy the Hyperindex frontend and backend to Railway. Use this skill when the user asks to deploy, redeploy, or update the production services on Railway.
---

# Deploy Hyperindex to Railway

## Project Layout

Hyperindex is a monorepo with two Railway services:

| Service | Source | Dockerfile | Railway Name |
|---------|--------|------------|-------------|
| **Backend** (Go) | repo root `/` | `Dockerfile` | `backend` |
| **Frontend** (Next.js) | `client/` | `client/Dockerfile` | `frontend` |

## Custom Domains

| Service | Domain |
|---------|--------|
| Backend | `https://api.hi.gainforest.app` |
| Frontend | `https://hi.gainforest.app` |

Legacy domains (still active): `backend-production-95a22.up.railway.app`, `frontend-production-dcce.up.railway.app`

## Prerequisites

- Railway CLI v4+ installed and logged in (`railway whoami`)
- Linked to project: `railway status` should show project `hyperindex`
- On the correct git branch (typically `tap-feature`)

## Deploy Backend

The backend deploys from the repo root using the root `Dockerfile`:

```bash
railway up -s backend -d
```

This uploads the entire repo, builds the Go binary in Docker, and deploys it. Takes ~3-5 minutes.

### Verify backend:
```bash
curl -s https://api.hi.gainforest.app/
# Should return: {"name":"Hyperindex","version":"0.1.0-dev",...}
```

## Deploy Frontend

**CRITICAL:** The frontend MUST use `--path-as-root` to avoid Railway picking up the root Go Dockerfile:

```bash
railway up --path-as-root client/ -s frontend -d
```

This makes `client/` the archive root so Railway only sees `client/Dockerfile` (the Next.js build). Takes ~3-5 minutes.

### Why `--path-as-root`?

Without it, `railway up` uploads the entire monorepo and Railway finds the root `Dockerfile` (Go backend) instead of `client/Dockerfile` (Next.js frontend). This causes the frontend service to run the Go binary instead of the Next.js app.

### Verify frontend:
```bash
curl -s -o /dev/null -w "%{http_code}" https://hi.gainforest.app/
# Should return: 200

# Verify it's actually Next.js (not the Go server):
curl -s https://hi.gainforest.app/ | grep -o '<title>[^<]*</title>'
# Should return: <title>Hyperindex</title>
```

## Deploy Both Services

```bash
# Backend (from repo root)
railway up -s backend -d

# Frontend (with path-as-root)
railway up --path-as-root client/ -s frontend -d
```

## Environment Variables

### Backend (`backend` service)
| Variable | Value |
|----------|-------|
| `HOST` | `0.0.0.0` |
| `PORT` | `8080` |
| `DATABASE_URL` | `sqlite:/app/data/hypergoat.db` |
| `EXTERNAL_BASE_URL` | `https://api.hi.gainforest.app` |
| `TRUST_PROXY_HEADERS` | `true` |
| `ADMIN_DIDS` | `did:plc:qc42fmqqlsmdq7jiypiiigww` (daviddao.org) |
| `OAUTH_LOOPBACK_MODE` | `true` |
| `SECRET_KEY_BASE` | *(set on Railway, do not change)* |

### Frontend (`frontend` service)
| Variable | Value |
|----------|-------|
| `PORT` | `3000` |
| `NEXT_PUBLIC_CLIENT_URL` | `https://hi.gainforest.app` |
| `NEXT_PUBLIC_API_URL` | `https://api.hi.gainforest.app` |
| `HYPERINDEX_URL` | `https://api.hi.gainforest.app` |
| `COOKIE_SECRET` | *(set on Railway, do not change)* |
| `ATPROTO_JWK_PRIVATE` | *(ES256 JWK, set on Railway, do not change)* |

**Note:** `NEXT_PUBLIC_API_URL` is a build-time variable (inlined by Next.js during `npm run build`). The `client/Dockerfile` declares `ARG NEXT_PUBLIC_API_URL` so Railway passes it during Docker build.

Comment on lines +101 to +107
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 SKILL.md references the stale env var NEXT_PUBLIC_API_URL at lines 101 and 106, but this PR renames it to NEXT_PUBLIC_HYPERINDEX_URL everywhere else (Dockerfile, env.ts, .env.example, docs/ENV_VARS.md). A developer following SKILL.md to deploy on Railway will set the wrong build arg, causing Next.js to silently fall back to http://127.0.0.1:8080, which breaks the production frontend.

Extended reasoning...

What the bug is and how it manifests

The newly-added .agents/skills/deploy-railway/SKILL.md file was created by this PR. The Frontend env vars table on line 101 lists NEXT_PUBLIC_API_URL as the build-time variable to set. The note on line 106 states "The client/Dockerfile declares ARG NEXT_PUBLIC_API_URL". Both of these are wrong: this same PR renames the variable from NEXT_PUBLIC_API_URL to NEXT_PUBLIC_HYPERINDEX_URL across the entire codebase.

The specific code path that triggers it

client/Dockerfile (added in this PR) declares:

ARG NEXT_PUBLIC_HYPERINDEX_URL
ENV NEXT_PUBLIC_HYPERINDEX_URL=$NEXT_PUBLIC_HYPERINDEX_URL

Next.js bakes NEXT_PUBLIC_* variables into the JavaScript bundle at build time. If Railway sets NEXT_PUBLIC_API_URL (as SKILL.md instructs), Docker never sees NEXT_PUBLIC_HYPERINDEX_URL, so it remains unset. The client-side code in client/src/lib/env.ts then resolves NEXT_PUBLIC_HYPERINDEX_URL to an empty string and falls back to http://127.0.0.1:8080 — a loopback address unreachable from the browser in production.

Why existing code doesn't prevent it

client/src/lib/env.ts validates the URL configuration at module load time, but only checks that HYPERINDEX_URL (the server-side var) doesn't point to the client origin — it does not warn when NEXT_PUBLIC_HYPERINDEX_URL is missing. The misconfiguration produces no visible error; the frontend simply makes all GraphQL requests to 127.0.0.1:8080 and gets network failures in the user's browser.

What the impact would be

Any deployer who follows the SKILL.md instructions will end up with a broken Railway frontend. Every GraphQL query from the browser fails silently (or with a CORS/network error). The Vercel-style deployment works because Vercel injects env vars differently, but the Railway Docker build path is exactly what SKILL.md is trying to guide.

How to fix it

In SKILL.md, replace both occurrences of NEXT_PUBLIC_API_URL with NEXT_PUBLIC_HYPERINDEX_URL. Also, docs/ENV_VARS.md (added in the same PR) explicitly documents NEXT_PUBLIC_API_URL as "Removed — Renamed to NEXT_PUBLIC_HYPERINDEX_URL", so the skill file is already inconsistent with the authoritative reference within this same PR.

Step-by-step proof

  1. Developer reads SKILL.md and sets Railway build var: NEXT_PUBLIC_API_URL=https://api.hi.gainforest.app
  2. Railway runs: docker build --build-arg NEXT_PUBLIC_API_URL=... client/
  3. client/Dockerfile declares ARG NEXT_PUBLIC_HYPERINDEX_URL — the passed NEXT_PUBLIC_API_URL build arg is unknown and silently ignored.
  4. NEXT_PUBLIC_HYPERINDEX_URL remains empty inside the Docker build context.
  5. npm run build runs; Next.js inlines process.env.NEXT_PUBLIC_HYPERINDEX_URL as "" into the JS bundle.
  6. At runtime, env.ts resolves: normalizePublicURL("") → "", then falls back to http://127.0.0.1:8080.
  7. All browser-side GraphQL calls go to http://127.0.0.1:8080/graphql — a loopback address the user's browser cannot reach — silently breaking the production frontend.

## Troubleshooting

### Frontend shows Go JSON response instead of HTML
You forgot `--path-as-root client/`. Redeploy with:
```bash
railway up --path-as-root client/ -s frontend -d
```

### "Application not found" on custom domain
SSL certificate is still provisioning. Wait 5-15 minutes after adding DNS records.

### GraphiQL returns 500 through frontend
GraphiQL is served directly by the backend. The frontend has a `/graphiql` server-side redirect route that redirects to `https://api.hi.gainforest.app/graphiql`.

### OAuth login fails
Check that `ATPROTO_JWK_PRIVATE` and `NEXT_PUBLIC_CLIENT_URL` are set on the frontend service. Generate a new JWK with:
```bash
node scripts/generate-jwk.js # (in hyperscan repo, or client/scripts/ if copied)
```

### "admin privileges required" after login
Ensure `TRUST_PROXY_HEADERS=true` is set on the backend. Without it, the backend ignores the `X-User-DID` header from the Next.js proxy.

## Setting Environment Variables

```bash
# Set a variable on a service
railway variables set 'KEY=value' -s backend
railway variables set 'KEY=value' -s frontend

# View all variables for a service
railway variables -s backend
railway variables -s frontend
```

After changing env vars, redeploy the affected service.
46 changes: 46 additions & 0 deletions .beads/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# SQLite databases
*.db
*.db?*
*.db-journal
*.db-wal
*.db-shm

# Daemon runtime files
daemon.lock
daemon.log
daemon.pid
bd.sock
sync-state.json
last-touched

# Local version tracking (prevents upgrade notification spam after git ops)
.local_version

# Legacy database files
db.sqlite
bd.db

# Worktree redirect file (contains relative path to main repo's .beads/)
# Must not be committed as paths would be wrong in other clones
redirect

# Merge artifacts (temporary files from 3-way merge)
beads.base.jsonl
beads.base.meta.json
beads.left.jsonl
beads.left.meta.json
beads.right.jsonl
beads.right.meta.json

# Sync state (local-only, per-machine)
# These files are machine-specific and should not be shared across clones
.sync.lock
.jsonl.lock
sync_base.jsonl
export-state/

# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
# They would override fork protection in .git/info/exclude, allowing
# contributors to accidentally commit upstream issue databases.
# The JSONL files (issues.jsonl, interactions.jsonl) and config files
# are tracked by git by default since no pattern above ignores them.
81 changes: 81 additions & 0 deletions .beads/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Beads - AI-Native Issue Tracking

Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.

## What is Beads?

Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.

**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)

## Quick Start

### Essential Commands

```bash
# Create new issues
bd create "Add user authentication"

# View all issues
bd list

# View issue details
bd show <issue-id>

# Update issue status
bd update <issue-id> --status in_progress
bd update <issue-id> --status done

# Sync with git remote
bd sync
```

### Working with Issues

Issues in Beads are:
- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
- **Branch-aware**: Issues can follow your branch workflow
- **Always in sync**: Auto-syncs with your commits

## Why Beads?

✨ **AI-Native Design**
- Built specifically for AI-assisted development workflows
- CLI-first interface works seamlessly with AI coding agents
- No context switching to web UIs

🚀 **Developer Focused**
- Issues live in your repo, right next to your code
- Works offline, syncs when you push
- Fast, lightweight, and stays out of your way

🔧 **Git Integration**
- Automatic sync with git commits
- Branch-aware issue tracking
- Intelligent JSONL merge resolution

## Get Started with Beads

Try Beads in your own projects:

```bash
# Install Beads
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash

# Initialize in your repo
bd init

# Create your first issue
bd create "Try out Beads"
```

## Learn More

- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
- **Quick Start Guide**: Run `bd quickstart`
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)

---

*Beads: Issue tracking that moves at the speed of thought* ⚡
67 changes: 67 additions & 0 deletions .beads/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Beads Configuration File
# This file configures default behavior for all bd commands in this repository
# All settings can also be set via environment variables (BD_* prefix)
# or overridden with command-line flags

# Issue prefix for this repository (used by bd init)
# If not set, bd init will auto-detect from directory name
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
# issue-prefix: ""

# Use no-db mode: load from JSONL, no SQLite, write back after each command
# When true, bd will use .beads/issues.jsonl as the source of truth
# instead of SQLite database
# no-db: false

# Disable daemon for RPC communication (forces direct database access)
# no-daemon: false

# Disable auto-flush of database to JSONL after mutations
# no-auto-flush: false

# Disable auto-import from JSONL when it's newer than database
# no-auto-import: false

# Enable JSON output by default
# json: false

# Default actor for audit trails (overridden by BD_ACTOR or --actor)
# actor: ""

# Path to database (overridden by BEADS_DB or --db)
# db: ""

# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
# auto-start-daemon: true

# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
# flush-debounce: "5s"

# Export events (audit trail) to .beads/events.jsonl on each flush/sync
# When enabled, new events are appended incrementally using a high-water mark.
# Use 'bd export --events' to trigger manually regardless of this setting.
# events-export: false

# Git branch for beads commits (bd sync will commit to this branch)
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
# This setting persists across clones (unlike database config which is gitignored).
# Can also use BEADS_SYNC_BRANCH env var for local override.
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
# sync-branch: "beads-sync"

# Multi-repo configuration (experimental - bd-307)
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
# repos:
# primary: "." # Primary repo (where this database lives)
# additional: # Additional repos to hydrate from (read-only)
# - ~/beads-planning # Personal planning repo
# - ~/work-planning # Work planning repo

# Integration settings (access with 'bd config get/set')
# These are stored in the database, not in this file:
# - jira.url
# - jira.project
# - linear.url
# - linear.api-key
# - github.org
# - github.repo
Empty file added .beads/interactions.jsonl
Empty file.
Loading
Loading