p24-infra — Strategia Rozwoju 2026

Synteza analizy krytycznej · Architektura docelowa · Plan wdrożenia Wersja: 2026-06-27


TL;DR — Co teraz robić

PriorytetDziałanieCzasEfekt
🔴 P1Uruchom restore drill MongoDB4 hZamknięcie 4-miesięcznego długu bezpieczeństwa
🔴 P1Dodaj nightly n8n workflow export → git2 hUtrata definitons = niemożliwa
🔴 P1Zainstaluj node_exporter na bms-1/2/31 dMTTD dla prod z 24 h → 2 min
🟡 P1Uruchom bms-3 jako 3. node agentów1 dPojemność z 7 → 11 agentów bez nowego serwera
🟡 P2Skróć notifikacje Discord (tylko zmiana stanu)2 hKoniec spam-fatigeu
🟡 P2Dodaj dev_r_ops_events (change log serwera)1 dKorelacja alertów z operacjami możliwa
🟡 P2Fix socat-supabase watchdog na bms-43 hKoniec cascade-failure przez tunel
🟢 P2Extend kolejkę: cost columns + billing tier3 dGotowość na SaaS billing
🟢 P3DuckDB reporting pipeline (ETL nightly)3 dRaporty bez obciążania Supabase
🟢 P3SaaS AI metering service (ai-worker)2 tygBrandPilot AI queuing i billing

1. Krytyczny przegląd procedur

1.1 Audit zdarzeń i zmian — stan obecny 🟡

Co działa:

  • docs/secrets-rotation-log.md — jedyny solidny log zmian w systemie (timestampowane wpisy + per-consumer potwierdzenie)
  • Git commit history — pełna historia kodu i konfiguracji
  • audit.runs w Supabase — historia wykonań audit-engine
  • GH issue history — kontekst incydentów z śladem rozumowania agentów

Krytyczne luki:

Brak ustrukturyzowanego change logu serwera. Jeśli ktoś uruchamia docker restart n8n przez SSH lub edytuje /opt/p24-infra/monitoring/.env bezpośrednio — ta akcja nie pozostawia żadnego śladu w żadnym systemie. Brak auditd na węzłach VPS, brak bazy operacji ręcznych.

Niemożliwa korelacja alertów z operacjami. Alert o 03:15, restart kontenera o 03:10 — połączenie tych faktów wymaga ręcznego zestawienia czasów w Discord, komentarzach GitHub Issues i docker logs. Nie ma wspólnego event store.

Log rotacji ma lukę weryfikacyjną. Wpisy z “Confirmed in sync” nie mają timestamp weryfikacji każdego konsumenta. Wzorzec “partial — DEFERRED” + późniejszy wpis “Complete” pojawia się wielokrotnie — log może zawierać otwarte wpisy wyglądające jak zamknięte.

Rekomendacja — dodać tabelę dev_r_ops_events:

CREATE TABLE dev_r_ops_events (
  id          BIGSERIAL PRIMARY KEY,
  occurred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  actor       TEXT NOT NULL,           -- 'claude-runner@bms-4', 'hourly-triage', 'human:radieu'
  action_type TEXT NOT NULL,           -- 'container_restart', 'config_reload', 'secret_deploy'
  target      TEXT NOT NULL,           -- 'monitoring-n8n-1', 'secrets/monitoring.env.sops'
  server_node TEXT,                    -- 'bms-4', 'vps-i1'
  outcome     TEXT NOT NULL,           -- 'success', 'failure', 'partial'
  gh_issue_id INT,                     -- powiązany issue jeśli istnieje
  notes       TEXT
);

Hourly triage, Tier 1 auto-fix i health-check.yml piszą do tej tabeli na każdym działaniu. Grafana ma timeline view. Korelacja alertów z operacjami staje się trywialna.


1.2 Monitorowanie — krytyczna ocena 🟡

4-warstwowy system jest komplementarny, nie redundantny — ale ma jeden poważny błąd projektowy:

