Claude Opus 5 84bb9faa4f
CI (SIAX Cloud) / security (push) Successful in 41s
Security Scan (SIAX Cloud) / security (push) Successful in 40s
CI (SIAX Cloud) / integration (push) Successful in 52s
CI (SIAX Cloud) / quality (push) Successful in 1m5s
CI (SIAX Cloud) / security (pull_request) Successful in 31s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 29s
CI (SIAX Cloud) / integration (pull_request) Successful in 45s
CI (SIAX Cloud) / quality (pull_request) Successful in 53s
feat(analytics): BI-P002..BI-P012 analytics core — domain model, tiers, contracts, Arrow, ClickHouse engine, isolation, governance
Implements the eight BI program prompts that make 0pt the canonical SIAX
analytics capability. Every file is NEW: not one existing file is modified,
and src/analytics/clickhouse-analytics.ts is byte-identical to main.

BI-P002 — the nineteen canonical entities, verbatim, with tenant_id +
project_id on every tenant-owned record. sql/008 gives each one a table.
The four version entities BI-P002 names as immutable are enforced by BEFORE
UPDATE/DELETE triggers, not by a TypeScript `readonly` — proven by direct SQL
against a live Postgres.

BI-P003 — RAW/NORMALIZED/CURATED/SERVING with the read rule enforced:
assertReadableByBiSurface refuses a RAW dataset to a dashboard unless a
recorded exception exists. All eight required declarations are NOT NULL.

BI-P004 — DatasetContract and a fail-closed compatibility gate. Fifteen
breaking-change classes are each tested twice: refused under a minor bump,
accepted under a major one.

BI-P005 — Arrow IPC alongside JSON, with a hand-written FlatBuffers writer so
no npm dependency (or CVE surface) is added. Conformance comes from three
independent implementations, not from self-agreement: pyarrow 25.0.1 and
DuckDB 1.5.5 read identical values from both ClickHouse's Arrow and ours, and
ClickHouse's own Arrow C++ ingests our 20,000-row batch with exact aggregates.

BI-P009 — SiaxAnalyticsEngine with all eight capabilities. The existing
ClickHouseAnalytics is COMPOSED, never replaced. executeQuery (analyst SQL) is
declared and deliberately refused with CAPABILITY_UNAVAILABLE until BI-P017 and
BI-P033 land, rather than opening the raw-SQL hole BI-P011 enumerates.

BI-P010 — four purpose-built tables, not one giant one, and the difference is
measured against the counterfactual: 48.8ms/40,960 rows vs 174.4ms/5,400,000
rows for the same question; 5/660 granules vs 660/1149.

BI-P011 — layered isolation, each layer proven with the layer above removed.
Without the forced predicate the same statement returns 50,050 (both tenants);
with it, t_alpha gets 50. Without a row policy an unrestricted user sees 2
tenants; the restricted user running the IDENTICAL statement sees 1.

BI-P012 — every named limit, fired individually and identified by ClickHouse
error code, plus the half usually skipped: an unrelated tenant is timed while
a real CPU bomb is in flight and must still return the CORRECT answer.

Three defects found by writing tests that can fail:
  * `CHECK (array_length(purposes,1) >= 1)` can NEVER fail — array_length is
    NULL for '{}' and a NULL CHECK passes. Fixed with coalesce(); the test
    that caught it is pinned.
  * EXPLAIN ESTIMATE run under the caller's own max_rows_to_read fails with
    code 158 exactly when the estimate would be over budget. Planner calls now
    use a narrower envelope.
  * result_overflow_mode=break returns HTTP 200 with 65,409 of 100,000 rows
    and no indication it is short. Every SELECT ships `throw`.

Verified rather than assumed: server7's ClickHouse holds `opt_scraped` (51
tables, 407,793,471 rows, `persons`/`cz_owners` included) — the b0ts plane this
module is prohibited from touching — has no `opt_analytics` database, zero
tenant_id columns and zero row policies. Nothing there was modified; every
proof ran against disposable containers.

Evidence: evidence/bi-p002-p012/{test-transcript.txt,bi-p010-benchmark.json,
bi-p005-arrow-roundtrip.json,server7-clickhouse-probe.md}
Docs: docs/analytics/BI_ANALYTICS_CORE.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 23:01:27 +02:00
2026-06-24 14:47:12 +00:00
2026-06-24 14:47:12 +00:00
2026-06-24 14:47:12 +00:00
2026-06-24 14:47:12 +00:00
2026-09-06 03:01:40 +00:00
2026-09-06 03:01:40 +00:00
2026-06-24 14:47:12 +00:00
2026-06-24 14:51:57 +00:00

