CI (SIAX Cloud) / security (push) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
CI (SIAX Cloud) / quality (push) Successful in 44s
CI (SIAX Cloud) / security (pull_request) Successful in 21s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / quality (pull_request) Successful in 42s
BACKLOG P1-1: siax.repo.json/siax.config.json rewritten to be schema-valid against sax3l/siax-standard's actual v2.0 schemas (lifecycle, operationalState, gitHost, domains-as-objects, consumedBy, children, contracts -- validated with jsonschema, not just eyeballed). config.json restructured to the real deploy-descriptor shape (framework/build/start/ port/healthcheck/environments) instead of duplicating repo.json's identity fields, which the schema doesn't allow. BACKLOG P1-2: 3 ADRs for decisions already made and evidenced elsewhere in this repo (Coolify-not-Vercel, Zitadel-not-NextAuth, Iceberg-format pointer to n0d ADR-0030) -- retroactive documentation, not new decisions. The Stripe/Revolut and services/scrapers/* questions are explicitly NOT written as ADRs here; both are account-owner-gated or actively under review elsewhere (see docs/architecture/decisions/README.md). BACKLOG P1-3: CHANGELOG.md from real git log history (no tags/releases exist yet -- this doesn't invent version numbers that were never cut). BACKLOG P1-19: `pnpm siax:doctor` (scripts/siax-doctor.mjs, AGENT-04) -- zero-dependency, checks required files + manifest shape, prints control-IDs. .devcontainer/devcontainer.json (DX-03). compose.dev.yaml (DX-02 -- UNVERIFIED, no Docker available in this environment to smoke-test, flagged in the file itself). All 4 prompts + the index rewritten to AGENT-03 shape (goal/context/prerequisites/scope/contract/acceptance-criteria/ control-ID/forbidden-actions). BACKLOG P1-20: docs/architecture/ARCHITECTURE.md migrated to the v2.0 9-heading template -- new §5 "Ytor och paritet" (capability x API/CLI/MCP/console coverage table, grounded in the same registry facts docs/02-architecture.md already established), §6-9 renumbered from the old §5-8 (all internal cross-references fixed, CLAUDE.md's own §-numbers left untouched). docs/api/ added (points at contracts/openapi.yaml as the one SSOT instead of duplicating it as drift-prone prose). BACKLOG P1-21: packages/schemas now has a real package.json (was loose JSON files with no package -- pnpm-workspace.yaml's packages/* glob matched an empty package). Verified `pnpm install --frozen-lockfile` and the full typecheck/test/build suite still pass with 2 real workspace projects. apps/ restructuring explicitly NOT attempted (BACKLOG's own effort estimate is "L" / large -- moving the whole app tree is a bigger, riskier change than belongs in this pass). Import-boundary check added via dependency-cruiser (ARK-14) -- installed for real, config tested against this codebase (179 modules, 310 deps, 0 violations), wired as `pnpm run deps:check` (advisory, not yet a CI gate). BACKLOG P2-5: docs/02-architecture.md's "Hosting" section marked SUPERSEDED (the Vercel plan was superseded by the Coolify deploy.target flip, 2026-08-09 -- ADR-0001). README.md/.env.example were checked and are already accurately framed (live-on-Vercel vs. config-target-is-Coolify) -- not touched. BACKLOG P3-5: 2 stale github.com/sax3l/0pt/pull/3 links removed (the PR merged long ago, .env.example is real and current) -- docs/09-build-plan.md, docs/08-infrastructure.md. The "two diverged remotes, unresolved which is canonical" language elsewhere (CLAUDE.md, AGENTS.md, SECURITY.md, etc.) is deliberately NOT touched -- that's a live, correctly-flagged, account-owner- owned open question per the Gitea-exclusivity mandate, not a stale link. BACKLOG P6 (19 items): concrete artifacts for the ones that are actually a file (.editorconfig, dependency-cruiser, deprecation policy, K8s reference manifest, .actrc, Makefile, ONBOARDING.md); docs/guides/P6-GUIDES.md for the rest (CLI-13, DOC-18, UI-30, IAM-19, PAY-11, AI-18, OBS-21, TEST-20, NET-19, SCALE-13, OSS-10, AGENT-13) -- each grounded in this repo's actual code/gaps, not generic advice. NOT attempted (out of this task's scope, noted for the record): - P2-1 (cl0ud app-registry.ts mismatch) -- lives in a different repo (sax3l/cl0ud), not cloned/authorized for this task's single-repo PR flow. - The CI "doctor step" half of P1-15 -- deliberately left out of this PR's .gitea/workflows/ci.yml to avoid a 3-way merge conflict with ci/security-headers-and-scanning, which already restructured that file; add it as a follow-up once that PR merges. This branch was authored independently of, but shares docs/architecture/ ARCHITECTURE.md and docs/slo.md with, fix/honest-health-check and ci/security-headers-and-scanning -- expect a small, normal merge conflict if this is rebased after either of those merge first (both already rebased cleanly against each other and against main as of this commit).
246 lines
20 KiB
Markdown
246 lines
20 KiB
Markdown
# 09 · Build plan
|
||
|
||
Phased, in dependency order. **Finish a phase to its acceptance criteria before the next.** Each phase = small, reviewable commits. Reconcile with existing code rather than rewriting wholesale.
|
||
|
||
> **Status callouts added 2026-07-19.** Each phase below now carries a `Status:` line, grep/read-verified
|
||
> against `main` this pass. These are conservative on purpose: a phase is only called **Done** when this
|
||
> pass found real, working code satisfying its Accept criteria; anything else is **Partial** (with the
|
||
> specific evidence and gap named) or **Not started**. No phase is upgraded to Done without a code
|
||
> citation. Where a referenced doc (e.g. `docs/design/...`) doesn't exist, that's flagged rather than
|
||
> silently worked around. See `docs/08-infrastructure.md` for the full env/security grounding these
|
||
> statuses draw on.
|
||
|
||
## Phase 0 — Foundation & repo
|
||
- Monorepo structure (`docs/08`). Migrate existing `src/orchestrator` + `src/workers` into `services/api`.
|
||
- Postgres schema + migrations (`docs/03`); `pgvector` enabled. `.env.example`.
|
||
- `docker-compose` up (postgres, redis, api, worker, nocodb, metabase, caddy). `/health` green.
|
||
- CI skeleton (lint/typecheck/build).
|
||
- **Accept:** `docker compose up` runs the whole stack locally; migrations apply; `/health` returns ok for db + queue.
|
||
- **Status: Partial.**
|
||
- Repo structure exists but diverged from the `apps/web`/`packages/shared` layout `docs/08` originally
|
||
sketched — it settled on `app/` (Next.js, repo root), `lib/`, `src/` (platform clients/services), and
|
||
`services/api/` (FastAPI). `docs/08-infrastructure.md` now documents the structure as-built.
|
||
- Migration to `services/api/orchestrator` + `services/api/workers` is **done** (verified: those
|
||
directories exist and contain `main.py`/`adaptive_router.py`/`pipeline.py`/etc.; no `src/orchestrator`
|
||
or `src/workers` remain at the old paths).
|
||
- Postgres schema is real: `sql/001_init.sql` (`CREATE EXTENSION vector`, `CREATE EXTENSION pgcrypto`,
|
||
17 tables incl. `orgs`, `users`, `orders`, `jobs`, `audit_log`, `bridge_provenance`, `db_grants`,
|
||
`payments`) + `sql/004_iceberg_write_boundary.sql`.
|
||
**No `sql/002_*` or `sql/003_*` exists anywhere in this repo's history** — some other docs
|
||
(`docs/ICEBERG_WRITE_BOUNDARY.md` etc.) cite a `sql/002_p0_dataset_quality.sql` that was never built;
|
||
see `docs/08-infrastructure.md`'s "Schema state" section.
|
||
- `.env.example` — **now exists and is merged to `main`** (BACKLOG P3-5: the
|
||
stale link to the unmerged `github.com/sax3l/0pt/pull/3` that used to sit
|
||
here has been removed — that PR has long since landed, `.env.example` is
|
||
a real, current, gitignore-exempted file at the repo root today).
|
||
- `infra/docker-compose.yml` and `infra/Caddyfile` are real, committed files (not sketches) covering
|
||
exactly the services listed. **This pass found no evidence they've ever actually been run** — no
|
||
CI, no deploy log, no reachable host checked. "File exists and looks correct" ≠ "verified to run";
|
||
treat the Accept criterion ("docker compose up runs... /health returns ok") as unverified.
|
||
- CI skeleton — **not built.** There is no `.github/workflows/` directory in this repo at all. `pnpm
|
||
lint`/`typecheck`/`test` exist as local scripts only.
|
||
|
||
## Phase 1 — Design system in code
|
||
- Tailwind + shadcn; `globals.css` (grain + reveal keyframes) and `useReveal` verbatim (`docs/05`).
|
||
- Build **DataArtifact** primitive (table/map/schema/chart/grid) and **ProvenanceBadge** (`docs/design` prompts 5.1, 2.11).
|
||
- **Accept:** a sample page renders mono tokens, a DataArtifact animates on scroll, reduced-motion respected, focus rings visible.
|
||
- **Status: Partial — real components exist; scroll-motion/reduced-motion/focus-ring behavior not
|
||
independently exercised this pass.**
|
||
- Tailwind + shadcn/radix stack: confirmed real in `package.json` (`tailwindcss`, `@radix-ui/*`,
|
||
`class-variance-authority`, `tailwind-merge`, `tailwindcss-animate`).
|
||
- `hooks/use-reveal.ts`, `components/data-artifact.tsx`, `components/provenance-badge.tsx` all exist
|
||
and are used across `app/katalog`, `app/kallor`, `app/bestall`, `app/order/[id]`, and most
|
||
`components/sections/*` files (grep-confirmed).
|
||
- `docs/design/0pt-v0-build-brief.md` and `docs/design/0pt-design-coverage-and-visuals.md` (the
|
||
"prompts 5.1, 2.11" this bullet references) **do not exist anywhere in this repo** — confirmed via
|
||
full-repo search; there is no `docs/design/` directory at all. `CLAUDE.md`'s own doc index has
|
||
already been corrected to flag this as a gap rather than list them as real. Treat any reference to
|
||
specific numbered "build-brief prompts" in this build plan as pointing at a doc that was never
|
||
written — not this file's scope to author that content.
|
||
- Reduced-motion handling, focus-ring visibility, and actual scroll-triggered animation behavior were
|
||
not executed/verified in this pass (no browser run performed) — code presence is confirmed, runtime
|
||
behavior is not.
|
||
|
||
## Phase 2 — Marketing + catalog (placeholder data)
|
||
- Landing components top-to-bottom (build-brief 2.1–2.10): Header, Hero, Philosophy, Catalog teaser, Engine, Visualisation gallery, Coverage, Editorial, Proof, Footer.
|
||
- Full **Catalog** page + **Dataset detail** + **Sourcing-map** page (coverage doc 5.4). Postgres full-text search.
|
||
- All with loading/empty/error states + mobile.
|
||
- **Accept:** marketing site + catalog browse work end-to-end on placeholder catalog rows; one continuous scroll reads well; DoD met per screen.
|
||
- **Status: Partial.**
|
||
- Landing section components are real: `components/sections/{hero,philosophy,gallery,editorial,
|
||
pricing,technology,testimonials,footer,featured-products,collection}-section.tsx` all exist.
|
||
- `app/katalog/page.tsx`, `app/katalog/[id]/page.tsx`, `app/kallor/page.tsx` all exist.
|
||
- **Postgres full-text search was not found** — grepped for `to_tsvector`/`websearch_to_tsquery`
|
||
across the whole repo, zero matches. Catalog browsing today reads from `lib/data.ts` placeholder
|
||
data, not a full-text query against Postgres. This Accept criterion's "catalog browse... on
|
||
placeholder catalog rows" half is plausible; the Postgres full-text search half is not built.
|
||
- Loading/empty/error states + mobile + DoD-per-screen were not independently audited screen-by-screen
|
||
this pass — `components/states.tsx` (`LoadingSkeleton`, `ErrorState`) exists and is imported widely,
|
||
which is evidence toward this but not a full verification.
|
||
|
||
## Phase 3 — Auth & portal shell
|
||
- Auth.js + Postgres adapter; sign in/up/verify/forgot. `orgs`/`users`.
|
||
- Portal shell + Dashboard ("Mina beställningar") with empty state.
|
||
- **Accept:** a user can sign up, land in an empty dashboard, sign out; routes protected.
|
||
- **Status: Not done — this is the most consequential gap in the whole repo, not a minor loose end.**
|
||
- **There is no Auth.js integration.** `lib/auth.ts` is a from-scratch, ~40-line HMAC-SHA256 session
|
||
scaffold (Web Crypto, no dependency) whose own comment states: "Production auth = Auth.js + Postgres
|
||
adapter + OAuth (docs/02) — wired once the database is provisioned." `app/api/auth/login/route.ts`
|
||
is a **dev-only** login gated by a shared `DEV_LOGIN_KEY`, not sign-up/verify/forgot.
|
||
- `orgs` and `users` tables exist in `sql/001_init.sql` (schema is ready), but nothing in the app
|
||
reads/writes them for real session-bound identity today.
|
||
- `app/portal/page.tsx` and sibling portal pages exist (shell is real), but routes are **not**
|
||
protected by any real session check tied to that schema.
|
||
- **Concretely, this means the tenant/org isolation several `0pt.*` API routes assume does not exist
|
||
yet.** `app/api/0pt/lakehouse/mappings/route.ts`, `.../writes/route.ts`,
|
||
`app/api/0pt/sources/rate-policies/route.ts`, `app/api/0pt/sources/[sourceId]/query/route.ts`, and
|
||
`src/services/document-capture-service.ts` all read `tenant_id`/`project_id` straight from the
|
||
request body — anyone can claim any tenant. `app/api/orders/route.ts`'s own `GET` handler carries
|
||
the literal comment `// org scoping added with auth`. This is an open security gap, not a
|
||
two-tier design choice — see `docs/08-infrastructure.md`'s "Security & compliance" section for the
|
||
full list. **Do not build any doc or feature that assumes tenant-scoped auth already exists.**
|
||
|
||
## Phase 4 — Order lifecycle end-to-end (test mode)
|
||
- **Configurator** (2.12) wired to `POST /estimates` (real estimate math in FastAPI).
|
||
- **Deposit checkout** (2.13) → Stripe **test** Checkout → webhook → order `IN_PRODUCTION`.
|
||
- **Production tracker** (2.14) reading `GET /orders/{id}/events` (SSE) — pipeline may be **simulated** at this phase.
|
||
- **Validation & delivery** (2.15): tabs render from a sample delivery; **accept** → `POST /payments/release` (test) → `DELIVERED`; **revise** leaves escrow untouched.
|
||
- AI-assist (`POST /ai/parse`) prefilling the configurator.
|
||
- **Accept:** a full custom order can be configured, deposit paid (test), watched, validated, accepted, and "delivered" — state machine in `docs/01` traversed; escrow split correct.
|
||
- **Status: Partial — the payment/escrow spine is genuinely real; the SSE tracker is not.**
|
||
- `app/api/estimates/route.ts` exists.
|
||
- Deposit checkout is **real, working code**: `app/api/payments/[order_id]/deposit/route.ts` calls
|
||
Stripe's Checkout Sessions API directly (not a stub) and `app/api/webhooks/stripe/route.ts` verifies
|
||
the webhook signature and advances order status via `setStatus`.
|
||
- `app/api/payments/[order_id]/release/route.ts` is also real: it enforces the escrow rule in code —
|
||
balance release is rejected with `409 not_accepted` unless `order.status === "accepted"` — matching
|
||
the "escrow split correct" accept criterion's intent.
|
||
- **`GET /api/orders/{id}/events` (SSE) does not exist.** Only `GET`/`PATCH /api/orders/{id}` were
|
||
found (`app/api/orders/[id]/route.ts`); no `/events` sub-route, and no `EventSource`/
|
||
`text/event-stream`/`ReadableStream` usage anywhere in `app/` (grep-verified). If a production
|
||
tracker is live today, it's polling `GET /api/orders/{id}`, not the SSE stream this bullet describes
|
||
— or it hasn't been built. Either way, the SSE contract as written is not implemented.
|
||
- `app/api/ai/parse/route.ts` is real: a genuine (non-fabricated) keyword/regex heuristic that
|
||
prefills a config object, with a documented fallback to `engineFetch("/ai/parse", ...)` when
|
||
`ENGINE_URL` is set. This one holds up as described.
|
||
|
||
## Phase 5 — Real data engine (Nordic slice)
|
||
- Compliant connectors first: **GLEIF + Brreg + Companies House** (verify access terms; record in `sources.yaml`). Remove any FlareSolverr/bypass path (`docs/06`).
|
||
- Pipeline stages produce real `dim_company` + `fact_financials` with `bridge_provenance`; QA threshold drops low-confidence rows.
|
||
- Production tracker now reflects **real** job metrics.
|
||
- **Accept:** a Nordic company dataset is produced for a real order, every field has provenance, quality report generated, level-0 fields shown honestly (not fabricated).
|
||
- **Status: Partial.**
|
||
- `services/api/sources/sources.yaml` and `connectors.py` are real: GLEIF, Brreg, Companies House,
|
||
PRH, and CVR are all registered, each with an explicit `licence: "... — VERIFY"` tag rather than an
|
||
assumed-clean claim — matches the "verify access terms" instruction.
|
||
- `services/api/workers/adaptive_router.py`'s own comment confirms: "There are NO bypass/stealth/
|
||
proxy-rotation tiers here, by design (CLAUDE.md §1)" — the FlareSolverr/bypass removal is done, at
|
||
least on this repo's `main` (see `docs/08-infrastructure.md`'s "Known open question" about the
|
||
diverged Gitea remote, which independently added such a stack on its own `main` — unresolved which
|
||
remote is canonical).
|
||
- `services/api/workers/pipeline.py` has a real, working confidence-threshold QA drop: `delivered =
|
||
[r for r in deduped if r["confidence"] >= threshold]`, plus an `avg_confidence` figure in its output.
|
||
This is a genuine, narrow QA mechanism inside the Python engine.
|
||
- **This is not the same thing as the "quality report" / quality-check layer once described in
|
||
`docs/ICEBERG_WRITE_BOUNDARY.md`, `docs/11-lakehouse-write-plan.md`, and
|
||
`docs/P0_QUERY_SOURCE_FLOW.md`.** Those three docs used to cite `src/services/quality-check-service.ts`,
|
||
`src/services/quality-report-service.ts`, `src/types/quality-{check,report}.ts`, and
|
||
`src/data-platform/services/catalog-service.ts` as already-built and tested. **None of those files
|
||
has ever existed in this repo's git history, on any branch** — and all three docs have since been
|
||
corrected to say so explicitly (verified this pass), rather than repeating the original claim. So:
|
||
the narrow Python-side confidence filter is real; the broader TS/lakehouse "quality report" this
|
||
Accept criterion likely also intends is not built (see `docs/P0_DATASET_QUALITY_FLOW.md` for the
|
||
honest target spec). Whether `pipeline.py`'s `avg_confidence` output satisfies "quality report
|
||
generated" is a judgment call for whoever runs this phase — flagging rather than deciding it here.
|
||
- Whether an actual Nordic dataset has been produced end-to-end for a real order was not verified
|
||
this pass (would require running the stack).
|
||
|
||
## Phase 6 — Delivery surfaces & integrations
|
||
- Exports: CSV / Parquet / JSON via R2 presigned URLs.
|
||
- Embedded **NocoDB** ("Min data") and **Metabase** dashboards via signed URLs in mono chrome.
|
||
- Integrations: **FiveCRM push**, webhooks, Google Sheets.
|
||
- File **uploads** (Uppy → R2) for matching/enrichment.
|
||
- **Accept:** a delivered dataset is downloadable, viewable in embedded NocoDB + Metabase (no separate login), and pushable to FiveCRM; uploads work.
|
||
- **Status: Not done — this phase is UI-shell-only today.**
|
||
- CSV/Parquet/JSON exports via R2 presigned URLs: not found. `app/api/uploads/route.ts` (the closest
|
||
R2-touching code) is a `501` stub with a hardcoded `put_url: null` — no presign logic exists yet,
|
||
for uploads or exports.
|
||
- `components/embed.tsx` (`EmbeddedView`) is real — a sandboxed iframe shell — but the server-side
|
||
signed-URL generator for Metabase/NocoDB (`METABASE_SECRET_KEY`/`NOCODB_API_TOKEN`) that would feed
|
||
it a real `src` was not found anywhere in this pass.
|
||
- "FiveCRM" appears only as a **destination label string** in `lib/data.ts`, `lib/services.ts`,
|
||
`app/portal/integrationer/page.tsx` (explicitly described in that file's own comment as
|
||
"presentationella toggles" — i.e. presentational, not wired), and as one of several regex-matched
|
||
destination names in `app/api/ai/parse/route.ts`'s heuristic. **No actual FiveCRM API push exists.**
|
||
- `uppy` is not a dependency in `package.json` (checked directly) — the Uppy → R2 upload flow this
|
||
bullet describes has no corresponding package installed, let alone implemented.
|
||
|
||
## Phase 7 — Subscriptions / feeds
|
||
- `subscriptions`; recurring jobs (weekly/daily) delivering **deltas**; webhooks on change.
|
||
- Freshness monitoring; Resend emails (confirmation, "din data är klar", feedback).
|
||
- **Accept:** an order converts to a feed; a scheduled run produces a delta + fires a webhook + email.
|
||
- **Status: Partial — data layer real, scheduling and email are not.**
|
||
- `lib/subscriptions-store.ts` is real CRUD against the `subscriptions` table (with an in-memory
|
||
fallback when no DB is configured) — `createSubscription`/`listSubscriptions` genuinely insert/read.
|
||
- No recurring-job scheduler (cron, queue consumer producing deltas, etc.) was found on the TS side of
|
||
this repo. `services/api/workers/queue.py` exists on the Python side but this pass did not trace
|
||
whether it implements actual delta-producing scheduled runs — flagged as unverified rather than
|
||
assumed either way.
|
||
- **Resend is not wired at all** — grepped for `resend`/`Resend` across the whole repo, zero matches
|
||
outside `RESEND_API_KEY` being listed as an env var. No confirmation/"din data är klar"/feedback
|
||
email has been implemented.
|
||
|
||
## Phase 8 — Admin, hardening, compliance
|
||
- Admin: order queue + scope/quote + escrow release; **source registry & freshness** monitoring; worker/job monitoring; customer + catalog management.
|
||
- Customer **DB-access grant** flow (encrypted, read-only, time-boxed) + revoke.
|
||
- Security pass: RLS, presigned-only files, signed embeds, secret rotation, `audit_log` everywhere; **DPA** published; legal pages.
|
||
- Finalize all loading/empty/error states + mobile across the app.
|
||
- **Accept:** admin can run the business; DB-grant flow works and self-revokes; security checklist passes; DoD met app-wide.
|
||
- **Status: Partial — UI shell real, the security substance is not.**
|
||
- Admin pages exist: `app/admin/{page,jobs/page,sources/page,customers/page,verktyg/page}.tsx`. This
|
||
pass did not verify whether they read real backend data or placeholders.
|
||
- `sql/001_init.sql` defines `audit_log`, `db_grants`, and `payments` tables — schema is ready.
|
||
- **The DB-access grant flow is a stub, not a working feature.**
|
||
`app/api/connections/db-grant/route.ts` returns `501` without `GRANT_ENC_KEY`, and with it set
|
||
returns a hardcoded `201 { grant_id, status: "pending" }` — **no AES-GCM encryption, no read-only
|
||
validation, and no self-revoke logic exist in code today**, despite the route's own comment
|
||
describing that target behavior. See `docs/08-infrastructure.md`'s "Security & compliance" section.
|
||
- RLS enforcement, presigned-only files (blocked on the Phase 6 R2 gap above), signed embeds (blocked
|
||
on the Phase 6 NocoDB/Metabase gap above), and a published DPA were not found as implemented in this
|
||
pass. Treat the "security checklist passes" accept criterion as not met.
|
||
|
||
## Phase 9 — Launch
|
||
- Domain `0pt.app` (Vercel) + subdomains (api/data/dash via Caddy). Sentry + uptime live.
|
||
- Soft launch: Protosell internally + a handful of existing dealer relationships.
|
||
- **Accept:** a real external customer completes an order start→delivery in production; feedback loop running.
|
||
- **Status: Domain is live; soft-launch/customer criterion not verified.**
|
||
- **Verified this pass** (network check performed): `https://0pt.app` returns HTTP 200 and serves this
|
||
repo's own Next.js app (title "0pt — your data", SIAX branding); `GET /api/health` returns
|
||
`{"ok":true,"service":"0pt-web","db":"not_configured","queue":"not_configured",...}`, an exact shape
|
||
match for `app/api/health/route.ts`. README's "Live: https://0pt.app" is confirmed, and the response
|
||
confirms the live deployment has no `DATABASE_URL`/`REDIS_URL` set — see `docs/08-infrastructure.md`'s
|
||
"Hosting topology" section. This does not confirm which git remote/commit is deployed (see the
|
||
diverged-remotes note elsewhere in this doc), or that api/data/dash subdomains or Caddy are live —
|
||
only the root Vercel deployment was checked.
|
||
- **Sentry is not wired** — no `sentry` package in `package.json`, no Sentry config file anywhere in
|
||
the repo (grep-confirmed). `@vercel/analytics` **is** genuinely wired (`app/layout.tsx` renders
|
||
`<Analytics />`), which is a real but much smaller piece of the "Sentry + uptime live" bullet.
|
||
- No evidence either way on the soft-launch/external-customer criterion — out of this doc's ability to
|
||
verify from code alone.
|
||
|
||
---
|
||
|
||
## Working conventions (for Claude Code)
|
||
- Tech docs + identifiers **English**; UI copy **Swedish**.
|
||
- Conventional Commits; one concern per PR; keep diffs reviewable.
|
||
- No secrets in code; update `.env.example` when adding env. (`.env.example` itself currently lives on
|
||
`feature/0pt-env-example` / PR #3 — merge that first, or this instruction has nothing to update yet.)
|
||
- Add/extend tests for engine logic (estimate math, fusion/confidence, dedup) and API contract.
|
||
- When a source's access/licence is unclear, **verify and record in `sources.yaml`** before relying; if disallowed for bulk, route to licensed/partner or mark level 0 — never bypass, never fabricate.
|
||
- Touch the design tokens/motion only via `docs/05`; keep red ≤ once per screen; no photography.
|
||
- If anything here conflicts with existing code, **flag it** in the PR description and propose the reconciliation rather than guessing.
|
||
- **Two git remotes claim to be this repo** (`github.com/sax3l/0pt` and `git.siax.io/sax3l/0pt`), and
|
||
they have independently diverged (see `CLAUDE.md`, `README.md`). Don't assume the checkout you're in
|
||
is the only copy, and don't silently pick one as canonical — that's Simon's decision, flag it if it
|
||
becomes relevant to the phase you're working on.
|