diff --git a/siax.repo.json b/siax.repo.json new file mode 100644 index 0000000..aa1cf06 --- /dev/null +++ b/siax.repo.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://git.siax.io/sax3l/siax-standard/raw/branch/main/schema/siax.repo.schema.json", + "repo": "0pt", + "standardVersion": "2.0", + "category": "platform", + "subcategory": "data-os", + "appId": "0PT", + "capabilityPrefix": "0pt", + "packageName": "@siax/0pt", + "owner": "SIAX Technology AB", + "codeowners": [ + "@sax3l" + ], + "lifecycle": "active", + "operationalState": "running", + "gitHost": "git.siax.io", + "node": null, + "domains": [ + { + "fqdn": "0pt.app", + "env": "prod", + "purpose": "Next.js edge plane -- marketing, catalog, order flow, customer/admin portal, capability API. LIVE på SIAX-flottan via signerad release-kedja (probe 2026-09-22: HTTP 200, /api/ready ready:true, db ok, engine ok). Tidigare Vercel 402-probe 2026-09-07 är föråldrad — cutover till flottan genomförd.", + "registrar": "verifierad via release-kedjan (se docs/runbook/) — BACKLOG P0-15 kvarstår för registrar-autentisering" + }, + { + "fqdn": "api.0pt.app", + "env": "prod", + "purpose": "Target API host (Caddy) -- documented target in contracts/openapi.yaml servers list, never live. Probe 2026-09-07 `curl -sSI https://api.0pt.app/health` returned HTTP 404 with server: Vercel and x-vercel-error: DEPLOYMENT_NOT_FOUND", + "registrar": "EJ VERIFIERAT fran detta repo -- se docs/architecture/ARCHITECTURE.md SS6/SS9 (BACKLOG P0-15)" + } + ], + "consumes": [ + "CL0UD", + "ST0RE", + "N0D", + "AUD0", + "INF0" + ], + "consumedBy": [], + "children": [ + { + "path": "app", + "purpose": "Next.js edge plane -- UI + capability/order/payment API route handlers", + "lifecycle": "active" + }, + { + "path": "services/api", + "purpose": "FastAPI data engine (orchestrator + workers) -- legal sourcing chain, estimates/orders/screening", + "lifecycle": "active" + }, + { + "path": "services/scrapers", + "purpose": "Scraper stack including WAF-bypass code -- kept per a dated, attributed account-owner decision under active review; NOT part of the compliant sourcing chain (see SECURITY.md, CLAUDE.md SS1)", + "lifecycle": "active" + }, + { + "path": "packages/schemas", + "purpose": "Shared JSON Schema definitions for 0pt data contracts (dataset/iceberg/lineage/signal/rate-policy)", + "lifecycle": "active" + } + ], + "replacesSaaS": [ + "Apollo", + "Cognism", + "ZoomInfo", + "Clearbit" + ], + "contracts": { + "openapi": "contracts/openapi.yaml" + }, + "decoupled": false +} diff --git a/tests/repo/siax-doctor.test.ts b/tests/repo/siax-doctor.test.ts index a18a7e3..026d092 100644 --- a/tests/repo/siax-doctor.test.ts +++ b/tests/repo/siax-doctor.test.ts @@ -44,17 +44,31 @@ function runDoctor(root?: string): { code: number; report: DoctorReport } { /** A fixture tree carrying only the two files the GOV-06 checks read. */ function fixture(repo: unknown, evidence: unknown): string { const dir = mkdtempSync(path.join(tmpdir(), "siax-doctor-fixture-")); - writeFileSync(path.join(dir, "siax.repo.v3.json"), JSON.stringify(repo, null, 2)); + writeFileSync(path.join(dir, "siax.repo.json"), JSON.stringify(repo, null, 2)); mkdirSync(path.join(dir, "evidence"), { recursive: true }); writeFileSync(path.join(dir, "evidence", "operational-state.json"), JSON.stringify(evidence, null, 2)); return dir; } -const REAL_REPO = JSON.parse(readFileSync(path.join(REPO_ROOT, "siax.repo.v3.json"), "utf8")); +const REAL_REPO = JSON.parse(readFileSync(path.join(REPO_ROOT, "siax.repo.json"), "utf8")); const REAL_EVIDENCE = JSON.parse( readFileSync(path.join(REPO_ROOT, "evidence", "operational-state.json"), "utf8"), ); +// FIXTURE-BAS: den HISTORISKA, dokumenterade lögner-paret (down + 402/404) +// som en SYNTETISK post — mutationstesterna nedan muterar denna bas, inte +// repots NUVARande evidens (som med rätta är running + 200 sedan flottan- +// cutovern: testerna ska aldrig flippa när verkligheten flippar). +const HISTORIC_EVIDENCE = { + ...REAL_EVIDENCE, + operationalState: "down", + checkedAt: "2026-09-07T00:00:00Z", + probes: [ + { fqdn: "0pt.app", env: "prod", url: "https://0pt.app/api/health", httpStatus: 402, ok: false, note: "server: Vercel (historisk proba, fixture)" }, + { fqdn: "api.0pt.app", env: "prod", url: "https://api.0pt.app/api/health", httpStatus: 404, ok: false, note: "server: Vercel (historisk proba, fixture)" }, + ], +}; + /** The GOV-06 failure detail for a fixture, or null when GOV-06 passed. */ function gov06Failure(root: string): string | null { const { report } = runDoctor(root); @@ -96,67 +110,59 @@ describe("GOV-06: a FALSE operationalState is detected (the historical defect)", for (const d of dirs) rmSync(d, { recursive: true, force: true }); }); - it("accepts the repo's real, honest pairing (running + live 200/ready probes) as the control", () => { - expect(gov06Failure(track(fixture(REAL_REPO, REAL_EVIDENCE)))).toBeNull(); + it("accepts the honest pairing (down + 402/404, den historiska lögner-posten) as the control", () => { + expect(gov06Failure(track(fixture({ ...REAL_REPO, operationalState: "down" }, HISTORIC_EVIDENCE)))).toBeNull(); }); - it("rejects operationalState 'down' when the evidence was recorded for 'running'", () => { - const detail = gov06Failure(track(fixture({ ...REAL_REPO, operationalState: "down" }, REAL_EVIDENCE))); - expect(detail).toMatch(/down/); + it('rejects operationalState "running" when the evidence was recorded for another state', () => { + const detail = gov06Failure(track(fixture({ ...REAL_REPO, operationalState: "running" }, HISTORIC_EVIDENCE))); + expect(detail).toMatch(/running/); expect(detail).toMatch(/operational-state\.json/); }); - it('rejects operationalState "down" when the evidence was recorded for "running"', () => { - const detail = gov06Failure(track(fixture({ ...REAL_REPO, operationalState: "down" }, REAL_EVIDENCE))); - expect(detail).toMatch(/down/); - expect(detail).toMatch(/operational-state\.json/); - }); - - it('rejects operationalState "down" when the recorded probes are 200/ready', () => { - const detail = gov06Failure( - track( - fixture( - { ...REAL_REPO, operationalState: "down" }, - { ...REAL_EVIDENCE, operationalState: "down" }, - ), - ), - ); - expect(detail).toMatch(/but these prod hosts answered/); - }); - - it("rejects an `ok: false` hand-written next to a 2xx status", () => { + it('rejects operationalState "running" when the recorded probes are 402/404', () => { const detail = gov06Failure( track( fixture( { ...REAL_REPO, operationalState: "running" }, - { - ...REAL_EVIDENCE, - operationalState: "running", - probes: (REAL_EVIDENCE.probes as { ok: boolean; httpStatus: number }[]).map((p) => ({ ...p, ok: false })), - }, - ), - ), - ); - expect(detail).toMatch(/records ok=false next to httpStatus/); - }); - - it('rejects operationalState "running" when probes record 402/404 (the historical defect)', () => { - const detail = gov06Failure( - track( - fixture( - { ...REAL_REPO, operationalState: "running" }, - { - ...REAL_EVIDENCE, - probes: (REAL_EVIDENCE.probes as { httpStatus: number; ok: boolean }[]).map((p) => ({ - ...p, - httpStatus: 402, - ok: false, - })), - }, + { ...HISTORIC_EVIDENCE, operationalState: "running" }, ), ), ); expect(detail).toMatch(/but the recorded probes say otherwise/); + expect(detail).toMatch(/402|404/); + }); + + it("rejects an `ok: true` hand-written next to a non-2xx status", () => { + const detail = gov06Failure( + track( + fixture( + { ...REAL_REPO, operationalState: "running" }, + { + ...HISTORIC_EVIDENCE, + operationalState: "running", + probes: (HISTORIC_EVIDENCE.probes as { ok: boolean }[]).map((p) => ({ ...p, ok: true })), + }, + ), + ), + ); + expect(detail).toMatch(/records ok=true next to httpStatus/); + }); + + it('rejects operationalState "down" when a prod host is recorded as answering', () => { + const detail = gov06Failure( + track( + fixture({ ...REAL_REPO, operationalState: "down" }, { + ...HISTORIC_EVIDENCE, + probes: (HISTORIC_EVIDENCE.probes as { httpStatus: number; ok: boolean }[]).map((p) => ({ + ...p, + httpStatus: 200, + ok: true, + })), + }), + ), + ); + expect(detail).toMatch(/"down" but these prod hosts answered/); }); it("rejects a liveness claim backed only by stale evidence", () => { @@ -166,10 +172,10 @@ describe("GOV-06: a FALSE operationalState is detected (the historical defect)", fixture( { ...REAL_REPO, operationalState: "running" }, { - ...REAL_EVIDENCE, + ...HISTORIC_EVIDENCE, operationalState: "running", checkedAt: stale, - probes: (REAL_EVIDENCE.probes as { httpStatus: number; ok: boolean }[]).map((p) => ({ + probes: (HISTORIC_EVIDENCE.probes as { httpStatus: number; ok: boolean }[]).map((p) => ({ ...p, httpStatus: 200, ok: true, @@ -192,7 +198,7 @@ describe("GOV-06: a FALSE operationalState is detected (the historical defect)", { fqdn: "invented.0pt.app", env: "prod", purpose: "x", registrar: "x" }, ], }, - REAL_EVIDENCE, + HISTORIC_EVIDENCE, ), ), ); @@ -207,7 +213,7 @@ describe("GOV-06: a FALSE operationalState is detected (the historical defect)", ...REAL_REPO, domains: [{ fqdn: "https://0pt.app/health", env: "prod", purpose: "x", registrar: "x" }], }, - REAL_EVIDENCE, + HISTORIC_EVIDENCE, ), ), );