0pt — your data

Data services on demand for the Nordics + Europe. Compose a data job, pay 50 % to start, watch production live, validate with full provenance, deliver anywhere. Owned by SIAX Technology AB. Honest accuracy is the moat: every field carries source, freshness and confidence; nothing is guessed.

Live: https://0pt.app · Contract: CLAUDE.md + docs/

Architecture (verified against code, not aspirational): docs/architecture/ARCHITECTURE.md. It documents the real API surface, the real persistence story, and the known security gaps — including several places where this README is optimistic. Read it before trusting any capability claim below. Repo identity + estate classification: siax.repo.json + siax.config.json. Compliance state: docs/compliance/ (INVENTORY, RELATIONS, OSS-INVENTORY, GOLDEN-STANDARD-REPORT, BACKLOG, SLUTRAPPORT).

Two planes (see docs/02-architecture.md)

  • Edge (Vercel, this app) — marketing, catalog, the order lifecycle, customer portal, admin portal, and the API route handlers. Defers to the data engine when ENGINE_URL is set.
  • Engine (services/api, runs on a VPS) — FastAPI orchestrator + worker pipeline doing the compliant sourcing (official API → bulk → authorized web → licensed → else level 0). Never on Vercel (long jobs). Bypass/stealth/proxy-rotation/fake-account paths are excluded by design (CLAUDE.md §1).

Routes

Area Routes
Marketing / (hero, filosofi, katalog, motorn, visualiseringar, täckning, editorial, bevis, priser, footer)
Catalog /katalog, /katalog/[id]
Sourcing map /kallor
Order lifecycle /bestall → /bestall/forskott → /order/[id] → /order/[id]/validera
Customer portal /portal, /portal/subscriptions, /portal/files, /portal/integrationer, /portal/settings
Admin portal /admin, /admin/sources, /admin/jobs, /admin/customers
API /api/{health,estimates,catalog,sources,orders,orders/[id],subscriptions,admin/metrics,uploads,auth/*,payments/*,webhooks/stripe,connections/db-grant}

Design system

Mono/editorial, light, radius 0, Inter + JetBrains Mono, single red #e40014, animated grain, scroll-reveal motion. No photography — imagery is rendered data (DataArtifact). Every fact shows a provenance square (ProvenanceBadge). Full spec: docs/05-design-system.md.

Run locally

pnpm install
pnpm dev                       # Next.js on http://localhost:3000

# data engine (separate, optional)
cd services/api && pip install -r requirements.txt && uvicorn orchestrator.main:app --reload

Deploy

  • Config target (as of 2026-08-09): siax.config.json declares deploy.target: "coolify", matching every other SIAX Cloud OS repo (n0d, st0re, aud0, ...) — a Dockerfile "for Coolify" (already committed, see Dockerfile) plus .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 (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 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 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 (Postgres+pgvector, Redis, api, worker, NocoDB, Metabase, Caddy).
  • Env inventory: .env.example.
  • Auth on /api/0pt/* is fail-closed: with AUTH_ENFORCE unset the middleware REQUIRES a verified Zitadel Bearer token (401 without one). Only the literal AUTH_ENFORCE=false disables it, and that is refused when NODE_ENV=production (the process throws at startup rather than serving anonymously). Caveat (live-verified 2026-08-10): the deployed instance still answers GET /api/0pt with 200 anonymously — the middleware appears not to run in production (gap S1, root cause unknown). Do not rely on this being enforced until an anonymous request gets a real 401.
  • Fonts: self-hosted via @fontsource-variable/inter + @fontsource-variable/jetbrains-mono (no Google Fonts / next/font/google).
  • API contract (SSOT): contracts/openapi.yaml.

Status

Frontend, full order lifecycle, customer + admin portals, edge API, payment/auth/embed infrastructure, the compliant data engine, schema and infra are all in place and building green. Integrations are env-guarded and activate when their keys/DB are provided:

  1. Database — Vercel → Storage → Postgres (sets POSTGRES_URL) → durable persistence (schema in sql/001_init.sql).
  2. Stripe + Resend keys → payments + email.
  3. VPS for the engine → set ENGINE_URL.
  4. AUTH_SECRET + DEV_LOGIN_KEY → login (full OAuth via Auth.js lands with the DB).

© 2026 SIAX Technology AB. Not affiliated with Protosell.

S
Description
No description provided
Readme
25 MiB
Languages
TypeScript 90.2%
Python 5.5%
JavaScript 2.1%
PLpgSQL 1.5%
Shell 0.3%
Other 0.4%