Claude Opus 5 8f6357044f
CI (SIAX Cloud) / integration (push) Successful in 43s
CI (SIAX Cloud) / security (push) Successful in 21s
CI (SIAX Cloud) / quality (push) Successful in 1m5s
Security Scan (SIAX Cloud) / security (push) Successful in 23s
CI (SIAX Cloud) / security (pull_request) Successful in 24s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m0s
CI (SIAX Cloud) / integration (pull_request) Successful in 42s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 38s
feat(analytics): BI-P018/BI-P019/BI-P021 — execution model, verified cancellation, a budget that stops queries
BI-P018 — every field the prompt names, plus the one it names by its absence.
The record carries `compiled_query_hash` and never the statement, and that is
ENFORCED: `assertNoRawSql` runs before any record is emitted and refuses one
whose `error` field looks like SQL. The realistic leak is ClickHouse's own
error text, which echoes the query — the test uses exactly that string. The
recorder writes at EVERY transition, because a recorder that only writes at
the end loses precisely the executions worth investigating. Illegal state
transitions throw rather than overwrite a terminal row.

The one place raw SQL is retained stays BI-P017's analyst statement history,
where a privileged human ran unreviewed SQL and "who ran what" must survive.
Different record, different retention posture, stated in both files.

BI-P019 — "stops" is VERIFIED, not requested. Aborting the client stops US
waiting, not the server; KILL QUERY without SYNC tells you nothing; even SYNC
can return while the query unwinds. So cancelAndVerify aborts, kills, then
POLLS the process list until the query is GONE or the deadline passes — and
if the deadline passes it returns `verified_stopped: false` rather than a
cheerful `true`. The return type is an outcome object, not a boolean, so a
caller cannot mistake "we asked" for "it stopped". An unreachable engine is
read as "still running" (fail closed), so the kill is still attempted at the
moment an operator most needs it to be.

Proven live against ClickHouse 24.8.14.39, with the counterfactual first:
  * an identical bomb left alone IS still running after 2s — so "gone after
    we cancelled" is not just "the query was short";
  * the cancelled query had read 6,559,476,156 rows, and was verified gone
    57ms after the request;
  * system.query_log records ExceptionWhileProcessing with code 394,
    QUERY_WAS_CANCELLED — ClickHouse's verdict, not ours.

BI-P021 — the honest version. A budget checked once before execution bounds
nothing, and the module says so in its first paragraph. ClickHouse's
max_rows_to_read bounds ONE query; it cannot express "this tenant may scan X
per hour", which is what a budget is for. So enforcement polls the engine's
live read_rows/read_bytes counters and CANCELS the running query, through
BI-P019 with verification, when window spend would be exceeded.

Measured live: a 1,000,000-row window cancelled the query at 130,883,409 rows,
92ms in, verified stopped, code 394. THE OVERSHOOT IS DOCUMENTED, in the module
and in the evidence: enforcement is granular to the poll interval, so this is
a bound of the form "within roughly one poll interval of engine throughput",
not a hard cap. Quoting it as a hard cap would be wrong.

Two more things stated rather than implied:
  * `enforceInFlight: false` is reported by describeEnforcement() as
    "NOT ENFORCED — this budget is advisory", and the constructor REFUSES to
    accept enforceInFlight without a process control;
  * an unshared window store is reported as non-binding across replicas
    ("with N replicas a tenant can spend up to N times this budget").
  * a query the budget killed is still charged for the work it burned. Not
    charging is how a tenant learns the cheapest query is a cancelled one.

Evidence: evidence/bi-p019-p021/cancellation-and-budget.json
268 unit tests, 7 live tests. typecheck + eslint clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 02:26:05 +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
26 MiB
Languages
TypeScript 90.3%
Python 5.5%
JavaScript 2.1%
PLpgSQL 1.4%
Shell 0.3%
Other 0.4%