fix(readiness): /api/ready svarade 200 med en död motor i produktion #116

Merged
admin merged 1 commits from fix/readiness-fails-closed-on-broken-engine-20260925 into main 2026-09-25 12:42:43 +00:00
Owner

Vad som var fel (mätt, inte antaget)

Mätt live 2026-09-25 mot produktionsdeployen 0pt.app / api.0pt.app (container shxd6lepxuxfsjsp0ath3z1g-172514162615, server6, uppe 17,9 h, Docker-status healthy hela tiden):

GET /api/health -> HTTP/1.1 200 OK
  {"ok":false,"service":"0pt-web","db":"ok","queue":"not_configured",
   "engine":"error","stripe":"not_configured",
   "detail":{"engine":"This operation was aborted"}}

GET /api/ready  -> HTTP/1.1 200 OK
  {"ready":true,"service":"0pt-web","db":"ok","engine":"error",...}

ENGINE_URL pekade på http://0pt-engine:8000. Mätt inifrån containern:

engine host: http://0pt-engine:8000   creds-in-url: false
getent hosts 0pt-engine  -> ingen post
fetch ENGINE_URL/health  -> ERR fetch failed after 5069 ms

Och det finns ingen container vid namn 0pt-engine på någon av server5–server11.

Datamotorn — 0pt:s hela produkt — var alltså borta, och varje signal ovanför den var grön: Docker healthy, /api/health 200, /api/ready 200. ok:false i en 200-kropp är ingen signal; ingenting i kedjan läser kroppar, allt läser statuskoder och exitkoder.

Vad ändringen gör

isReady skilde tidigare bara på db.status === "ok". Den skillnad som saknades är inte konfigurerad vs ej konfigurerad utan frånvarande vs trasig:

status betydelse readiness
not_configured / not_integrated ingen bad om integrationen fortsatt ready — 0pt är byggt för att köra utan motor/Stripe/kö
error någon konfigurerade den och en riktig round trip mot den misslyckades just nu inte ready

En konfigurerad-men-död motor är inte en "valfri integration" längre. Någon har bett om den och den svarar inte.

Vad ändringen INTE gör

Ingenting i driften ändras i dag. Container-HEALTHCHECK pekar på /api/health (liveness), och Dockerfilen säger uttryckligen att en readiness-probe inte ska peka dit — det respekteras, Dockerfilen är orörd. Den här ändringen gör bara den ärliga ytan faktiskt ärlig, så att en yttre övervakning kan använda den.

Rekommendation som ligger utanför det här repot

Coolifys /api/health-probe för 0pt.app bör kompletteras med en uptime-övervakning mot /api/ready. Det är en driftkonfiguration, inte en kodändring, och den lämnas till Simon.

Verifiering

Regressionstest tillagt i tests/lib/health-checks.test.ts. Verifierat i båda riktningar:

  • mot den gamla isReady: 1 failed | 18 passed
  • mot den nya: 24 passed över health-checks + ready + health

