diff --git a/README.md b/README.md index 254ecb6..648a472 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # granthi-sync v1.2 The signup → download → link-folders → cloud product spine for the Granthi -forge, tested against the BETA forge (granthi-beta.shre.ai). Python 3 stdlib + -git CLI only — same portability heritage as the estate's `gitea_sync.py` mesh. +forge. Developed and live-E2E-tested against the BETA forge +(granthi-beta.shre.ai); **the deployed service now runs against the PRODUCTION +forge** — see "Where this actually runs" below. Python 3 stdlib + git CLI only +— same portability heritage as the estate's `gitea_sync.py` mesh. ``` ┌──────────────┐ device flow ┌─────────────────┐ @@ -13,7 +15,8 @@ git CLI only — same portability heritage as the estate's `gitea_sync.py` mesh. │ │ POST /v1/link {zitadel_access_token, device_name} │ │ ───────────────▶ ┌───────────────────────────────┐ │ │ ◀─────────────── │ granthi-link :3042 │ - │ │ {login, token} │ (granthi VPS, tailnet-only) │ + │ │ {login, token} │ (granthi VPS; public via │ + │ │ │ https://granthi-link.shre.ai)│ │ │ │ · userinfo validation │ │ │ POST /v1/repos │ · ensure Gitea user (admin) │ │ │ ───────────────▶ │ · mint scoped user token │ @@ -21,11 +24,28 @@ git CLI only — same portability heritage as the estate's `gitea_sync.py` mesh. │ │ git push/fetch (user token │ admin API │ │ via credential helper) ▼ │ │ ───────────────▶ ┌───────────────────────────────┐ - └──────────────┘ │ BETA forge :3041 │ - │ granthi-beta.shre.ai │ + └──────────────┘ │ PROD forge :3040 │ + │ granthi.shre.ai │ └───────────────────────────────┘ ``` +## Where this actually runs + +Verified on the granthi VPS (`root@100.111.127.127`) on 2026-08-30, because +this file previously described the beta tier long after the deployment moved: + +| | value | +|---|---| +| service | `/opt/granthi-link/`, `granthi-link.service`, `systemctl is-active` → `active` | +| public entry | `https://granthi-link.shre.ai` — `/health` → 200. `/` → 404 is **no root route**, not an outage | +| `gitea_base` | `http://127.0.0.1:3040` (container `gitea-central-gitea-1`) | +| `public_gitea_base` | `https://granthi.shre.ai` | +| rate limiting | `trust_forwarded_for: true`, `trusted_proxies: ["100.107.37.98/32"]`, no `rules` key → falls back to `DEFAULT_RATE_RULES` | +| deployed version | `/health` reports **1.1.0** while this repo is **v1.2** — the running service lags `main` | + +So a new computer that follows Quickstart lands on the **production** forge. +Beta remains where changes are proven before they reach it. + ## Quickstart (invited user) You need a shre-id account — an operator creates it; there is no open signup @@ -194,13 +214,16 @@ So: **64 KB** (413 beyond; missing `Content-Length` → 411, invalid → 400). * `POST /v1/repos {token, name, private}` → creates the user repo with the USER token; clone/html URLs are rebased onto `public_gitea_base` because the - container `ROOT_URL` (https://granthi-beta.shre.ai) does not resolve for - tailnet-only clients. + container `ROOT_URL` does not necessarily resolve for the client that asked + (it was a tailnet-only address on beta; on prod the rebase keeps clone URLs + on `https://granthi.shre.ai` rather than the container's own view). Deployment: `/opt/granthi-link/{granthi_link.py,config.json,state.json}` + systemd unit `granthi-link.service`; binds `127.0.0.1:3042` **and** -`100.111.127.127:3042` (tailnet). **Not publicly exposed** — see promotion -window. The service **refuses to start** (exit 2) unless `config.json` is +`100.111.127.127:3042` (tailnet), and is **publicly reachable** at +`https://granthi-link.shre.ai` through the `pulse-granthi-edge` cloudflared +tunnel (done 2026-08-23; re-verified 2026-08-30). The service **refuses to +start** (exit 2) unless `config.json` is mode 0600/0400 and owned by the user it runs as — the config carries the forge admin password, so permissive perms fail closed, not open. @@ -620,10 +643,12 @@ Shape this should take, so the next session does not re-litigate it: `https://granthi-link.shre.ai` (second-level, see above), origin stays tailnet-only, `trust_forwarded_for` on with the tunnel as the only trusted proxy. -2. **Swap forge base URLs** in `/opt/granthi-link/config.json`: - `gitea_base` → prod forge, `public_gitea_base` → - `https://granthi.shre.ai`; the client default server URL moves to the - public endpoint. +2. ~~**Swap forge base URLs** in `/opt/granthi-link/config.json`~~ + **DONE — verified live 2026-08-30**: the deployed config reads + `gitea_base: http://127.0.0.1:3040` and + `public_gitea_base: https://granthi.shre.ai`, and the client default + server is already the public endpoint. Linking a new device therefore + creates the account on **prod**. 3. The `granthi-web` OIDC app already lists the prod callback; the device app is host-independent. Rotate the beta admin token/password out of the config when pointing at prod (prod forge is READ-ONLY to this estate — diff --git a/server/config.example.json b/server/config.example.json index 40f1fb6..b53273f 100644 --- a/server/config.example.json +++ b/server/config.example.json @@ -1,15 +1,17 @@ { - "gitea_base": "http://127.0.0.1:3041", - "public_gitea_base": "http://100.111.127.127:3041", + "_comment_forge": "Values below mirror the LIVE prod deployment (verified 2026-08-30). For the beta tier use gitea_base http://127.0.0.1:3041, public_gitea_base https://granthi-beta.shre.ai, container gitea-beta-gitea-1, creds /opt/gitea-beta/.admin-creds.", + "gitea_base": "http://127.0.0.1:3040", + "public_gitea_base": "https://granthi.shre.ai", "zitadel_userinfo": "https://id.shre.ai/oidc/v1/userinfo", - "admin_token": "MINT-VIA: docker exec -u git gitea-beta-gitea-1 gitea admin user generate-access-token --username nirpa --scopes write:admin,write:user,write:repository --raw", + "admin_token": "MINT-VIA: docker exec -u git gitea-central-gitea-1 gitea admin user generate-access-token --username nirpa --scopes write:admin,write:user,write:repository --raw", "admin_login": "nirpa", - "admin_password": "FROM /opt/gitea-beta/.admin-creds (required: Gitea 1.27 token minting only works via basic auth + Sudo header)", + "admin_password": "FROM shre-cred: superadmin/granthi-link/granthi-prod-forge-admin (required: Gitea 1.27 token minting only works via basic auth + Sudo header). NEVER paste this into chat or a shell history.", "binds": [["127.0.0.1", 3042], ["100.111.127.127", 3042]], "test_mode": false, "rate_limit": { "enabled": true, - "trust_forwarded_for": false, + "trust_forwarded_for": true, + "trusted_proxies": ["100.107.37.98/32"], "rules": {"/v1/link": [5, 3600], "/v1/repos": [60, 3600]} } }