WarstwaFunkcjaProblem
Prometheus (ciągły)Metryki progowe✅ Działa, 22 pliki reguł
GitHub Actions co 2hHTTP probe z zewnątrz⚠️ Spamuje Discord przy każdym uruchomieniu (12×/dobę)
Nightly AI triage 00:30 UTC11-fazowe sprawdzenie SSH⚠️ Pass/fail nie jako metryka Prometheus — historia gubi się
Hourly AI triageKlasyfikacja issues⚠️ Gdy bms-4 pada — tier 4 znika bez powiadomienia

MTTD dla awarii produkcji — porównanie:

Serwer / usługaMTTD (obecnie)MTTD (po poprawkach)
vps-i1 kontener crash30 s30 s (bez zmian)
vps-i1 host down2 h (health-check.yml)2 h (bez zmian)
bms-1 dysk/RAM24 h (nightly triage SSH)2 min (node_exporter + Prometheus)
bms-2/3 MongoDB24 h (nightly triage)2 min (po node_exporter)
WAHA sesja degradacjaBrak metryki5 min (po blackbox probe)

Naprawy priorytetowe:

  1. node_exporter na bms-1, bms-2, bms-3 — Ansible role, 1 dzień pracy
  2. Prometheus gauge p24_nightly_triage_result{phase, result} — push po każdym runie
  3. health-check.yml — Discord tylko przy zmianie stanu (2 h pracy, nie tydzień)
  4. Thanos upload alert: thanos_objstore_bucket_last_successful_upload_seconds_ago > 7200

1.3 Playbooki — ocena jakości 🟡

108 playbooki = dobre pokrycie, ale problemy strukturalne:

  • ~40% to rotacje credentiali (jeden plik na typ klucza). Razem z credential-rotation.yml (automatyka) te pliki są fallback manualnym — warto skonsolidować do jednego “manual-rotation-fallback.md” + wyjątki per-usługa.
  • Brak last_verified date w żadnym playbooku — nie wiadomo które są aktualne po decommission Infisical CE, usunięciu claude-proxy, włączeniu ufw na bms-2/3.
  • infra_docs_check sprawdza czy playbook istnieje, nie czy jest aktualny.

Potwierdzone brakujące playbooki (krytyczne):

Brakujący playbookRyzyko
disaster-recovery.mdBrak DR runbooka narusza infrastructure-standard §4
bms1-total-failure.md24 kontenery prod, brak hot standby, brak procedury
mongodb-rs0-divergence.mdSplit-brain + data divergence podczas partycji sieci
vps-i1-rebuild.mdCałkowita utrata monitoring stack — jak odbudować < 30 min
pinbox24-rollback.mdRollback kontenera v42 → v41 na bms-1
supabase-project-suspended.mdPlatforma zależy od Supabase — co gdy projekt zawieszony?
loki-retention-setup.mdRetencja Loki niezdefiniowana — nigdy nie skonfigurowana
agents-capacity-exhausted.mdWszystkie 4 sloty bms-4 zajęte + P1 issue wymaga agenta

1.4 Samoleczenie — luki mechanizmów 🟡

Tier 2 (AI-Dev spawning) nie ma idempotency guard. Jeśli hourly triage odpala się dwukrotnie dla tego samego otwartego issue (np. issue nie zamknięte gdy następna godzina uderza), można dostać 2 agentów pracujących na tym samym zadaniu. Fix: dodać label ai-dev-spawned na issue przed spawnem, sprawdzać w triage.

Playwright OAuth re-auth detection — skrypt Playwright re-authu uruchamia się reagując na awarie SSH. Gdy Playwright fail — Discord alert. Ale brak automatycznej detekcji, że “Playwright uruchomił się i zawiódł po raz 2.” Efektywnie: ludzki tier eskalacji jest wykrywany przez ludzkie oczy, nie przez automat.

n8n-OOM masking: health-check.yml restartuje n8n co 2h jeśli jest crashnięty. Jeśli n8n crashuje co 25 min z OOM — restart się “udaje”, leci kolejny crash. OOM jest maskowany przez auto-restart. Fix: alert na pattern n8n_restart_count > 3 in 6h → wymuś diagnozę zamiast restart.


2. Analiza kolejki — decyzja architektoniczna

2.1 Co tak naprawdę mamy

Po analizie kodu (infra-src/meta-dispatcher/, queue-dispatcher-loop.py, spawn-worker.sh):

