think
16px
820px

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-foundation was
fast-forwarded onto master — the tidy rewrite IS master now, and the
old legacy code is retired. Branch new work off master;
refactor/tidyup-foundation is 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, .env with fresh
per-instance secrets, deps installed, per-worktree git identity set, and each
verified with dev-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 pull ever fails with Permission denied on 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/1dev/6) is yours — commit and push it freely,
    open PRs into master when ready.
  • master is 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 with scripts/dev-sync.sh <N>.
  • refactor/tidyup-foundation is 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.sh shows what's up.
  • If your instance's DB looks broken, bunx prisma db push inside your
    backend/ re-syncs the schema (uses the .env in your worktree root,
    symlinked into backend/.env for the Prisma CLI).
  • If ports 4701N/4702N ever seem taken by someone else, check
    docker ps / tmux ls before reusing — this file is the source of truth
    for who owns what.