diff --git a/README.md b/README.md index b0118ea..86d318c 100644 --- a/README.md +++ b/README.md @@ -58,14 +58,25 @@ cd services/api && pip install -r requirements.txt && uvicorn orchestrator.main: (already committed, see [`Dockerfile`](Dockerfile)) plus [`.gitea/workflows/cd.yml`](.gitea/workflows/cd.yml) (renamed from `deploy.yml` 2026-08-10) that POSTs a restart to a Coolify app UUID on `COOLIFY_TOKEN` push. -- **Actually live right now:** the only running instance of `0pt.app` is still on **Vercel** +- ~~**Actually live right now:** the only running instance of `0pt.app` is still on **Vercel** (project `0pt`, scope *Simon Axelsson's projects*) — no Coolify app has been provisioned for this repo yet, so `deploy.yml`'s app UUID is a placeholder that fails the job on purpose until - someone fills it in. Flipping the config declares intent; it does not move traffic. See + someone fills it in. Flipping the config declares intent; it does not move traffic.~~ See [`docs/architecture/ARCHITECTURE.md`](docs/architecture/ARCHITECTURE.md) §5/§8 for the full "Vercel or fleet" state and what's still open (Coolify app provisioning + DNS cutover — a separate decision from this config change, since the live Vercel deployment is not being touched). +- **CORRECTED 2026-09-06 — the bullet above is no longer true. The Coolify deploy hook is LIVE.** + The repo secret `COOLIFY_TOKEN` exists (created 2026-08-31T11:34:34Z) and the repo Actions + variable `COOLIFY_APP_ID` holds a real 24-character UUID, **not** the + `TODO-no-coolify-app-provisioned-yet` literal. Both guard conditions in + [`.gitea/workflows/cd.yml`](.gitea/workflows/cd.yml) therefore pass. Measured on the push to + `main` at `1ff34410` (2026-09-06): job `Deploy to Coolify / deploy` (run 11695, job 26295) + finished **success** with `coolify deploy HTTP 200` in its log. **Every merge into `main` now + fires a real redeploy against `cloud.siax.io` — know what you are shipping before you merge.** + **Probed 2026-09-06 08:00 UTC:** `0pt.app` still answers from **Vercel** (`server: Vercel`, `x-vercel-id: arn1::…`) and returns **HTTP 402 `DEPLOYMENT_DISABLED` — "Payment required"** on both `/` and `/api/health`. So the public domain is *down*, DNS has **not** been cut over to Coolify, and the Coolify app — whatever state it is in — serves no `0pt.app` traffic. Two separate facts, both true at once: the deploy hook fires for real, and the product domain is dark behind an unpaid Vercel deployment. + Still not established: whether the Coolify app itself builds and starts — the deploy endpoint + returning 200 only means the request was accepted, not that a container came up healthy. - **Engine + DB + embeds** → one VPS via [`infra/docker-compose.yml`](infra/docker-compose.yml) (Postgres+pgvector, Redis, api, worker, NocoDB, Metabase, Caddy). - Env inventory: [`.env.example`](.env.example). - **Auth on `/api/0pt/*` is fail-closed**: with `AUTH_ENFORCE` unset the middleware diff --git a/docs/02-architecture.md b/docs/02-architecture.md index 69a392e..cd987e1 100644 --- a/docs/02-architecture.md +++ b/docs/02-architecture.md @@ -207,12 +207,26 @@ Flagged so it is not repeated: `src/services/quality-check-service.ts`, `src/ser > **SUPERSEDED 2026-08-11.** This section describes the original Vercel+Neon > hosting plan. `siax.config.json` flipped `deploy.target` from `"vercel"` to > `"coolify"` on 2026-08-09 to match every other SIAX Cloud OS repo — that -> decision supersedes the Vercel prescription below. The live instance is +> decision supersedes the Vercel prescription below. ~~The live instance is > **still actually running on Vercel today** (no Coolify app has been > provisioned yet — see `README.md`'s "Deploy" section and -> `docs/architecture/ARCHITECTURE.md` §5/§8 for the current, verified state); +> `docs/architecture/ARCHITECTURE.md` §5/§8 for the current, verified state)~~; > this section is kept for history, not as the current target. Do not read > "Vercel (Hobby/free)" below as still-current guidance. +> +> **CORRECTED 2026-09-06 — the struck sentence above is no longer true.** The Coolify +> deploy hook is live: repo secret `COOLIFY_TOKEN` exists (created 2026-08-31T11:34:34Z) +> and repo Actions variable `COOLIFY_APP_ID` holds a real 24-character UUID, not the +> `TODO-no-coolify-app-provisioned-yet` literal, so both guards in +> `.gitea/workflows/cd.yml` pass. On the push to `main` at `1ff34410` (2026-09-06) the +> `Deploy to Coolify / deploy` job finished **success** with `coolify deploy HTTP 200`. +> **Every merge into `main` fires a real redeploy against cloud.siax.io.** +> +> Probed 2026-09-06 08:00 UTC: `0pt.app` still answers from **Vercel** (`server: Vercel`) +> with **HTTP 402 `DEPLOYMENT_DISABLED`** on both `/` and `/api/health`. The public domain +> is therefore *down*, DNS has not been cut over, and the Coolify app serves no `0pt.app` +> traffic. Still unestablished: whether the Coolify app builds and starts at all — an +> accepted deploy request is not a healthy container. - **Vercel** (Hobby/free) — Next.js + custom domain `0pt.app`. - **One small VPS** (e.g. Hetzner ~€5/mo) running `docker-compose` (`infra/docker-compose.yml`): FastAPI, workers, NocoDB, Metabase, (Postgres or use Neon), optional Meilisearch later. Per-service managed platforms (Railway) get expensive once you have 4–5 always-on services; a single VPS + Vercel + R2 lands ≈ <€10/mo to start. diff --git a/docs/architecture/decisions/0001-deploy-target-coolify-not-vercel.md b/docs/architecture/decisions/0001-deploy-target-coolify-not-vercel.md index a7fb772..ca09bfe 100644 --- a/docs/architecture/decisions/0001-deploy-target-coolify-not-vercel.md +++ b/docs/architecture/decisions/0001-deploy-target-coolify-not-vercel.md @@ -27,6 +27,13 @@ Coolify app UUID on push to `main`) both exist and are committed. `cd.yml`'s `COOLIFY_APP_ID` is a literal placeholder that fails the job loudly on purpose (see the guard step) rather than posting to a bogus endpoint. The live instance of `0pt.app` is still served by Vercel. + + > **UPDATE 2026-09-06 (the consequence above has since been overtaken; the + > decision itself stands).** **CORRECTED 2026-09-06 — this is no longer true.** The Coolify deploy hook is LIVE: the repo secret `COOLIFY_TOKEN` exists (created 2026-08-31T11:34:34Z) and the repo Actions variable `COOLIFY_APP_ID` holds a real 24-character UUID, not the `TODO-no-coolify-app-provisioned-yet` literal. Both guard conditions in `.gitea/workflows/cd.yml` therefore pass, and the push to `main` at `1ff34410` (2026-09-06) ran `Deploy to Coolify / deploy` to **success** with `coolify deploy HTTP 200` in the job log. **Every merge into `main` now fires a real redeploy against cloud.siax.io.** What is still NOT verified: whether that Coolify app actually builds and serves, and whether `0pt.app` DNS points at it or still at Vercel — nobody has probed the running site. + > + > An ADR is a historical record, so the original consequence text is left + > intact above rather than rewritten — read it as "true when written + > 2026-08-09", not as current state. - Flipping the config was deliberately decoupled from the actual cutover: it states intent (BACKLOG P0-2 / P3-1 own the "provision the Coolify app, cut DNS, decommission Vercel" work, gated on a dump-before-write blocker per diff --git a/docs/compliance/GOLDEN-STANDARD-REPORT.md b/docs/compliance/GOLDEN-STANDARD-REPORT.md index 30ef03b..6de0bcf 100644 --- a/docs/compliance/GOLDEN-STANDARD-REPORT.md +++ b/docs/compliance/GOLDEN-STANDARD-REPORT.md @@ -56,7 +56,7 @@ | D1 | Container icke-root, multi-stage, utan tsx i prod | ✅ | Dockerfile: node:24-alpine, builder+runtime, `USER node`, `CMD next start` (ingen tsx) | | D2 | /health verifierar beroenden | ⚠️ | /api/health rapporterar db/queue lägen men alltid `ok:true` — liveness ej readiness; "alltid grönt för en döende instans" (ARCHITECTURE §6) | | D3 | CI grön på main | ✅ | Gitea Actions run 3759 success; deploy.yml röd men avsiktligt (guard) | -| D4 | Deploy till Coolify provisionerad | ❌ | Coolify-app ej provisionerad; deploy.yml placeholder-UUID (avsiktligt röd); node:null | +| D4 | Deploy till Coolify provisionerad | ⚠️ **(uppdaterad 2026-09-06, var ❌)** | Coolify-app ÄR provisionerad: repo-variabeln `COOLIFY_APP_ID` innehåller en riktig 24-teckens-UUID och repo-secreten `COOLIFY_TOKEN` finns (skapad 2026-08-31). Guarden i `cd.yml` passerar och deployen körde `coolify deploy HTTP 200` på push `1ff34410`. Kvarstår ⚠️ och inte ✅: probe 2026-09-06 08:00 UTC visar att `0pt.app` fortfarande svarar från **Vercel** med **HTTP 402 `DEPLOYMENT_DISABLED`** — publika domänen är nere, DNS är inte omlagd, och Coolify-appen serverar ingen `0pt.app`-trafik. Att webhooken accepteras (HTTP 200) betyder inte att en container kommer upp frisk | | D5 | Backup + testad restore | ❌ | Ingen backup, ingen DB i prod, restore aldrig testat (ARCHITECTURE §6) | | D6 | Loggning/observabilitet | ⚠️ | Ingen strukturerad loggning/OTel; endast console.warn (ARCHITECTURE §6) | | D7 | Infisical-projekt + token tillgängligt för denna session | ➖ | **Blockerare:** ingen Infisical-token tillhandahållen — projekt/secret-bootstrap kan inte verifieras (se SLUTRAPPORT) | diff --git a/docs/compliance/INVENTORY.md b/docs/compliance/INVENTORY.md index ccb0a57..e18ce0a 100644 --- a/docs/compliance/INVENTORY.md +++ b/docs/compliance/INVENTORY.md @@ -114,7 +114,7 @@ v0-datahub, prt-* etc.) finns i 0pt. | /api/health | 200, `{"ok":true,"db":"not_configured","queue":"not_configured"}` | live-probe 2026-08-10 | | /api/0pt (anonym) | **200 anonymt** — middleware fail-closed verkar INTE köra i prod (lucka S1) | live-probe 2026-08-10 | | /api/orders (anonym) | **200 anonymt** — inget skyddat (lucka S3) | live-probe 2026-08-10 | -| CI (Gitea Actions) | senaste ci.yml på main: **success** (run 3759, 2026-08-09). deploy.yml: röd men **avsiktligt** (guard: placeholder-app-ID). 48 runs totalt | Gitea API `/actions/runs` | +| CI (Gitea Actions) | senaste ci.yml på main: **success** (run 3759, 2026-08-09). ~~deploy.yml: röd men **avsiktligt** (guard: placeholder-app-ID)~~ **korrigerat 2026-09-06:** cd.yml är **grön** och deployar på riktigt — `COOLIFY_APP_ID` är en riktig UUID, guarden passerar, `coolify deploy HTTP 200` (run 11695, jobb 26295, head `1ff34410`). 48 runs totalt vid ursprungsmätningen | Gitea API `/actions/runs`, `/actions/variables`, `/actions/secrets` | | Secrets | Inga hårdkodade hemligheter hittade (grep-skannat). **Infisical ej inkopplat** — inga referenser i repot | grep + ARCHITECTURE §5 | | Backup | Ingen (ingen DB i prod att backa upp) | ARCHITECTURE §6 | diff --git a/docs/runbook/incident.md b/docs/runbook/incident.md index a442e9f..5adac4d 100644 --- a/docs/runbook/incident.md +++ b/docs/runbook/incident.md @@ -14,7 +14,7 @@ |---|---|---| | `/api/health` grön men `/api/orders` tom | Ingen DB i prod (in-memory-store) | Sätt `DATABASE_URL`; se BACKLOG P3-4 | | `/api/0pt/*` svarar 200 anonymt | Middleware körs inte på Vercel-deployen (lucka S1) | Rotorsaksanalys; verifiera 401 anonymt före "skyddad" | -| deploy.yml-röd på main | Guard: placeholder `COOLIFY_APP_ID` (avsiktligt) | Provisionera Coolify-app + fyll UUID | +| ~~deploy.yml-röd på main~~ | ~~Guard: placeholder `COOLIFY_APP_ID` (avsiktligt)~~ **INAKTUELL 2026-09-06** — guarden passerar numera; `COOLIFY_APP_ID` är en riktig UUID och `COOLIFY_TOKEN` finns | Rätt symtom i dag är det omvända: **varje merge till `main` utlöser en riktig omdeploy** mot cloud.siax.io (verifierat: push `1ff34410`, jobb `Deploy to Coolify / deploy` = success, `coolify deploy HTTP 200`). Vet vad du deployar innan du mergar | | Test `*.realinfra.test.ts` skip | ST0RE inte nåbar från CI | Inte en incident — förväntat beteende | | Trivy-fynd på `services/scrapers/*` | Medvetet behållen bypass-stack | Läs GOLDEN-STANDARD-REPORT C6; triage, radera ej |