CF Worker dispatcher + Supabase dev_r_worker_queue to zaawansowany system kolejkowania — nie uproszczony hack. Zawiera:

  • Wave planning z topologicznym sortowaniem (algorytm Kahn) → zapobiega race condition na tych samych plikach
  • Role classification (classify.ts) — dekoupled od dispatchu
  • Server affinity + RAM-aware spawn (systemd-run --scope MemoryMax=)
  • Distributed lock via partial unique index na dev_r_orchestrator_runs
  • Heartbeat tracking (60s curl PATCH) — detekcja stallujących agentów
  • Spawn_failures vs. retry_count separacja
  • Night-task time gating (20:00–02:59 UTC)
  • Dedup guards

Wniosek: nie zastępować. Rozszerzyć.

RabbitMQ — decommissioned za brak konsumentów. BullMQ — Redis na bms-4 jest SPOF dla n8n i nie nadaje się na drugi backend. Temporal — overkill. CF Queues — beta.

Wystarczy: dodać kolumny cost metering + billing tier + SaaS job types + bms-3 jako 3. dispatch node.

2.2 Plan rozszerzenia kolejki

Faza 1 — Cost attribution (2 dni):

-- Dodać do dev_r_worker_queue:
ALTER TABLE dev_r_worker_queue
  ADD COLUMN client_id       TEXT,
  ADD COLUMN project_id      TEXT,
  ADD COLUMN billing_tier    TEXT NOT NULL DEFAULT 'internal'
    CHECK (billing_tier IN ('client-paid', 'client-free', 'internal')),
  ADD COLUMN tokens_in       INTEGER,
  ADD COLUMN tokens_out      INTEGER,
  ADD COLUMN cost_usd        NUMERIC(10,6),
  ADD COLUMN model_used      TEXT;

Workers piszą token_tick events przez istniejący heartbeat curl — ten sam mechanizm, nowy endpoint.

Faza 2 — Priority tiers dla SaaS (1 dzień):

// W classify.ts — computePriority():
const tierAdj = billingTier === 'client-paid' ? -20
              : billingTier === 'client-free' ? -10
              : 0;
return waveNumber * 10 + labelAdj + sizeAdj + tierAdj;

Dispatcher ORDER BY priority ASC → client-paid jobs wychodzą pierwsze.

Faza 3 — Skala do 12 agentów (1 dzień):

bms-3 ma 8 vCPU / 32 GB RAM — większość zajmowana przez MongoDB PRIMARY (~21 GB) i staging (10 kontenerów, ~6 GB). Dostępne headroom: ~4 GB RAM i ~2 vCPU — wystarczy na 3-4 lekkich agentów.

# Na bms-3: zainstalować claude-runner + spawn-worker.sh
# Dodać do dev_r_server_capacity:
INSERT INTO dev_r_server_capacity VALUES
  ('bms-3', '51.68.155.224', 3, 6, 2, 'claude-runner');

Dispatcher iteruje SERVERS z env — to zmiana konfiguracyjna, nie code change.

Faza 4 — Visibility Grafana (1 dzień):

# queue-exporter/app.py — nowe metryki:
P24_JOB_COST = Gauge('p24_job_cost_usd_total', 'Cost per client', ['client_id', 'project_id'])
P24_AGENTS_ACTIVE = Gauge('p24_agents_active', 'Active agents per server', ['server_node', 'weight'])
P24_QUEUE_BY_TIER = Gauge('p24_queue_depth_by_tier', 'Queue depth by billing tier', ['billing_tier'])

Docelowa architektura kolejki (po rozszerzeniu):

ENQUEUE (CF Worker — bez zmian oprócz nowych kolumn billing):
  SaaS Apps / n8n → POST /queue-issue → Supabase dev_r_worker_queue
                    wave planning + role classify + billing_tier + priority

DISPATCH (Python, cron co 2 min, na każdym serwerze):
  ├─ bms-4  (54.36.123.110) — max 6 slotów: n8n + 4-6 agentów
  ├─ bms-3  (51.68.155.224) — max 3 sloty: nowy node        [NOWY]
  └─ vps-i1 (217.154.82.162) — max 2-3 sloty: lekkie taski

EXECUTION:
  spawn-worker.sh → claude -p
  Heartbeat 60s → PATCH status + token_tick events

