From d2b5ec8e4f159cf4573768d16efd717ee0c7f7b2 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Mon, 10 Aug 2026 04:03:40 +0200 Subject: [PATCH] docs(compliance): FAS 0-5 - inventory, relations, OSS, golden standard, backlog + repo classification (siax.repo.json) --- docs/architecture/ARCHITECTURE.md | 23 +++- docs/compliance/BACKLOG.md | 81 +++++++++++++ docs/compliance/GOLDEN-STANDARD-REPORT.md | 98 +++++++++++++++ docs/compliance/INVENTORY.md | 141 ++++++++++++++++++++++ docs/compliance/OSS-INVENTORY.md | 91 ++++++++++++++ docs/compliance/RELATIONS.md | 123 +++++++++++++++++++ siax.config.json | 10 +- siax.repo.json | 34 ++++++ 8 files changed, 595 insertions(+), 6 deletions(-) create mode 100644 docs/compliance/BACKLOG.md create mode 100644 docs/compliance/GOLDEN-STANDARD-REPORT.md create mode 100644 docs/compliance/INVENTORY.md create mode 100644 docs/compliance/OSS-INVENTORY.md create mode 100644 docs/compliance/RELATIONS.md create mode 100644 siax.repo.json diff --git a/docs/architecture/ARCHITECTURE.md b/docs/architecture/ARCHITECTURE.md index f201717..788ebc0 100644 --- a/docs/architecture/ARCHITECTURE.md +++ b/docs/architecture/ARCHITECTURE.md @@ -1,7 +1,7 @@ # 0PT — Arkitektur -**Kategori:** PLATTFORM **Underkategori:** Data OS **Status:** under utveckling (deployad frontend i drift, capability-lagret ej produktionsklart) -**Senast verifierad mot kod:** 2026-08-07 (commit `6531384`, main) +**Kategori:** platform (K1) **Underkategori:** data-os **Status:** under utveckling (deployad frontend i drift, capability-lagret ej produktionsklart) +**Senast verifierad mot kod:** 2026-08-07 (commit `6531384`, main) · **Klassificeringsuppdatering:** 2026-08-10 (`siax.repo.json`) > **Läsanvisning.** Detta dokument beskriver vad koden i repot **gör**, inte vad > `README.md`, `CLAUDE.md` eller `docs/01–11` säger att den borde göra. Där de @@ -17,6 +17,25 @@ och levererar företags-, kontakt- och fordonsdata för Norden/Europa, med proveniens (källa, färskhet, konfidens) per fält. +### 1.1 Klassificering (SSOT: `siax.repo.json` / `siax.config.json`, VERIFIERAT 2026-08-10) + +| Fält | Värde | +|---|---| +| category / subcategory | `platform` (K1) / `data-os` | +| appId / packageName | `0PT` / `@siax/0pt` | +| capabilityPrefix | `0pt` | +| node | `null` (ingen SIAX-nod tilldelad — ingen drift på flottan än) | +| domains | `0pt.app` (live) · `api.0pt.app` (target per `.env.example`) | +| consumes | CL0UD · ST0RE · N0D · AUD0 · INF0 | +| replacesSaaS | Apollo · Cognism · ZoomInfo · Clearbit (målet för Data OS: ersätta paid enrichment-SaaS) | +| decoupled | `false` | +| designSystem | `null` (eget mono/editorial-system, konsumerar inte @siax/ui — öppen fråga §8.8) | + +Ersätter krav på betald enrichment-SaaS (Apollo/Cognism/ZoomInfo/Clearbit) med +egen compliant sourcing + provenance — målet är att Datahub/VehIQ/data-avdelningar +konsumerar `0pt.*`-capabilities i stället för att köpa listor. *(ANTAGANDE om +konsumentledet: inga inkommande integrationer är verifierade i detta repo.)* + Repot innehåller i praktiken **två separata system** i samma träd: | Plan | Var | Vad koden faktiskt är | diff --git a/docs/compliance/BACKLOG.md b/docs/compliance/BACKLOG.md new file mode 100644 index 0000000..5f49b9e --- /dev/null +++ b/docs/compliance/BACKLOG.md @@ -0,0 +1,81 @@ +# BACKLOG — 0pt (FAS 5) + +> P0 = säkerhetskritiskt · P1 = hög · P2 = medel · P3 = låg · P4 = hygien · P5 = struktur · P6 = senare. +> Alla luckor hänvisar till docs/architecture/ARCHITECTURE.md §7 (S1–S12) och GOLDEN-STANDARD-REPORT. +> **[BYPASS]** = berört av det medvetna användarbeslutet (rör ej kod). + +## P0 — säkerhet, görs först (kräver produktbeslut + egna PR:er) + +| ID | Lucka | Åtgärd | Kräver | +|---|---|---|---| +| P0-1 | **S1** — middleware körs inte i prod (live: 200 anonymt) | Rotorsaksanalys (Next 16 + src/-träd + Vercel build-output), sedan verifierad 401 anonymt | Prod-deploy + test mot live | +| P0-2 | **S2** — tenant tas ur body/query | Alla /api/0pt/*-handlers läser `x-0pt-verified-tenant` (middleware-header) | Fungerande middleware (P0-1) | +| P0-3 | **S3** — hela icke-/api/0pt-API:t utan auth | Auth på orders/payments/admin/subscriptions/uploads/estimates/screen/ai | Auth-design (Zitadel-session eller bearer) | +| P0-4 | **S4** — escrow-release utan identitet | `POST /payments/{id}/release` kräver verifierad ägare + betalningsbekräftelse före `delivered` | P0-3 | +| P0-5 | **S5** — CL0UD fail-open | fail-closed + `assertPolicyConfigSafe` (mönster från auth) + NODE_ENV-spärr | — | +| P0-6 | **S8** — FastAPI-engine utan auth | `X-Internal-Token`-verifiering (constant-time) på alla engine-endpoints | Koordinering med deploy | +| P0-7 | **S10** — connection_config ur body (SSRF-primitiv) | Allow-list av hosts/protokoll + tenant-scoped källdefinitioner; aldrig godtycklig URL | — | +| P0-8 | **C11** — middleware typkontrolleras ej | Inkludera middleware.ts i tsconfig.check.json; eslint blockerande | — | + +## P1 — hög + +| ID | Lucka | Åtgärd | +|---|---|---| +| P1-1 | **S6** — AUD0 no-op utan URL | Wire AUD0_URL från Infisical; verifiera event-emission live | +| P1-2 | **S7** — db-grant påstår kryptering | Implementera AES-GCM med GRANT_ENC_KEY, read-only-validering, lagring + audit — eller ta bort påståendet | +| P1-3 | **S12** — svag session | exp-kontroll, rotation, användar-binding | +| P1-4 | **S9** **[BYPASS]** | Produktbeslut: behåll/bygg-om bypass-stacken (GPL-fläckar + juridiskt läge). Teknisk radering är INTE planerad — beslut om framtida läge fattas av Simon | +| P1-5 | **D4** — Coolify-app ej provisionerad | Provisionera app i cloud.siax.io, fyll COOLIFY_APP_ID + COOLIFY_TOKEN (Infisical) | +| P1-6 | **C8** — Infisical ej inkopplat | Infisical-projekt 0pt + env-mapping; Vercel-env avvecklas i takt med cutover | + +## P2 — medel + +| ID | Lucka | Åtgärd | +|---|---|---| +| P2-1 | **D5** — ingen backup/restore | När DB provisioneras: pg_dump-schema + offsite (jfr fleet-blockerare), restore-test i kalender | +| P2-2 | **C13** — retention/deletion-after-job | TTL-jobb + DELETE-väg + audit | +| P2-3 | **C10→P0-7-efterföljd** | Källquery-vägar tenant-scopade | +| P2-4 | **D6** — observabilitet | Strukturerad loggning + correlation-id-propagering; OTel-agent senare | + +## P3 — låg + +| ID | Lucka | Åtgärd | +|---|---|---| +| P3-1 | **A4/A5-efterföljd** | Registera 0pt-capabilities i CL0UD capability-registry (API/CLI/MCP/SDK) från contracts/openapi.yaml | +| P3-2 | **S2-efterföljd** | Tenantmodell bekräftas mot CL0UD-tenantregister (1:1 Zitadel-org?) | +| P3-3 | **C2-efterföljd** | X-Tenant-Id-headerkontroll vs body → enhetlig policy | +| P3-4 | **Engine-DB** | asyncpg inkopplad; Postgres som riktig store för ordrar/jobb (idag in-memory) | + +## P4 — hygien (kan göras i en session utan produktbeslut) + +| ID | Åtgärd | +|---|---| +| P4-1 | `duckdb` saknas i services/scrapers/requirements.txt trots import — lås versionen | +| P4-2 | `package.json` namn `"my-v0-project"` → `@siax/0pt` (spårbarhet) | +| P4-3 | sql/002/003 refereras men saknas — antingen skapa eller korrigera referenserna | +| P4-4 | Committed `__pycache__/*.pyc` + `services/scrapers/output/*.json` (skrapdata) — flytta ut ur git (ej radering av funktionalitet) | +| P4-5 | `.github/workflows/ci.yml` (legacy GitHub-mirror) — beslut om GitHub-avveckling; behålls tills dess (AR-1) | +| P4-6 | In-memory-state-fix: Map per instans → delad store (förutsätter P3-4) | + +## P5 — struktur + +| ID | Åtgärd | +|---|---| +| P5-1 | runbook/SLO-uppföljning i drift (oncall-rotation) | +| P5-2 | Docs: konsumentled (Protosell/VehIQ-integrationer) verifieras och dokumenteras | + +## P6 — senare + +| ID | Åtgärd | +|---|---| +| P6-1 | Designsystem-konvergens mot @siax/ui (öppen fråga §8.8) | +| P6-2 | NER (spaCy), OCR (self-hosted på N0D), kvalitetslager (docs/P0_DATASET_QUALITY_FLOW.md) | +| P6-3 | OpenSanctions-avtal: verifiera kommersiella villkor före produktionsvolym | +| P6-4 | AI-parsning → INF0-gateway (consumes INF0) | + +## Bypass-undantag (formellt) + +Följande backlog-poster berör den medvetet behållna bypass-stacken och ska inte +åtgärdas som "radera koden": P1-4. All övrig backlog rör inte +`services/scrapers/*`, `services/infra/docker-compose.data-stack.yml` eller +`adaptive_router.py` (AR-1-undantag). diff --git a/docs/compliance/GOLDEN-STANDARD-REPORT.md b/docs/compliance/GOLDEN-STANDARD-REPORT.md new file mode 100644 index 0000000..80a3e69 --- /dev/null +++ b/docs/compliance/GOLDEN-STANDARD-REPORT.md @@ -0,0 +1,98 @@ +# GOLDEN-STANDARD-REPORT — 0pt (FAS 4) + +> Bedömning mot SIAX Cloud K1-golden-standard (plattformsrepo). Verifierad 2026-08-10. +> Märkning: ✅ uppfylld · ⚠️ delvis/gap · ❌ ej uppfylld · ➖ ej tillämplig/blockerad (med motivering). +> Bevis per kontroll (AR-5). Poäng: ✅=1, ⚠️=0.5, ❌=0, ➖ exkluderas ur nämnaren. + +--- + +## A. Plattformsidentitet & kontrakt + +| # | Kontroll | Status | Bevis | +|---|---|---|---| +| A1 | Korrekt klassificering (category=platform K1, subcategory=data-os, appId=0PT, prefix=0pt, @siax/0pt) | ✅ | `siax.config.json` + ny `siax.repo.json` (FAS 1, VERIFIERAT) | +| A2 | consumes ⊆ tillåtna K1-OS (CL0UD/ST0RE/N0D/AUD0/INF0) | ✅ | siax.repo.json consumes-lista; klienterna finns i `src/clients/*` | +| A3 | replacesSaaS-dokumenterat (Apollo/Cognism/ZoomInfo/Clearbit) | ✅ | siax.repo.json + ARCHITECTURE §1.1 | +| A4 | OpenAPI 3.1-kontrakt som SSOT (/orders, /estimates, enrich, resolve, provenance) | ❌ | `contracts/openapi.yaml` finns inte — byggs FAS 6 | +| A5 | Capability på sex ytor (API/CLI/MCP/UI/Job/SDK) | ⚠️ | API (app/api/0pt/*) + UI (admin/kallor) + Job-signaler (n0d-client) finns; CLI/MCP/SDK delegeras till cl0ud — ej verifierat registrerat i capability-registret (ANTAGANDE) | + +## B. Beroenden & arkitektur (hårda regler) + +| # | Kontroll | Status | Bevis | +|---|---|---|---| +| B1 | AR-4: inga Vercel/Google Fonts/next/font/google i körbar kod | ❌ | `@vercel/analytics` (package.json:48, app/layout.tsx:4,64) + `next/font/google` (app/layout.tsx:3,11-12) — åtgärdas FAS 6 | +| B2 | AR-4: inga betald-SaaS-beroenden som driftkrav (Stripe är kundval, env-guardad — ej plattformsberoende) | ⚠️ | Stripe env-guardad ✅; Azure Doc Intelligence + Cloudflare R2-adapter env-guardade, behållna per AR-1 (migration → backlog) | +| B3 | AR-8: beroenden pekar bara nedåt (inga K2–K5) | ✅ | Ingen referens till kundrepon (contentroom/v0-datahub/prt-*) i koden (grep) | +| B4 | AR-2: inga frysta kundrepon berörs | ✅ | Denna session rör endast sax3l/0pt | +| B5 | AR-3: ärvd licens ej ersatt | ✅ | 0pt är ingen fork; egen proprietär kod (LICENSE) | +| B6 | OSS-disciplin (licenskompatibilitet, låsningar) | ⚠️ | duckdb används i kod men saknas i requirements.txt; GPL-komponenter (FlareSolverr/NocoDB/Metabase) containeriserade — medvetet | +| B7 | Testbarhet: tester gröna i CI | ✅ | Gitea run 3759 (ci.yml, main) success 2026-08-09; lokalt omverifieras FAS 8 | + +## C. Säkerhet (SEC-kontroller) + +| # | Kontroll | Status | Bevis | +|---|---|---|---| +| C1 | Auth på /api/0pt/* (fail-closed) | ⚠️ | Koden fail-closed (middleware.ts + assertAuthConfigSafe) men live-probe 2026-08-10: `GET 0pt.app/api/0pt` → **200 anonymt** (lucka S1, orsak OKÄND) | +| C2 | Tenant bundet till session, aldrig från body | ❌ | S2: ingen handler läser x-0pt-verified-tenant; tenant_id tas ur body/query (grep) | +| C3 | Auth på övriga routes (orders/payments/admin/estimates) | ❌ | S3+S4: live 200 anonymt på /api/orders + /api/admin/metrics; escrow-release utan identitet | +| C4 | Policy-klient (CL0UD) fail-closed | ❌ | S5: `cl0ud-client.ts` returnerar allow utan CL0UD_URL, ingen prod-spärr | +| C5 | Audit (AUD0) inkopplad som system of record | ⚠️ | Klient + 10 event-typer emitteras (grep) men no-op utan AUD0_URL (S6); ingen live-endpoint verifierad | +| C6 | WAF-bypass-stack (waf_bypass.py, FlareSolverr, Tor) | ➖ | **Medvetet användarbeslut (AR-1-undantag): bypass-adapter/produktionskod rörs inte.** Stacken behålls intakt, dokumenteras som medvetet val. Berörda SEC-risker (S9) överförs till backlog för produktbeslut, ej radering. | +| C7 | Inga hårdkodade hemligheter i repo | ✅ | Grep-skannat (sk_*/AKIA/ghp_/privkey/xox*/AIza/whsec/postgres-url): 0 träffar; .env.example placeholders | +| C8 | Secrets via Infisical (ej Vercel-env/kommitterade) | ❌ | Infisical ej inkopplat (0 referenser i repo); live-env på Vercel-projektet | +| C9 | Engine (FastAPI) autentiserad | ❌ | S8: 12 endpoints utan auth; X-Internal-Token skickas men läses aldrig | +| C10 | SSRF-skydd (connection_config ur body) | ❌ | S10: POST /api/0pt/sources/{id}/query tar anslutningskonfig ur body → utgående anslutningar mot godtycklig host | +| C11 | Middleware/kritisk seam typkontrolleras i CI | ❌ | S11: middleware.ts i roten, utanför tsconfig.check.json; eslint rådgivande | +| C12 | Stripe-webhook signaturverifiering | ✅ | app/api/webhooks/stripe verifierar mot STRIPE_WEBHOOK_SECRET | +| C13 | GDPR: retention/deletion-after-job implementerad | ❌ | Ingen retention/TTL/DELETE-väg (ARCHITECTURE §4.4) | +| C14 | db-grant-route krypterar verkligen | ❌ | S7: kommentar lovar AES-GCM, kod returnerar random grant_id | + +## D. Drift & runtime + +| # | Kontroll | Status | Bevis | +|---|---|---|---| +| 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 | +| 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) | + +## E. Dokumentation & compliance + +| # | Kontroll | Status | Bevis | +|---|---|---|---| +| E1 | INVENTORY.md (FAS 0) | ✅ | docs/compliance/INVENTORY.md | +| E2 | RELATIONS.md + Mermaid (FAS 2) | ✅ | docs/compliance/RELATIONS.md | +| E3 | OSS-INVENTORY.md (FAS 3) | ✅ | docs/compliance/OSS-INVENTORY.md | +| E4 | GOLDEN-STANDARD-REPORT (denna) | ✅ | — | +| E5 | BACKLOG P0–P6 (FAS 5) | ✅ | docs/compliance/BACKLOG.md | +| E6 | SLO + runbooks + säkerhetsdokumentation (FAS 9) | ⚠️ | SECURITY.md finns; SLO/runbook/oncall saknas → FAS 9 | +| E7 | Sanning-ärlighet: inga fabricerade påståenden | ✅ | Repot är exceptionellt ärligt (ARKITEKTUR-dok korrigerar README-systematiskt, t.ex. S1–S12, "fabricated, not built"-callouts) | + +--- + +## Poäng + +**Före denna session (FAS 0–4), n=29 kontroller, 6 ➖ exkluderade:** + +| Markering | Antal | +|---|---| +| ✅ | 9 | +| ⚠️ | 8 | +| ❌ | 10 | +| ➖ | 2 (C6 bypass, D7 Infisical-token) | + +**Poäng före: (9×1 + 8×0.5) / 27 = 13/27 ≈ 48 %** + +**Prognos efter FAS 6–9:** A4, B1, C11→fixade; C1/C2/C3/C4/C5/C10/C14 → backlog-P0 (kräver produktändringar som kan ske inom FAS 6 endast i begränsad omfattning) — se BACKLOG. + +## Bypass-undantag (formell notering) + +Per explicit användarbeslut behålls `services/scrapers/waf_bypass.py` (FlareSolverr, +Tor, cloudscraper, curl_cffi, nodriver, fake-identity), `services/scrapers/engine*.py`, +`services/infra/docker-compose.data-stack.yml` och `adaptive_router.py` intakt och +orörda. Kontroll **C6** markeras ➖ med motiveringen **"medvetet användarbeslut"**. +Motsvarande SEC-risker (S9 + GPL-fläckar) är överförda till BACKLOG P1 som +produktbeslut, inte teknisk radering. diff --git a/docs/compliance/INVENTORY.md b/docs/compliance/INVENTORY.md new file mode 100644 index 0000000..ddb3797 --- /dev/null +++ b/docs/compliance/INVENTORY.md @@ -0,0 +1,141 @@ +# INVENTORY — 0pt (sax3l/0pt) — FAS 0 + +> Kategori: **platform (K1)** · Subkategori: **data-os** · Repo: `git.siax.io/sax3l/0pt` +> Kartlagd: 2026-08-10 · Metod: klon (git) + Gitea API (v1, token admin) + grep + live-prober +> Alla påståenden märkta **VERIFIERAT** / **ANTAGANDE** / **EJ VERIFIERAT** per AR-5. + +--- + +## 1. Repo-identitet (VERIFIERAT — Gitea API) + +| Fält | Värde | +|---|---| +| full_name | `sax3l/0pt` (id 21) | +| visibility | private | +| default_branch | `main` | +| HEAD (main) | `1346e868bf5c55c6771377c60a3ab7d3dd789ffc` (2026-08-09) | +| branches | 8 (main, fix/remove-vercel-deploy-target, unify/github-main-2026-07-28, docs/1p-egress-measurement-point, compliance/remove-evasion-stack, renovate/configure, foundation/hardening, feature/0pt-remove-noncompliant-scrapers) | +| språk | TypeScript (dominerande) + Python (engine + scrapers) | +| storlek | ~22 MB (inkl. committed skrapdata `services/scrapers/output/*.json` + `__pycache__/*.pyc`) | +| licens | egen (proprietär, SIAX Technology AB — LICENSE-fil finns) | +| Gitea | 1.26.4; Actions aktiverade (`has_actions: true`) | + +**Historik:** Repot har haft två remotes (github.com/sax3l/0pt + git.siax.io/sax3l/0pt) +som divergerade; unifierades 2026-07-28 i Gitea main (merge `a714668`). Gitea main +är nu det gemensamma trädet. VERIFIERAT via merge-commits + CLAUDE.md-dokumentation. + +## 2. Filträd (VERIFIERAT — git ls-files) + +``` +0pt/ +├─ app/ # Next.js 16 App Router: 20 sidor (sv UI-copy) + 28 API-routehandlers +│ └─ api/ # health, orders, estimates, 0pt/*, auth/*, payments/*, admin/metrics, +│ # screen, uploads, vehicles, subscriptions, connections, webhooks/stripe, ai/parse +├─ components/ # shadcn/ui + sections + DataArtifact/ProvenanceBadge +├─ lib/ # db, engine, auth, stripe, orders-store, subscriptions-store, data, services +├─ src/ # capability-lagret (TS): clients (cl0ud, n0d, aud0, st0re, st0re-lakehouse), +│ │ # services (dataset, source, source-query, iceberg-write, document-capture/-extraction, +│ │ # external-writeback, source-rate-policy, dataset-iceberg-mapping), adapters, auth, types +├─ services/ +│ ├─ api/ # FastAPI-engine: orchestrator/main.py (12 endpoints) + workers (adaptive_router, +│ │ # pipeline, queue, resolve, run) + sources (sources.yaml, connectors, financials) +│ ├─ scrapers/ # Skrapmotor Python: engine.py, engine_v2.py, waf_bypass.py, clickhouse_pipeline.py, +│ │ # s3_sync.py + committed output/*.json + __pycache__/*.pyc +│ └─ infra/ # docker-compose.data-stack.yml (clickhouse, trino, flaresolverr, tor-proxy, superset, postgres) +├─ infra/ # docker-compose.yml (postgres+pgvector, redis, api, worker, nocodb, metabase, caddy) + Caddyfile +├─ sql/ # 001_init.sql, 004_iceberg_write_boundary.sql, 005_..._gap_closure.sql +│ # (002/003 saknas — refereras av 3 filer, se GAP-1) +├─ packages/schemas/ # JSON Schemas 0pt.* (dataset_iceberg_mapping, iceberg_table, lineage_event, signal, source_rate_policy) +├─ tests/ # vitest: auth/ + p0/ + validation/ (17+ testfiler) +├─ docs/ # 01–12 + architecture/ARCHITECTURE.md (S1–S12-luckor) + P0_*-flöden +├─ .gitea/workflows/ # ci.yml, deploy.yml, health-check.yml +├─ .github/workflows/ # ci.yml (arv från GitHub-linjen, kvar efter unifiering) +├─ Dockerfile # Coolify, multi-stage, icke-root (node), HEALTHCHECK /api/health +└─ root: package.json, pnpm-workspace.yaml, pnpm-lock.yaml, siax.config.json, renovate.json, + .npmrc, .env.example, .gitignore, .dockerignore, middleware.ts, next.config.mjs, vitest.config.ts, + tsconfig{,.check}.json, eslint.config.mjs, CLAUDE.md, README.md, SECURITY.md, LICENSE +``` + +## 3. Beroenden + +### 3.1 JS/TS (VERIFIERAT — package.json + pnpm-lock.yaml) + +- **next@16.0.10, react@19.2.0** (App Router), tailwindcss@4, shadcn/ui (Radix-primitiver), + zod@3.25.76, jose (JWT-verifiering), stripe@22, postgres@3, recharts, sonner, vaul m.fl. +- devDeps: vitest@3, typescript@5, eslint@9, prettier@3. +- packageManager: `pnpm@9.15.9` (lockfile v9.0). +- **Namnet i package.json är fortfarande `"my-v0-project"`** (v0-exportartefakt, GAP-2). +- **Förbjudet beroende enligt AR-4 (VERIFIERAT):** + - `@vercel/analytics@1.3.1` (package.json rad 48) — används i `app/layout.tsx` rad 4/64. + - `next/font/google` (Inter + JetBrains Mono) — `app/layout.tsx` rad 3/11-12. Google Fonts hämtas + vid byggtid → AR-4-brott. + - Azure Document Intelligence (`DOC_INTELLIGENCE_*`) — env-guardad adapter + `src/adapters/document-intelligence-adapter.ts` (befintlig funktionalitet, AR-1 behåller). + - Cloudflare R2 (`app/api/uploads`) — env-guardad stub (AR-4: pågående migrering noteras). + +### 3.2 Python engine (VERIFIERAT — services/api/requirements.txt) + +fastapi, uvicorn, pydantic, httpx, asyncpg (oanvänd), python-dotenv, pyyaml, +rapidfuzz (enda matching-engine, `workers/resolve.py`), tenacity. +**saknas (plan i docs/07):** spaCy/transformers (NER), dedupe-paket (rapidfuzz täcker dedup), +DuckDB/polars, Playwright (kompliant, ej installerat), unstructured, OCR. + +### 3.3 Python scrapers (VERIFIERAT — services/scrapers/requirements.txt) + +curl_cffi, cloudscraper, httpx, aiohttp, requests, beautifulsoup4, lxml, boto3. +→ **Bypass-stacken.** BEHÅLLS INTACT per explicit användarbeslut (AR-1-undantag): +`waf_bypass.py` (FlareSolverr, Tor, cloudscraper, TLS-fingerprintbyte, proxypool, nodriver, +fake-identity) + `services/infra/docker-compose.data-stack.yml` (flaresolverr, tor-proxy) + +`workers/adaptive_router.py` ("all methods, no compliance restrictions"). +Dokumenteras i GOLDEN-STANDARD-REPORT som medvetet val (SEC-kontroller ➖/⚠️). + +### 3.4 Beroenden uppåt (VERIFIERAT — src/clients/*) + +| OS/klient | Env | Fail-beteende | +|---|---|---| +| Zitadel (IdP) | `ZITADEL_ISSUER` (default id-customers.siax.io) | Fail-closed (401/403), `assertAuthConfigSafe` | +| CL0UD | `CL0UD_URL` | **Fail-open** → `allow` (lucka S5) | +| AUD0 | `AUD0_URL` | No-op (lucka S6) | +| ST0RE | `ST0RE_URL` | Mock-artefakt | +| N0D | `N0D_URL` | Mock-jobb | +| Stripe | `STRIPE_*` | 501 | + +AR-8 (beroenden bara nedåt, K1 får inte bero på K2–K5): alla OS-beroenden är plattformsinternta +(CL0UD/ST0RE/N0D/AUD0/INF0 = K1). VERIFIERAT: inget beroende på kundrepon (contentroom, +v0-datahub, prt-* etc.) finns i 0pt. + +## 4. Drift (VERIFIERAT 2026-08-10) + +| Fråga | Läge | Bevis | +|---|---|---| +| Live-instans | **Vercel** (0pt.app) — Coolify avsett, ej provisionerat | README §Deploy + ARCHITECTURE §5 | +| Nod (flotta) | `siax.config.json` → `deploy.node: null` — ingen nod tilldelad | siax.config.json | +| Domän | `0pt.app` (live). `api.0pt.app`/`data.0pt.app`/`dash.0pt.app` (Caddy) EJ VERIFIERAT | README + ARCHITECTURE §5 | +| /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` | +| 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 | + +## 5. Förbjudna beroenden — sammanfattning (AR-4) + +| Träff | Fil | Åtgärd FAS | +|---|---|---| +| `@vercel/analytics` | package.json + app/layout.tsx | FAS 6: ta bort (ersättning saknas — ej betald SaaS) | +| `next/font/google` | app/layout.tsx | FAS 6: ersätt med självhämtade fonter (fontsource) | +| Azure Doc Intelligence | src/adapters/document-intelligence-adapter.ts (env-guardad) | FAS 6: behåll (AR-1) — dokumenteras ⚠️, migration → backlog | +| Cloudflare R2 | app/api/uploads/route.ts (env-guardad stub) | FAS 6: behåll (AR-1 + pågående migrering) — dokumenteras | + +## 6. Kända luckor (arv från docs/architecture/ARCHITECTURE.md §7, verifierade) + +S1 (middleware körs ej i prod — live-bekräftat 2026-08-10), S2 (tenant från body, ej session), +S3 (icke-/api/0pt-API saknar auth — live-bekräftat), S4 (escrow-release utan identitet), +S5 (CL0UD fail-open), S6 (AUD0 no-op), S7 (db-grant påstår kryptering som inte finns), +S8 (engine utan auth), S9 (bypass-kod — **medvetet behållen per användarbeslut**), +S10 (connection_config ur body → SSRF-primitiv), S11 (middleware typkontrolleras ej), +S12 (svag sessions-scaffold). + GAP-1 (sql/002–003 saknas), GAP-2 (package.json-namn). + +## 7. Utfallsfil FAS 0 + +✅ `docs/compliance/INVENTORY.md` skapad. Redo för FAS 1. diff --git a/docs/compliance/OSS-INVENTORY.md b/docs/compliance/OSS-INVENTORY.md new file mode 100644 index 0000000..1b2f5b9 --- /dev/null +++ b/docs/compliance/OSS-INVENTORY.md @@ -0,0 +1,91 @@ +# OSS-INVENTORY — 0pt (FAS 3) + +> Kartlagd 2026-08-10. Status per manifest/läsning: **INSTALLERAD** (i requirements.txt/package.json) +> vs **PLANAD** (docs/07-dependencies.md, ej installerad) vs **REFERENS** (nämnd i kod/docs). +> Licens-URLer och licenser är välkända, ej individuellt omverifierade denna pass (ANTAGANDE där annat ej anges). + +## 1. Python — engine (services/api/requirements.txt) + +| Paket | Roll | Licens | Status | +|---|---|---|---| +| fastapi | API-ramverk | MIT | INSTALLERAD | +| uvicorn | ASGI-server | BSD-3-Clause | INSTALLERAD | +| pydantic | validering | MIT | INSTALLERAD | +| httpx | HTTP (kompliant, identifierar sig) | BSD-3-Clause | INSTALLERAD, aktivt använd | +| asyncpg | Postgres-driver | Apache-2.0 | INSTALLERAD men oanvänd (grep) | +| python-dotenv | env | BSD-3-Clause | INSTALLERAD | +| pyyaml | sources.yaml | MIT | INSTALLERAD, använd | +| rapidfuzz | fuzzy matching / entity resolution (Levenshtein-familjen) | MIT | INSTALLERAD, enda matching-engine (workers/resolve.py) | +| tenacity | retry | Apache-2.0 | INSTALLERAD | +| **spaCy** (+modeller) | NER / entity resolution | MIT (modeller: CC-BY-SA-3.0) | **PLANAD** (docs/07), EJ installerad — NER saknas helt i kod | +| **dedupe** | record linkage / dedupe | MIT | **PLANAD/ERSATT** — rapidfuzz fyller dedup-rollen idag; dedupe ej installerat | +| **DuckDB** | kolumnanalys | MIT | **REFERENS + kodanvändning** — lazy-import i `services/scrapers/clickhouse_pipeline.py:220` (DuckDBWriter), men **SAKNAS i requirements.txt** (GAP: låsas om den ska vara del av stacken) | +| **Playwright** | kompliant JS-rendering (public pages) | Apache-2.0 | **PLANAD** (docs/07 rad 45) — ej installerad; klart skild från bypass | +| **python-Levenshtein** | Levenshtein | GPL-2.0-or-later | **UNDVIK medvetet** — rapidfuzz (MIT) ersätter (GPL-kompatibilitetsskäl, docs/07-rad 39) | +| polars | tabular | MIT | PLANAD, ej installerad | +| unstructured | PDF/HTML→element | Apache-2.0 | PLANAD, ej installerad | +| paddleocr/pytesseract | OCR | Apache-2.0 | PLANAD, ej installerad | + +## 2. Python — scrapers (services/scrapers/requirements.txt) — medvetet behållen stack + +> ⚠️ AR-1-undantag (användarbeslut): hela `services/scrapers/*` + `services/infra/docker-compose.data-stack.yml` +> behålls intakt. OSS-inventeringen listar dem ärligt; compliance-bedömning sker i GOLDEN-STANDARD-REPORT. + +| Paket/komponent | Roll | Licens | Status | +|---|---|---|---| +| curl_cffi | TLS-fingerprintbyte | MIT | INSTALLERAD, använd i engine.py/engine_v2.py/waf_bypass.py | +| cloudscraper | Cloudflare-bypass (basic) | MIT | INSTALLERAD, använd | +| httpx / aiohttp / requests | HTTP | BSD-3-Clause / Apache-2.0 / Apache-2.0 | INSTALLERAD | +| beautifulsoup4 + lxml | HTML-parsing | MIT | INSTALLERAD | +| boto3 | S3-sync (MinIO/R2) | Apache-2.0 | INSTALLERAD, använd i s3_sync.py | +| **FlareSolverr** | CF-bypass (tung) | **GPL-3.0** | REFERENS — container i docker-compose.data-stack.yml + waf_bypass.py | +| **Tor** | proxy-rotation | BSD-3-Clause | REFERENS — tor-proxy-container i docker-compose.data-stack.yml | +| **nodriver** | undetected browser | Apache-2.0 | REFERENS (waf_bypass.py) — ej i requirements | +| **DuckDB** | alternativ lagring | MIT | KODANVÄND (clickhouse_pipeline.py) men ej i requirements.txt — GAP | + +## 3. JS/TS (package.json, urval) — OSS + proprietär + +| Paket | Roll | Licens | Status | +|---|---|---|---| +| next / react / react-dom | App Router | MIT | INSTALLERAD | +| zod | schema-validering | MIT | INSTALLERAD | +| jose | JWT/JWKS | MIT | INSTALLERAD | +| stripe | betalningar | Apache-2.0 | INSTALLERAD | +| postgres (pg) | DB-driver | Unlicense | INSTALLERAD | +| tailwindcss / shadcn-ui-komponenter | styling | MIT | INSTALLERAD | +| Radix-primitiver (react-*)| a11y-komponenter | MIT | INSTALLERAD | +| vitest | testrunner | MIT | INSTALLERAD | +| recharts | diagram | MIT | INSTALLERAD | +| @vercel/analytics | **FÖRBJUDET (AR-4)** | MIT | INSTALLERAD → tas bort FAS 6 | + +## 4. Self-hosted containers (infra/, services/infra/) + +| Komponent | Licens | Status | +|---|---|---| +| postgres pgvector (pg16) | PostgreSQL | infra/docker-compose.yml (ej verifierat körande) | +| redis:7 | BSD-3-Clause | infra/docker-compose.yml | +| nocodb/nocodb | AGPL-3.0 | infra/docker-compose.yml | +| metabase/metabase | AGPL-3.0 | infra/docker-compose.yml | +| caddy | Apache-2.0 | infra/Caddyfile | +| clickhouse | Apache-2.0 | services/infra/data-stack (ej verifierat körande) | +| trino | Apache-2.0 | services/infra/data-stack | +| **flaresolverr** | **GPL-3.0** | services/infra/data-stack — medvetet behållen | +| **tor-proxy** | BSD-3-Clause | services/infra/data-stack — medvetet behållen | +| superset | Apache-2.0 | services/infra/data-stack | + +## 5. Noteringar + +- **AR-3 (ärvd licens):** 0pt är ingen fork — egen proprietär kod. Inga ärvda + licenser att ersätta. ✔ +- **GPL-fläckar:** FlareSolverr (GPL-3.0) och NocoDB/Metabase (AGPL-3.0) är + containeriserade, ej inlänkade bibliotek — GPL-eksponeringen begränsad men bör + hållas i åtanke vid byte av BI-verktyg. +- **Låsnings-GAP:** `duckdb` används i kod (scrapers) men saknas i + requirements.txt — se BACKLOG (P4). +- Playwright/FlareSolverr radas som referens i samma dokumentfamilj men är varandras + motsatser: Playwright = kompliant hämtning (docs/07, ej installerad), FlareSolverr = + bypass (medvetet behållen). + +## 6. Utfallsfil FAS 3 + +✅ `docs/compliance/OSS-INVENTORY.md` skapad. diff --git a/docs/compliance/RELATIONS.md b/docs/compliance/RELATIONS.md new file mode 100644 index 0000000..60923d3 --- /dev/null +++ b/docs/compliance/RELATIONS.md @@ -0,0 +1,123 @@ +# RELATIONS — 0pt relationskarta (FAS 2) + +> Verifierad mot kod 2026-08-10. Alla relationer är grep-/läs-verifierade (AR-5). +> Legenden: **sources.yaml** = kompliant källregistret · **bypass-stacken** = medvetet behållen +> per användarbeslut (se GOLDEN-STANDARD-REPORT), visas grått. + +## 1. Router → källor + +`services/api/workers/adaptive_router.py` bygger sourcingplan per marknad; +`services/api/sources/sources.yaml` är källregistret (kompliant sida). Skrapmotorn +(`services/scrapers/`) är den medvetet behållna bypass-sidan. + +```mermaid +flowchart LR + subgraph Router["adaptive_router.py (workers)"] + R["plan_for_market(market) -> source_id-lista"] + end + subgraph Registry["sources.yaml (kompliant, 8 källor)"] + S1[gleif · global · api CC0] + S2[brreg · NO · api NLOD] + S3[companies_house · GB · api nyckel] + S4[prh · FI · api CC-BY] + S5[cvr · DK · api Virk] + S6[bolagsverket · SE · licensed] + S7[rdw · NL · bulk fordon] + S8[opensanctions · global · bulk screening] + end + subgraph Scraper["services/scrapers (medvetet behållen bypass)"] + W[waf_bypass.py: FlareSolverr/Tor/cloudscraper/curl_cffi] + E2[engine_v2.py] + C[clickhouse_pipeline.py] + end + R -->|NO| S2 + R -->|GB| S3 + R -->|FI| S4 + R -->|DK| S5 + R -->|SE| S6 + R -->|NL| S7 + R -->|global| S1 + R -->|screening| S8 + R -.->|"deep scraping (b0ts/legacy)"| E2 + E2 --> W + E2 --> C +``` + +## 2. ST0RE-artefakter (lakehouse-write-vägen) + +Enda skrivväg för Iceberg-state: `src/clients/st0re-lakehouse-client.ts` → +`/v1/st0re/lakehouse/*` (namespace → table → snapshot). Live-verifierad 2026-07-13. + +```mermaid +flowchart LR + API["POST /api/0pt/lakehouse/mappings/{id}/writes"] --> WRITE[IcebergWriteService] + WRITE --> NS[registerNamespace
X-Tenant-Id/X-Actor-Id] + NS --> T[registerTable
IcebergTableInput] + T --> SNAP[createSnapshot
manifestUri, aud0EventId] + SNAP --> MANI["Iceberg-manifest (bytes)
N0D skriver faktiska filer"] + WRITE --> N0D[createJob /v1/n0d/jobs
job_type=0pt.* heavy] + WRITE --> MAP["DatasetIcebergMapping (0pt, in-memory/Postgres mål)"] + MAP -.->|"mappingId->tableId"| T +``` + +## 3. N0D-jobb + +`src/clients/n0d-client.ts` → `POST /v1/n0d/jobs`. 0pt begär jobb, äger aldrig +scheduling/GPU. Mock (`mock_job_*`) utan `N0D_URL` — testbar, inte verklig. + +```mermaid +sequenceDiagram + participant S as Service (0pt) + participant N as N0D (POST /v1/n0d/jobs) + participant R as N0D-Runner + S->>N: createJob {tenant_id, project_id, job_type, input_artifact_ids, risk_level} + N-->>S: job_id (status=queued) + N->>R: scheduler -> worker + R-->>S: (0pt följer ej upp — poll/hook saknas, backlog) +``` + +## 4. AUD0-events (system of record) + +`src/clients/aud0-client.ts` → `POST /v1/aud0/events` + `/v1/aud0/lineage/events`. +Event-typer som emiteteras i kod (grep-verifierat): + +| event_type | Källa (service) | Linjage-event | +|---|---|---| +| `0pt.dataset_registered` | dataset-service.ts | — | +| `0pt.source_created` | source-service.ts | — | +| `0pt.source_rate_policy_created` | source-rate-policy-service.ts | — | +| `0pt.source_queried` | source-query-service.ts | — | +| `0pt.dataset_iceberg_table_mapped` | dataset-iceberg-mapping-service.ts | `lineage_0pt_dataset_iceberg_*` | +| `0pt.iceberg_write_requested` | iceberg-write-service.ts | — | +| `0pt.iceberg_snapshot_created` | iceberg-write-service.ts | `lineage_0pt_iceberg_snapshot_*` | +| `0pt.document_captured` | document-capture-service.ts | `lineage_0pt_document_captured_*` | +| `0pt.document_extracted` | document-extraction-service.ts | `lineage_0pt_document_extracted_*` | +| `0pt.external_record_written` | external-writeback-service.ts | `lineage_0pt_external_write_*` | + +> ⚠️ Utan `AUD0_URL` är emissionen **no-op** (klientkontraktet) — lucka S6. +> Ingen live-AUD0-endpoint verifierad för 0pt ännu (klientdokkommentar). + +## 5. Beroendepilar (AR-8, nedåt endast) + +```mermaid +flowchart TD + UI[0pt.app UI] --> API[Next.js API-routes] + API --> CAP[src/ capability-lagret] + CAP --> CL[CL0UD policy · fail-open] + CAP --> ST[ST0RE artefakter/lakehouse] + CAP --> ND[N0D jobb] + CAP --> AU[AUD0 audit · no-op utan URL] + CAP --> EN[FastAPI-engine services/api] + EN --> SRC[Komplienta källor + bypass-stack] + CL -.->|K1| SAX[SIAX Cloud (K1) - endast nedåt, inga K2-K5] + ST -.->|K1| SAX + ND -.->|K1| SAX + AU -.->|K1| SAX +``` + +AR-8-status: **VERIFIERAT** — 0pt beror endast på K1-tjänster (CL0UD/ST0RE/N0D/AUD0/INF0) ++ externa data-/betalningskällor; inga kundrepon (K2–K5) refereras i koden. + +## 6. Utfallsfil FAS 2 + +✅ `docs/compliance/RELATIONS.md` skapad med 4 Mermaid-diagram. diff --git a/siax.config.json b/siax.config.json index 0d92ed7..0ac39c4 100644 --- a/siax.config.json +++ b/siax.config.json @@ -1,7 +1,8 @@ { - "name": "0PT", - "category": "PLATTFORM", - "subcategory": "Data OS", + "name": "0pt", + "category": "platform", + "subcategory": "data-os", + "appId": "0PT", "owner": "SIAX Technology AB", "packageName": "@siax/0pt", "capabilityPrefix": "0pt", @@ -11,7 +12,8 @@ "domain": "0pt.app", "healthPath": "/api/health" }, - "consumes": ["CL0UD", "AUD0", "ST0RE", "N0D"], + "consumes": ["CL0UD", "ST0RE", "N0D", "AUD0", "INF0"], + "replacesSaaS": ["Apollo", "Cognism", "ZoomInfo", "Clearbit"], "decoupled": false, "designSystem": null } diff --git a/siax.repo.json b/siax.repo.json new file mode 100644 index 0000000..4e83641 --- /dev/null +++ b/siax.repo.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://docs.siax.io/schemas/siax.repo.schema.json", + "name": "0pt", + "category": "platform", + "subcategory": "data-os", + "appId": "0PT", + "capabilityPrefix": "0pt", + "packageName": "@siax/0pt", + "owner": "SIAX Technology AB", + "node": null, + "domains": [ + "0pt.app", + "api.0pt.app" + ], + "deploy": { + "target": "coolify", + "healthPath": "/api/health" + }, + "consumes": [ + "CL0UD", + "ST0RE", + "N0D", + "AUD0", + "INF0" + ], + "replacesSaaS": [ + "Apollo", + "Cognism", + "ZoomInfo", + "Clearbit" + ], + "decoupled": false, + "designSystem": null +}