AHU OCR — 6-developer environment (valserver)
Six fully isolated instances of the codebase, running side by side on this
server so nobody's work collides. Nothing here touches the staging deploy
(:3520, GPU server) — this is a separate, self-contained sandbox.
Branch cutover (2026-07-27):
refactor/tidyup-foundationwas
fast-forwarded ontomaster— the tidy rewrite ISmasternow, and the
old legacy code is retired. Branch new work offmaster;
refactor/tidyup-foundationis frozen as a historical pointer.
Layout
ahu-ocr-dev/
dev_1/…/dev_6/ git worktrees, own branch each (dev/1 … dev/6),
based on master, same .git as
../ahu-ocr-tidyup (shared object store, isolated checkouts)
docker-compose.dev-db.yaml ONE shared Postgres container, 12 databases (see below)
init-databases.sh ran once at container creation to create those DBs
scripts/dev-up.sh <N> start instance N (backend + frontend, tmux session ahu-dev-N)
scripts/dev-down.sh <N> stop instance N
scripts/dev-status.sh show what is running
scripts/dev-sync.sh <N> bring slot N up to date with master (safe: refuses a dirty tree)
Assignment
| Slot | Owner | Branch | Backend port | Frontend port | Database | Test database |
|---|---|---|---|---|---|---|
| dev_1 | Marvella | dev/1 | 47011 | 47021 | ahu_ocr_dev1 | ahu_ocr_dev1_test |
| dev_2 | Viernicia | dev/2 | 47012 | 47022 | ahu_ocr_dev2 | ahu_ocr_dev2_test |
| dev_3 | Firman | dev/3 | 47013 | 47023 | ahu_ocr_dev3 | ahu_ocr_dev3_test |
| dev_4 | Xaviero | dev/4 | 47014 | 47024 | ahu_ocr_dev4 | ahu_ocr_dev4_test |
| dev_5 | Dian | dev/5 | 47015 | 47025 | ahu_ocr_dev5 | ahu_ocr_dev5_test |
| dev_6 | Vincentius | dev/6 | 47016 | 47026 | ahu_ocr_dev6 | ahu_ocr_dev6_test |
dev_4 (2026-07-21, Xaviero) and dev_5 (2026-07-27, Dian) were added by
mirroring the original pattern — worktree, own DB pair,.envwith fresh
per-instance secrets, deps installed, per-worktree git identity set, and each
verified withdev-up.sh <N>→ backend + frontend both HTTP 200.
Each slot's git commit identity is already set to its owner (per-worktree), so
commits are attributed correctly even though you all share the developer login.
Shared Postgres container ahu-ocr-dev-db listens on 127.0.0.1:47030 (bound to
loopback only — not reachable off this host). Shared GPU/OCR/LLM services (the
same ones staging uses) are pre-configured in each dev_N/.env.
Everything is bound to 127.0.0.1 — nothing here is exposed to the internet.
You reach it by already being logged into this server, or via an SSH tunnel.
Day to day
Go to your slot (Marvella → 1, Viernicia → 2, Firman → 3, Xaviero → 4,
Dian → 5, Vincentius → 6; see the Assignment table) and cd into it:
cd /home/efran/remote-development/poc-ahu-ai/ahu-ocr-dev/dev_1 # <- your slot
git status # you're on your own branch (dev/1 … dev/6)
../scripts/dev-sync.sh 1 # pull in the latest work from master (your slot number)
Start/stop your instance (runs backend + frontend together in a tmux session):
/home/efran/remote-development/poc-ahu-ai/ahu-ocr-dev/scripts/dev-up.sh 1 # your N
/home/efran/remote-development/poc-ahu-ai/ahu-ocr-dev/scripts/dev-status.sh
/home/efran/remote-development/poc-ahu-ai/ahu-ocr-dev/scripts/dev-down.sh 1
View live logs / restart on a crash:
tmux attach -t ahu-dev-1 # your N; Ctrl+B then D to detach without killing it
bun isn't on the default PATH yet — either add this to your own ~/.bashrc:
export PATH="/home/efran/.bun/bin:$PATH"
or just use the full path /home/efran/.bun/bin/bun (that's what the scripts do).
Viewing the frontend in your own browser
Nothing is exposed publicly (no DNS, no public port) by design. From your own
laptop, open an SSH tunnel to your instance's frontend port and browse to
localhost on your machine:
ssh -L 47021:localhost:47021 developer@<valserver-ip> # dev_1's port; use 47022/47023 for dev_2/3
# then open http://localhost:47021 in your own browser
Keep that SSH session open while you work (or add -N to just hold the tunnel
without a shell).
Tests
cd dev_1/backend
TEST_DATABASE_URL="postgresql://ahu:ahu_dev@127.0.0.1:47030/ahu_ocr_dev1_test" bun test
cd ../frontend
bun run test
⚠️ SYNC NEEDED (2026-07-27) — everyone please run this
master has moved a long way ahead of every slot (17–57 commits), and it now
includes a security wave: role/domain separation, per-object authorization,
and fixes for 17 findings from a security scan. There are also 2 new database
migrations. Sync with:
/home/efran/remote-development/poc-ahu-ai/ahu-ocr-dev/scripts/dev-sync.sh <your slot>
That one command merges master, installs deps only if they changed, syncs
both your databases, and regenerates the Prisma client. Then restart:
scripts/dev-down.sh <N> && scripts/dev-up.sh <N>
It refuses to run if you have uncommitted changes — that's deliberate, so it
can never clobber your work. Commit first, then re-run. (Right now dev_1, dev_2,
dev_3 and dev_4 all have uncommitted work.)
Notes:
- Use the script rather than prisma migrate deploy by hand: your dev databases
were created with db push and have no migration history, so migrate deploy
fails on them with P3005. The script does the right thing.
- Nothing changes about how you log in locally — SECURITY_ENFORCE is unset in
your .env, so the new auth guards stay in report-only (shadow) mode and your
slot behaves exactly as before. Staging is different: it now enforces, so
the demo requires logging in at /login.
GitHub access (do this once)
git pull / git push talk to a private GitHub repo over SSH, so the
shared developer account needs its own deploy key first (this is separate
from efran's key — you never use his). Run this once, from anywhere:
/home/efran/remote-development/poc-ahu-ai/ahu-ocr-dev/scripts/setup-github-access.sh
The first run generates the key and prints it (also saved to
developer-github-deploy-key.pub in the ahu-ocr-dev/ folder). Give that key
to Efran — he adds it once, for the whole developer account, under the repo's
Settings → Deploy keys with Allow write access ticked. Then re-run the
script (or just git pull) and it should say OK. After that, normal
git pull / git push work in every slot.
Your slot's commit identity is already set to you (per-worktree — see the
Assignment table). Double-check with git config --worktree --get user.email;
if you ever need to correct it, git config --worktree user.email "you@…".
If
git pullever fails withPermission deniedon a path under
…/ahu-ocr-akta-notaris/.git/…, that's a shared-repo group-permission
hiccup, not your key — tell Efran and he'll refresh it.
Git workflow
- Your slot's branch (
dev/1…dev/6) is yours — commit and push it freely,
open PRs intomasterwhen ready. masteris the shared integration branch (since the 2026-07-27 cutover) —
please go through a PR rather than pushing directly, so nobody's work gets
clobbered. Sync from it withscripts/dev-sync.sh <N>.refactor/tidyup-foundationis FROZEN at the cutover commit as a historical
pointer — don't commit or push to it.- Nobody deploys to the staging environment (
x056.ahu-demo.ocr.val.id,
GPU server:3520) from here — that stays a deliberate, reviewed step.
Troubleshooting
scripts/dev-status.shshows what's up.- If your instance's DB looks broken,
bunx prisma db pushinside your
backend/re-syncs the schema (uses the.envin your worktree root,
symlinked intobackend/.envfor the Prisma CLI). - If ports 4701N/4702N ever seem taken by someone else, check
docker ps/tmux lsbefore reusing — this file is the source of truth
for who owns what.