CAPACITY TOTAL: ~11-12 równoległych agentów bez nowego serwera

Uwaga: Jeśli bms-3 CPU okaże się niewystarczający (MongoDB PRIMARY + staging + agenty) → wtedy zakup nowego serwera. Testować pod obciążeniem przez 2 tygodnie przed decyzją o bms-5.


3. Architektura SaaS AI Metering

3.1 Pozycjonowanie

Nowy serwis ai-worker jest odrębny od CF Worker dispatcha (który obsługuje dev-issues/infra taski). Inne semantyki: sub-sekundowa admisja, auth per-project, billing, różne typy job.

Client Apps (BrandPilot, Art Agency, future SaaS)
    │
    │  POST /ai/jobs  (X-AI-API-Key header)
    ▼
Supabase Edge Function (admission layer):
  1. Weryfikacja klucza API → resolve project_id, client_id
  2. Rate limit check (ai_rate_limits)
  3. Budget check (ai_usage month aggregate)
  4. INSERT ai_jobs
  5. Redis LPUSH → BullMQ queue notification
  Returns: {job_id, status: "queued"}
    │
    ▼
BullMQ queues (Redis bms-4):
  ai:strategy     — concurrency 1  (Claude Opus, 5-min timeout)
  ai:article      — concurrency 3  (Claude Sonnet, 2-min timeout)
  ai:script       — concurrency 5  (Claude Sonnet, 1-min timeout)
  ai:heygen       — concurrency 10 (async poll, near-instant)
  ai:batch        — concurrency 3  (Claude Sonnet, 2-min per item)
  ai:analysis     — concurrency 2  (Playwright + Claude, 10-min timeout)
    │
    ▼
FastAPI Worker Service (bms-4 :8200):
  1. Claim job (SELECT FOR UPDATE SKIP LOCKED z ai_jobs)
  2. Call AI API (Anthropic/HeyGen/Playwright)
  3. Capture token usage z API response
  4. Upload wynik → Wasabi ai-results/{project_id}/{job_id}
  5. INSERT ai_usage (tokens, cost_usd)
  6. UPDATE ai_rate_limits (counters)
  7. Fire webhook do klienta
  8. Log events → ai_job_events
    │
    ▼
Klient: webhook lub polling GET /ai/jobs/:id

3.2 Typy zadań i timeouty

Job typeModelTimeoutRetryDelivery
marketing_strategyclaude-opus-4-85 minWasabi PDF
articleclaude-sonnet-4-62 minWasabi MD + HTML
video_scriptclaude-sonnet-4-61 minWasabi MD
heygen_videoheygen-v2Submit: 30 s / Poll: 30 minWasabi MP4 URL
batch_articlesclaude-sonnet-4-62 min/elemWasabi ZIP
competitive_analysisclaude-sonnet-4-610 minWasabi PDF

3.3 Kalkulacja kosztów

# Ceny modeli (USD per 1M tokenów):
MODELS = {
  'claude-opus-4-8':   {'input': 15.00, 'output': 75.00},
  'claude-sonnet-4-6': {'input':  3.00, 'output': 15.00},
  'claude-haiku-3-5':  {'input':  0.80, 'output':  4.00},
  'heygen-v2':         {'flat_per_call': 0.30},  # ~$0.30-0.50 za wideo
}
 
# W workerze po każdym call do Claude API:
usage = message.usage
cost_usd = (usage.input_tokens / 1_000_000)  * model['input']  \
         + (usage.output_tokens / 1_000_000) * model['output']

3.4 Kluczowe tabele (DDL)

Pełne DDL w osobnym pliku: supabase/migrations/048_ai_job_queue.sql

Podsumowanie tabel:

  • ai_models — rejestr modeli z kosztami per 1M tokenów
  • ai_jobs — kolejka zadań z maszyną stanów (queued → processing → completed/failed/awaiting_external)
  • ai_job_events — append-only log zdarzeń per job (submitted, claimed, started, completed, failed, webhook_sent)
  • ai_usage — jeden wiersz per completed job z tokenami i cost_usd (billing source of truth)
  • ai_rate_limits — limity per projekt/klient z atomowymi counterami

3.5 2-tygodniowy plan MVP (BrandPilot)

