6e2d794130
- @app/storage med MockStorage + AwsStorage delas mellan API och worker - Workerns readUrl() ger presignerad S3-URL i aws-läge (fixar mock-s3 404) - sync-env-from-ssm.py hämtar /cibello/prod/* och skriver .env; first-deploy.sh kör det i prod - /readyz returnerar 503 om app.aamos.healthCheck() misslyckas - docs/SECRETS.md med rotations- och SSM-regler
78 lines
5.2 KiB
Markdown
78 lines
5.2 KiB
Markdown
# Cibello — HANDOFF / DEPLOY-STATE
|
|
Cibello = AI-matapp (recept + bildscanning av kylskåp/etiketter/kvitto/utgångsdatum).
|
|
pnpm/turbo-monorepo: Fastify+Drizzle+BullMQ (apps/api, apps/worker), Expo (apps/mobile).
|
|
Roller: OpenClaw bygger. Extern granskare ("Sven", i Johans chatt) verifierar + ger promptar.
|
|
|
|
## Var saker finns
|
|
- Prod-server (EC2): 13.48.40.1, repo /opt/cibello-platform
|
|
- OpenClaw-workspace: cibello-work/cibello
|
|
- Region: eu-north-1
|
|
- SSM: `/cibello/prod/*` (enda sanningskälla för hemligheter)
|
|
- `.env` på servern härleds ur SSM via `infrastructure/deployment/sync-env-from-ssm.py`
|
|
|
|
## Infra (uppe)
|
|
- EIP 13.48.40.1 → api.cibello.app + admin.cibello.app
|
|
- CloudFront → cibello.app (marknadssajt, S3 cibello-web)
|
|
- RDS cibello-prod-db (privat subnät, krypterad, SSL krävs: sslmode=require)
|
|
- S3: cibello-production (app + training/cibello/-prefix), cibello-web (sajt)
|
|
- Route53 zon cibello.app. Mail: Mailu mail.aamos.systems (hello@cibello.app)
|
|
- Caddy reverse proxy på prod-servern: TLS (Let's Encrypt) → 127.0.0.1:4000
|
|
|
|
## AI-modell
|
|
- AAMOS_MODE=gemini. GeminiAamosClient täcker scan/etikett/kvitto/utgång.
|
|
- Shadow-capture skriver träningspar → s3://cibello-production/training/cibello/. Insamling PÅ
|
|
för admin/beta (imageTraining=true); publika användare följer samtycke (gate ej byggd än).
|
|
- **Global Gemini dagsbudget:** `GEMINI_DAILY_BUDGET_USD=25`. Budget-check sker före varje
|
|
AI-jobb i workern; vid överskridande stoppas jobbet, `gemini:daily:budget:alarm:<datum>`
|
|
sätts i Redis, och ops-summary får `larm` + wall-tile `AI-budget` i `crit`.
|
|
- **Trial efter verifiering:** Family 7-dagars trial startas först när användaren verifierar
|
|
e-posten. En trial per verifierad e-post. Trial-rättigheter räknas mot samma
|
|
`ai_usage_counters` som övriga planer.
|
|
|
|
## Hemligheter
|
|
- SSM /cibello/prod/* (SecureString).
|
|
- **ROTERADE (Grupp A):** JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, ENTITLEMENT_SIGNING_SECRET,
|
|
db-password (cibello_admin). Både RDS och SSM uppdaterade; appen verifierad med nya värden.
|
|
- **VÄNTAR PÅ JOHAN (Grupp B):**
|
|
- Egen Cibello-Gemini-nyckel (ersätt återanvänd /openclaw/-nyckel).
|
|
- SMTP-pass för hello@cibello.app.
|
|
|
|
## KLART
|
|
- [x] **Skarpt bildflöde:** delad lagringsmodul `@app/storage` (MockStorage + AwsStorage) används av både API och worker. Workerns `readUrl()` ger nu riktig presignerad S3-URL i `aws`-läge istället för `/v1/mock-s3/...`.
|
|
- [x] **SSM = enda sanningskälla:** `infrastructure/deployment/sync-env-from-ssm.py` hämtar `/cibello/prod/*` och skriver `/opt/cibello-platform/.env`. `first-deploy.sh` kör detta i produktion.
|
|
- [x] **Gemini-nyckel hälsokoll:** `/readyz` returnerar 503 om `app.aamos.healthCheck()` misslyckas (t.ex. ogiltig Gemini-nyckel).
|
|
- [x] Dokumenterat i `docs/SECRETS.md`.
|
|
- [x] FAS 1 byggt: GeminiAamosClient + shadow-capture.ts + scans-integration.
|
|
- [x] Gemini som committat prod-läge (AAMOS_MODE=gemini).
|
|
- [x] Hermetiska eval-fixtures committade.
|
|
- [x] RDS SSL fixat vid källan: `packages/database/src/client.ts` strippar `sslmode` från URL och skapar explicit `ssl`-objekt från `DATABASE_CA_CERT` eller `rejectUnauthorized: false`.
|
|
- [x] `first-deploy.sh` uppdaterad för RDS-SSL + `DATABASE_CA_CERT` + `pg_dump` 16.
|
|
- [x] Vitest-konfig för `apps/api` och `apps/worker` laddar root `.env` så tester hittar `TEST_DATABASE_URL` även i produktion.
|
|
- [x] Prod-server: Node 22, pnpm, Redis, postgresql-client-16, Caddy.
|
|
- [x] `DEPLOY_MODE=production REQUIRE_REAL=1 ./infrastructure/deployment/first-deploy.sh` → **ALLA GRINDAR GRÖNA**.
|
|
- [x] `https://api.cibello.app/healthz` och `/readyz` svarar.
|
|
- [x] Röktest via HTTPS: registrering + token + recept fungerar.
|
|
- [x] JWT- + DB-hemligheter roterade och verifierade.
|
|
- [x] **Pre-launch cost-safeguards (bränn-spärr):**
|
|
- `GEMINI_DAILY_BUDGET_USD=25` i `.env` och `.env.example`.
|
|
- Budget-check före bildhämtning i `GeminiAamosClient` (`packages/ai-contracts/src/gemini.ts`).
|
|
- `BudgetStore.raiseBudgetAlarm()` + `RedisBudgetStore`-implementation.
|
|
- Ops-summary visar `AI-budget` wall-tile och `larm`-block vid överskridande.
|
|
- Trial startas först vid e-postverifiering (`apps/api/src/routes/auth.ts`).
|
|
- [x] **Verifierat i produktion:**
|
|
- Gratisanvändare blockeras på 11:e AI-scanen (HTTP 429 `QUOTA_EXCEEDED`).
|
|
- AI-jobb stoppas när `GEMINI_DAILY_BUDGET_USD` sätts till 0.001 USD.
|
|
- `/ops/v1/summary` visar `AI-budget` tile och `budget_exceeded`-larm i `crit`.
|
|
|
|
## PENDING (i ordning)
|
|
1. **Egen Gemini-nyckel + SMTP-pass** — Johan levererar värden lokalt; claw skriver till SSM/.env.
|
|
- Nuvarande `.env` innehåller fortfarande den delade `/openclaw`-Gemini-nyckeln.
|
|
2. **Skarpt end-to-end-test** när Grupp B är på plats: riktig scan → S3 → Gemini → resultat + träningspar i `s3://cibello-production/training/cibello/`.
|
|
3. **End-user samtyckes-gate** för bildträning + in-app allergen-disclaimer före publik lansering.
|
|
4. **Säkerhetsgranskning**: öppna portar, Caddy-konfig, IAM, S3-bucket-policy.
|
|
5. **Övervakning/larm**: logga fel, sentry, health-check alert.
|
|
|
|
## Så här återupptar en färsk session
|
|
Läs denna fil + `git log --oneline -8` + senaste prompt från Sven. Arbeta stramt. Echo ALDRIG
|
|
.env/hemligheter (`set +x`, variabler, aldrig `cat .env`). Uppdatera denna fil innan sessionen tar slut.
|