# ๐Ÿงจ LANDMINE โ€” where every key lives and what it opens This repo is on the house's **private** Gitea (`gitmirah:3000`, Tailscale-only), so real `.env` files are committed on purpose. That is a deliberate trade: no `.env.example` drift, no "works on my box", and anyone cloning has a running stack. It also means **a clone of this repo is a full set of production credentials.** Treat it that way. Before this repo goes anywhere else โ€” a public mirror, GitHub, a zip to a client โ€” every secret below has to be rotated first. Deleting the file later does not help; git keeps history. --- ## What each key opens | Key | Lives in | Opens | Blast radius if leaked | |---|---|---|---| | **`SPREE_ADMIN_KEY`** | `catalogue/.env` | Full Spree **admin** API | ๐Ÿ”ด Total. Create/delete/reprice every product, read every order and customer. | | `SECRET_KEY_BASE` | `backend/.env` | Rails signing | ๐Ÿ”ด Forges sessions and signed URLs. **Rotating breaks every signed image URL and the admin API key** โ€” see below. | | `NEXT_PUBLIC_SPREE_API_KEY` | `storefront/.env.production` | Spree **store** API | ๐ŸŸก Low. Public by design โ€” it ships to every browser. Read products, create carts. Not admin. | | `EASYPARCEL_CLIENT_ID` / `_SECRET` | `storefront/.env.production` | EasyParcel account | ๐ŸŸ  Book real shipments, spend real money. | | `PHOTOROOM_API_KEY` | `backend/.env` | Photoroom **sandbox** | ๐ŸŸข Low. Watermarked output, 1000/month free. The **live** key is not in this repo. | ## Not in this repo | Thing | Where it actually is | |---|---| | Photoroom **live** key | `/root/.photoroom/credentials` on the house box (chmod 600). 10 images/month. | | Spree **admin password** | Nowhere written down. One shared account โ€” see below. | | GCloud SSH key | `/root/.ssh/google_compute_engine` on the house box. | | `storefront/.easyparcel-token.json` | A **cached OAuth token**, committed with the rest. It expires and regenerates itself; harmless, but it is a live credential while valid. | --- ## ๐Ÿ”ด Do not rotate `SECRET_KEY_BASE` casually It signs more than sessions. Changing it: - breaks **every ActiveStorage image URL** โ€” 3,228 blobs, the whole catalogue goes blank - invalidates the **admin API key**, so every script in `catalogue/` stops working To force everyone out of the admin, change the **admin password** instead โ€” that invalidates sessions without touching signed URLs. ## ๐Ÿ”ด One shared admin account Every admin session is indistinguishable. This already cost an investigation: an unknown IP (`42.188.122.106`, Windows/Brave, valid session cookie) was browsing `/admin/api_keys` and `/admin/admin_users`, and there was no way to attribute it. It turned out to be a colleague. ~5 people are expected to use the admin. Give each one their own account (Settings โ†’ Users) before that number grows. --- ## Where the boxes are | | Host | Access | |---|---|---| | Storefront | `celest-proto` 34.21.217.116 | `ssh ijat@34.21.217.116` | | Backend + DB | `pak-jabit-backend` 35.247.170.3 | `ssh -i ~/.ssh/google_compute_engine ijat@35.247.170.3` | Public: `shop.jux-lab.com` ยท `api.jux-lab.com` ยท `admin.jux-lab.com` --- ## ๐Ÿ”ด The custom backend code exists ONLY as bind mounts `ghcr.io/spree/spree` is prebuilt and mounts **no app code**. Everything under `backend/config/` and `backend/app/` needs an explicit volume entry in `docker-compose.yml`, or the container simply never loads it โ€” **no error, no warning, dead file**. The 10MB body-limit initializer sat on the host for a whole day doing nothing before anyone noticed. None of it is in the database. A rebuilt box without these files comes back with no Image Studio, no address labels, no region preference, and no EasyParcel rates. --- ## Sandbox things that are NOT real Full list in `docs/MOCKS.md`. The ones that matter most: - **`Test Card (sandbox)`** โ€” a Bogus gateway that approves any card ending in the right digits. **Deactivate before launch.** - **`Test Payment`** โ€” offline placeholder, no money moves. - **`Standard Delivery (South Africa)` R99** and **`Free Shipping` US $0** โ€” placeholder rates, not quotes. (Malaysia is real: live EasyParcel.) - **`studio-test-chinos`** โ€” a fake product, kept deliberately as the worked example for the Image Studio. --- *Written 2026-09-15, the night the stack got its region anchor and a customer-owned cart.*