masterplan-lock / check (push) Successful in 4s
CI (SIAX Cloud) / security (push) Successful in 14s
Security Scan (SIAX Cloud) / security (push) Successful in 23s
CI (SIAX Cloud) / integration (push) Successful in 25s
CI (SIAX Cloud) / quality (push) Successful in 34s
118 lines
7.4 KiB
Markdown
118 lines
7.4 KiB
Markdown
# 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`](CLAUDE.md) + [`docs/`](docs/)
|
|
|
|
> **Architecture (verified against code, not aspirational):**
|
|
> [`docs/architecture/ARCHITECTURE.md`](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.repo.json) +
|
|
> [`siax.config.json`](siax.config.json). Compliance state:
|
|
> [`docs/compliance/`](docs/compliance/) (INVENTORY, RELATIONS, OSS-INVENTORY,
|
|
> GOLDEN-STANDARD-REPORT, BACKLOG, SLUTRAPPORT).
|
|
|
|
## Two planes (see [docs/02-architecture.md](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](docs/05-design-system.md).
|
|
|
|
## Run locally
|
|
|
|
**SIAX toolchain-kontrakt (mise):**
|
|
|
|
```bash
|
|
mise install # pinnar node 22.13.0 + pnpm 9.15.9 (se mise.toml [tools])
|
|
mise run setup # pnpm install --frozen-lockfile
|
|
mise run check # typecheck + lint (snabbt, deterministiskt)
|
|
mise run verify # vitest + next build (full svit)
|
|
mise run build # deploybar artefakt
|
|
```
|
|
|
|
mise är task-entrypoint (`mise.toml`); gate-logiken bor kvar i
|
|
`.gitea/workflows/` och package.json — pinning: `.siax/template-pin.json`.
|
|
|
|
```bash
|
|
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`](Dockerfile)) plus [`.gitea/workflows/cd.yml`](.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`](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`](.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`](infra/docker-compose.yml) (Postgres+pgvector, Redis, api, worker, NocoDB, Metabase, Caddy).
|
|
- Env inventory: [`.env.example`](.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`](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`](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.
|