Tydzień 1 (równolegle):
  [A] Migration 048: DDL ai_jobs, ai_usage, ai_models, ai_rate_limits
  [B] Scaffold ai-worker (FastAPI + BullMQ) na bms-4 :8200 + Traefik route
  [C] Extend queue-exporter: dodaj ai_jobs do QUEUES + 3 nowe Gauge

  [D] Claude article worker: claim → Anthropic API → upload MD → Wasabi → done
  [E] Edge Function: POST /ai/jobs (admission + rate limit + insert + Redis notify)
  [F] Edge Function: GET /ai/jobs/:id (status polling)

Tydzień 2:
  [G] Cost recording: INSERT ai_usage po każdym Claude call (potrzebuje A+D)
  [H] Rate limiting w Edge Function (potrzebuje A+E)
  [I] Webhook delivery z workera (potrzebuje D)
  [J] Integracja BrandPilot: zastąp bezpośrednie Anthropic calls przez POST /ai/jobs
  [K] Grafana dashboard: queue depth + cost panels (potrzebuje C+G)
  [L] Migration 049: ai_api_keys + provisioning dla BrandPilot

Human-action (GH issues, nie blokują):
  [H1] HeyGen API key → secrets/n8n-bms4.env.sops
  [H2] Zatwierdzenie Traefik route dla :8200

4. Analiza pojemności — plan sprzętowy

4.1 Obecne obciążenie (podstawa planowania)

SerwerRAM wolne (szacunek)CPU headroomRola
vps-i1~1 GBminimalNA GRANICY — nie dodawać nic
vps-h1~5 GBmoderateFrozen — WAHA only
bms-1~10 GBmoderatePinbox24 prod — nie dotykać
bms-2~26 GBmoderateMongoDB rs0 PRIMARY (voting member, priority 1) — brak agentów
bms-3~4 GBtightMongoDB rs0 SECONDARY (21.7 GB) + staging
bms-4~26 GBmoderaten8n + 4 agenty + Redis

4.2 Wymagania rozbudowy

KomponentRAMCPU burstGdzie
Playwright × 42.5–3.5 GB4 vCPUbms-4
SaaS AI worker + BullMQ1–3 GB5 vCPUbms-4
4 nowe agenty na bms-31.5 GB2 vCPUbms-3
ai-worker serwis FastAPI0.3 GBminimalbms-4

bms-4 po rozbudowie: ~13 GB / 32 GB RAM (40%) — OK
bms-4 CPU burst: ~14 vCPU vs. 8 fizycznych — potencjalna contention

4.3 Decyzja sprzętowa

Etap 1 (teraz, 0 PLN):
  → Uruchom Playwright × 4 + SaaS microservices na bms-4
  → Uruchom 3-4 dodatkowych agentów na bms-3
  → Monitoruj CPU bms-4 pod obciążeniem przez 2 tygodnie

Etap 2 (jeśli CPU bms-4 saturuje się):
  → Zakup OVH Kimsufi ECO-4 (8 vCPU, 32 GB SSD) ~€60-70/mies
  → Lub OVH Rise-3 (16 vCPU, 64 GB NVMe) ~€140-160/mies (headroom na lata)
  → Dedykowany bms-5 jako "agent farm + SaaS overflow"

Docelowy split pojemności (Etap 2):
  bms-4: n8n + WAHA + Playwright × 4 + SaaS microservices + 4 agenty
  bms-3: MongoDB PRIMARY + staging + 3-4 agenty (jeśli CPU pozwala)
  bms-2: MongoDB rs0 PRIMARY (voting, brak agentów — nie obciążać)
  bms-5: 8 agentów (dedykowany)
  vps-i1: monitoring + 2-3 agenty
  TOTAL: 21-27 równoległych agentów

4.4 GPU — rekomendacja

Nie kupować dedykowanego serwera GPU.

Workloady AI (Whisper, SDXL, embeddings) są burstowe i nieciągłe. RunPod Serverless pokrywa potrzeby:

Use caseProviderKoszt/mies
Whisper (transkrypcja)RunPod Serverless A10G~$10
SDXL (generacja obrazów)RunPod Spot RTX 4090~$8
32B LLM (raporty audit)RunPod A100 80GB~$160 max
Łącznie$10-160 zmienny