npx eslint rent på de ändrade filerna. npx tsc --noEmit visar samma redan existerande fel som på main (tests/auth/*, tests/p0/decision-er-shadow.test.ts) — inga i de filer den här PR:en rör.

🤖 Generated with Claude Code

## Vad som var fel (mätt, inte antaget) Mätt live 2026-09-25 mot produktionsdeployen `0pt.app` / `api.0pt.app` (container `shxd6lepxuxfsjsp0ath3z1g-172514162615`, server6, uppe 17,9 h, Docker-status `healthy` hela tiden): ``` GET /api/health -> HTTP/1.1 200 OK {"ok":false,"service":"0pt-web","db":"ok","queue":"not_configured", "engine":"error","stripe":"not_configured", "detail":{"engine":"This operation was aborted"}} GET /api/ready -> HTTP/1.1 200 OK {"ready":true,"service":"0pt-web","db":"ok","engine":"error",...} ``` `ENGINE_URL` pekade på `http://0pt-engine:8000`. Mätt inifrån containern: ``` engine host: http://0pt-engine:8000 creds-in-url: false getent hosts 0pt-engine -> ingen post fetch ENGINE_URL/health -> ERR fetch failed after 5069 ms ``` Och det finns ingen container vid namn `0pt-engine` på någon av server5–server11. **Datamotorn — 0pt:s hela produkt — var alltså borta, och varje signal ovanför den var grön:** Docker `healthy`, `/api/health` 200, `/api/ready` 200. `ok:false` i en 200-kropp är ingen signal; ingenting i kedjan läser kroppar, allt läser statuskoder och exitkoder. ## Vad ändringen gör `isReady` skilde tidigare bara på `db.status === "ok"`. Den skillnad som saknades är inte *konfigurerad vs ej konfigurerad* utan **frånvarande vs trasig**: | status | betydelse | readiness | |---|---|---| | `not_configured` / `not_integrated` | ingen bad om integrationen | fortsatt ready — 0pt är byggt för att köra utan motor/Stripe/kö | | `error` | någon konfigurerade den **och** en riktig round trip mot den misslyckades just nu | **inte ready** | En konfigurerad-men-död motor är inte en "valfri integration" längre. Någon har bett om den och den svarar inte. ## Vad ändringen INTE gör Ingenting i driften ändras i dag. Container-`HEALTHCHECK` pekar på `/api/health` (liveness), och Dockerfilen säger uttryckligen att en readiness-probe inte ska peka dit — det respekteras, Dockerfilen är orörd. Den här ändringen gör bara den ärliga ytan faktiskt ärlig, så att en yttre övervakning kan använda den. ## Rekommendation som ligger utanför det här repot Coolifys `/api/health`-probe för `0pt.app` bör kompletteras med en uptime-övervakning mot `/api/ready`. Det är en driftkonfiguration, inte en kodändring, och den lämnas till Simon. ## Verifiering Regressionstest tillagt i `tests/lib/health-checks.test.ts`. Verifierat i båda riktningar: * mot den gamla `isReady`: `1 failed | 18 passed` * mot den nya: `24 passed` över `health-checks` + `ready` + `health` `npx eslint` rent på de ändrade filerna. `npx tsc --noEmit` visar samma redan existerande fel som på `main` (`tests/auth/*`, `tests/p0/decision-er-shadow.test.ts`) — inga i de filer den här PR:en rör. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
admin added 1 commit 2026-09-25 11:35:03 +00:00
fix(readiness): /api/ready svarade 200 med en död motor i produktion
CI (SIAX Cloud) / integration (push) Skipped
masterplan-lock / check (push) Successful in 6s
CI (SIAX Cloud) / security (push) Successful in 15s
masterplan-lock / check (pull_request) Successful in 4s
Security Scan (SIAX Cloud) / security (push) Successful in 27s
CI (SIAX Cloud) / security (pull_request) Successful in 23s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 24s
CI (SIAX Cloud) / quality (push) Successful in 45s
CI (SIAX Cloud) / integration (pull_request) Successful in 31s
CI (SIAX Cloud) / quality (pull_request) Successful in 40s
0062edbec3
Mätt live 2026-09-25 mot produktionsdeployen (0pt.app / api.0pt.app,
container shxd6lepxuxfsjsp0ath3z1g-172514162615 på server6, uppe 17,9 h,
Docker-status "healthy" hela tiden):

    GET /api/health -> HTTP/1.1 200 OK
      {"ok":false,"service":"0pt-web","db":"ok","queue":"not_configured",
       "engine":"error","stripe":"not_configured",
       "detail":{"engine":"This operation was aborted"}}

    GET /api/ready  -> HTTP/1.1 200 OK
      {"ready":true,"service":"0pt-web","db":"ok","engine":"error",...}

ENGINE_URL pekade på http://0pt-engine:8000. Mätt inifrån containern:
`getent hosts 0pt-engine` ger ingen post, och det finns ingen sådan
container på någon av server5-11. Ett direktanrop mot motorn misslyckas
efter ~5 s (DNS). Datamotorn — 0pt:s hela produkt — var alltså BORTA, och
samtliga signaler ovanför den var gröna: Docker healthy, /api/health 200,
/api/ready 200.

`ok:false` i en 200-kropp är ingen signal. Ingenting i kedjan läser
kroppar; allt läser statuskoder och exitkoder.

isReady skilde tidigare bara på "db ok". Den skillnad som saknades är inte
konfigurerad-vs-ej-konfigurerad utan FRÅNVARANDE-vs-TRASIG:

  * not_configured / not_integrated -> fortsatt ready. 0pt är byggt för att
    kunna köra utan motor, Stripe och kö (se .env.example).
  * error -> INTE ready. Statusen "error" betyder att någon medvetet
    konfigurerade beroendet och att en riktig round trip mot det just
    misslyckades. Det är inte längre en valfri integration.

Ändrar ingenting i driften i dag: container-HEALTHCHECK pekar på
/api/health (liveness) och Dockerfilen säger uttryckligen att en
readiness-probe inte ska peka dit. Den här ändringen gör bara att den
ärliga ytan faktiskt blir ärlig, så en yttre övervakning kan använda den.

Regressionstest tillagt; verifierat att det FALLER mot den gamla isReady
(1 failed | 18 passed) och passerar mot den nya (24 passed över
health-checks/ready/health).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CODEOWNERS rules requested review from sax3l 2026-09-25 11:35:03 +00:00
siax-bot approved these changes 2026-09-25 12:42:42 +00:00
siax-bot left a comment
Collaborator

Granskad och mergad av plattformssamordningen. Checkar grona (10 st), mergeable, inga rода eller pending vid mergetillfallet.

🤖 Generated with Claude Code

Granskad och mergad av plattformssamordningen. Checkar grona (10 st), mergeable, inga rода eller pending vid mergetillfallet. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
admin merged commit ec487746fd into main 2026-09-25 12:42:43 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/0pt#116