Architektura nightly GPU batch już udokumentowana w docs/ai-batch-gpu-operations.md. PR #583 gotowy — uruchomić gdy pojawi się pierwszy use case.

4.5 MongoDB — kiedy skalować

TriggerAkcjaKiedy
mongod RSS na bms-3 > 26 GBPlanuj migrację do serwera 64 GBMonitoruj miesięcznie
Read QPS > 500/sDodaj read replica (nowy węzeł) — bms-2 jest już full voting memberNa demand
Single collection > 100 GBRozważ shardingNie teraz

Teraz: Przenieś Pinbox24 staging z bms-3 na bms-4 → wolni ~3-4 GB RAM dla MongoDB na bms-3.


5. Reporting — pipeline oparty na plikach

5.1 Architektura (DuckDB + Parquet na Wasabi)

Dlaczego DuckDB: Zero nowego serwera. Działa jako biblioteka Python. Czyta Parquet bezpośrednio z S3 przez httpfs. Supabase dostaje tylko bounded SELECT raz na dobę. Storage: ~180 MB/rok, koszt Wasabi < $0.002/mies.

Nightly ETL (01:00 UTC, cron na vps-i1):
  scripts/nightly-etl/
    export_supabase.py    → dev_r_services, agent_tasks, ai_usage, incidents
    export_prometheus.py  → metryki kosztów, uptime, alert history (Thanos Query API)
    export_github.py      → issues, PRs, resolution times
    export_n8n.py         → execution history (SSH + psql na bms-4)
    export_atrax.py       → p24_gps_daily_stats, p24_driver_ecodriving_daily,
                             p24_atrax_drivers_daily (+ anomalie paliwowe, patrz #6138)
    run_etl.sh            → orchestruje wszystko, push metric do pushgateway
                         → Wasabi: reporting/{table}/{YYYY-MM-DD}.parquet
                         → Wasabi: reporting/atrax/{table}/{YYYY-MM-DD}.parquet
Report Query API (FastAPI sidecar vps-i1 :9230):
  GET /query?sql=SELECT... → DuckDB query na S3 Parquet → JSON
  Grafana "Infinity" datasource → bez pluginu → wyniki w dashboardzie
Miesięczny raport PDF (1. każdego miesiąca):
  export_monthly_billing.py → DuckDB aggregation → Jinja2 → pdf-service :8100 → Wasabi → email Mailgun
  (reuse 100% z report_scheduler.py — tylko swap fetch_cars() → duck_query())

5.2 Eksportowane dane

ŹródłoTabele/metrykiRetencja Parquet
Supabaseagent_tasks, audit.runs, incidents, dev_r_services, ai_usage2 lata
Prometheus/Thanoskoszty, uptime, alert history1 rok
GitHubissues, PRs, resolutionsbezterminowo
n8nexecutions, error rate1 rok
secrets-rotation-log.mdparsowany Markdown → JSONbezterminowo
Atrax (fuel/ecodriving)p24_gps_daily_stats, p24_driver_ecodriving_daily, p24_atrax_drivers_daily, anomalie paliwowe — patrz #6138 (blocked na #5921)10 lat (spójne z atrax-archival.py)

5.3 Nowe alerty Prometheus (ETL health)

# monitoring/rules/reporting-etl.yml
- alert: ReportingETLStale
  expr: time() - etl_last_success_timestamp > 86400
  labels: {severity: warning}
  annotations:
    summary: "Reporting ETL nie uruchomił się od >24h — raporty mogą być nieaktualne"

6. Najsłabsze elementy — plan naprawy

6.1 Ranking słabości (posortowane po blast radius × detection time)

#ElementBlast radiusMTTDMTTRFixEffortPriorytet
1bms-1 Ubuntu 20.04 EOLPinbox24 prod down + CVEDni–tygodnieDniDistro upgrade per playbook #16831 dzień (human)🔴 P1
2n8n workflows nie w gitUtrata wszystkich definitons jeśli bms-4 DB padnieNatychmiastowyDni (manual)Nightly n8n export:workflow --all → git push2 h🔴 P1
3MongoDB restore >4 mies.Silent backup corruption → katastrofa przy restoreNigdyNieznanyDrill teraz, automat kwartalny4 h🔴 P1
4bms-1/2/3 bez PrometheusMTTD dla prod disk/RAM = 24 h24 h30 minAnsible role node_exporter na 3 serwerach1 dzień🔴 P1
5bms-4 role overloadn8n + Redis + arbiter + agenty = 4 SPoF w 15–26 h30 minPrzenieś arbiter na vps-i1 (lekka usługa)1 dzień🟡 P2
6socat-supabase tunnel na bms-4Cascade failure: n8n + triage + raporty< 5 min15 min (ręczny restart)Watchdog cron co 5 min — auto-restart przed awarią3 h🟡 P2
7ANTHROPIC_API_KEY/OAuth collisionKażdy nowy skrypt na bms-4 może użyć API key zamiast OAuthPotencjalnie nigdy (silent)N/AIzoluj n8n env w Docker-scope, nie sourcować do claude-runner shell1 dzień🟡 P2
8Claude runner OAuth expiryNightly triage stop26 h15 minPre-expiry refresh cron o godz. 74 h🟡 P2
9GitHub jako jedyny control planeGitHub outage = wszystko autonomiczne zatrzymuje się15 min (brak probe)N/A (zewnętrzne)GitHub API heartbeat probe co 15 min → Discord alert < 15 min2 h🟡 P2
10secrets-sync.yml silent failureSerwery z przeterminowanymi credentialamiPotencjalnie zero (stary klucz działa)MinutyAlert: brak infra_operations row dla deploy w 48h po SOPS commit3 h🟡 P2
11vps-h1 WAHA jako SPoFWhatsApp gateway kompletnie down5 min30 min–kilka godzinBlackbox external probe + warm standby runbook na vps-i11 dzień🟡 P2
12bms-2 secondary monitoring stackKonflikty portów jeśli ktoś edytuje sieć bms-2Nigdy (nieznany stan)NieznanySSH audit: docker ps na bms-2 → decommission lub zarejestruj2 h🟢 P3
13Tier 2 duplikat agent spawn2 agenty na tym samym issue → konflikt PRNigdy (silent)Manualna kasacjaLabel ai-dev-spawned before spawn, check in triage2 h🟢 P3

6.2 3 systemowe luki architektury

1. GitHub jako jedyny control plane Każdy mechanizm autonomii (secrets-sync, CI, issue queue, agent spawn przez GH API) zależy od GitHub. Jedna awaria zatrzymuje wszystko bez ostrzeżenia. Fix: GitHub heartbeat probe co 15 min → Discord alert w < 15 min. Long-term: lokalny fallback scheduler na bms-4 z offline queue (dla zadań pilnych).

2. socat-supabase zombie crash-loop na bms-4 Tunel między n8n a Supabase PostgreSQL przez lokalny socat na porcie 15432 to ukryta zależność. Gdy zombie process trzyma socket — n8n, nightly triage, raporty i routing alertów padają jednocześnie, wyglądając jak 4 niezwiązane alarmy. Playbook istnieje, ale brak watchdoga który wykryje problem w 5 min zamiast w moment gdy n8n workflow krzyknie timeout.

3. ANTHROPIC_API_KEY/OAuth scope collision .env na bms-4 zawiera ANTHROPIC_API_KEY dla n8n workflows. Shell claude-runnera może odziedziczyć tę zmienną i użyć API key zamiast OAuth — cicho, bez błędu, ale z kosztem i risk rate-limit. Każdy nowy skrypt na bms-4 może wpaść w tę pułapkę jeśli deweloper nie wie o niej. Systemowe rozwiązanie: env n8n wyłącznie w Docker-compose scope (.env file), nigdy sourced do claude-runner environment.


7. Mapa wdrożenia

Faza 1 — Stabilizacja (Tydzień 1, ~8 dni pracy)

Natychmiast (równolegle, < 1 dzień):
  [1] Restore drill MongoDB na bms-2 — uruchom verify-backup-restore.sh
  [2] Nightly n8n workflow export → git (cron na bms-4 + GH push)
  [3] Fix health-check.yml Discord spam (notifikacja tylko przy zmianie stanu)
  [4] Fix socat-supabase watchdog (cron co 5 min, auto-restart)

Tydzień 1 (po stabilizacji):
  [5] node_exporter na bms-1/2/3 (Ansible role)
  [6] Prometheus gauge: nightly triage pass/fail per phase
  [7] Tabela dev_r_ops_events (DDL + writer w hourly triage)
  [8] Label ai-dev-spawned guard w hourly triage
  [9] GitHub heartbeat probe → Discord alert
  [10] Izolacja ANTHROPIC_API_KEY do Docker-scope na bms-4

Faza 2 — Skala kolejki (Tydzień 2, ~5 dni pracy)

  [11] bms-3 jako dispatch node (Ansible + dev_r_server_capacity insert)
  [12] Cost attribution columns w dev_r_worker_queue
  [13] Billing tier priority w classify.ts
  [14] SaaS job types w queue (job_type check + spawn-worker.sh cases)
  [15] Grafana: queue depth by tier + cost per client dashboard

Faza 3 — SaaS AI Metering (Tydzień 3-4, ~10 dni pracy)

  [16] Migration 048: ai_jobs, ai_usage, ai_models, ai_rate_limits (DDL)
  [17] ai-worker FastAPI scaffold na bms-4 :8200
  [18] Claude article worker (claim → API → Wasabi → done)
  [19] Supabase Edge Function: POST /ai/jobs (admission)
  [20] Cost recording po każdym Claude call
  [21] Rate limiting w admission
  [22] Webhook delivery z workera
  [23] BrandPilot integracja
  [24] Grafana AI cost dashboard

Faza 4 — Reporting + DR (Tydzień 5-6, ~8 dni pracy)

  [25] DuckDB reporting ETL (export_supabase.py, export_prometheus.py, run_etl.sh)
  [26] report-query-api na vps-i1 :9230 (FastAPI + DuckDB)
  [27] Grafana Infinity datasource → raporty compliance
  [28] Miesięczny PDF raport (Jinja2 + pdf-service)
  [29] DR playbooks: disaster-recovery.md, bms1-total-failure.md, vps-i1-rebuild.md
  [30] Playbook audit: dodaj last_verified do wszystkich 108 playbooki

Faza 5 — Hardware (Tydzień 7+, decyzja po testach)

  [31] Ocena CPU bms-4 po 2 tygodniach z Playwright × 4 + SaaS
  [32] Jeśli saturacja: zakup bms-5 (OVH ECO-4 lub Rise-3)
  [33] Migracja Pinbox24 staging z bms-3 na bms-4 → wolni RAM dla MongoDB
  [34] RunPod setup dla GPU batch (PR #583 gotowy)

8. Metryki sukcesu

KPITerazCel (8 tyg.)
MTTD bms-1 disk/RAM24 h< 2 min
Liczba równoległych agentów6-711-12
Restore drill MongoDBOverdueMiesięcznie (automatyczny)
Pokrycie playbooki108 (brak DR)+8 nowych, wszystkie z last_verified
Discord false-positive rate~12 notif/dobę~1-2 na dobę (state-change only)
Change trackinggit + rotation log+ dev_r_ops_events (real-time)
AI job billingBrakcost_usd per job, dashboard per projekt
ReportingManual / SupabaseNightly Parquet ETL + DuckDB query API

9. Pliki do stworzenia (backlog)

PlikTypFaza
supabase/migrations/048_ai_job_queue.sqlDDL3
infra-src/ai-worker/FastAPI service3
supabase/functions/ai-jobs/index.tsEdge Function3
monitoring/rules/ai-jobs.ymlAlert rules3
scripts/nightly-etl/run_etl.shETL orchestrator4
infra-src/report-query-api/FastAPI + DuckDB4
docs/ai-worker-operations.mdWorkbook3
docs/reporting-etl-operations.mdWorkbook4
docs/playbooks/disaster-recovery.mdPlaybook4
docs/playbooks/bms1-total-failure.mdPlaybook4
docs/playbooks/vps-i1-rebuild.mdPlaybook4
docs/playbooks/pinbox24-rollback.mdPlaybook4
docs/playbooks/supabase-project-suspended.mdPlaybook4
docs/playbooks/agents-capacity-exhausted.mdPlaybook4

Dokument wygenerowany na podstawie 5-agentowej równoległej analizy. 2026-06-27. Następna aktualizacja: po ukończeniu Fazy 1 (~ Tydzień 1).