Skip to content

SPEC-001: Baseline — Ported Pipeline + Data Assembler Client Shell

Ref: SPEC-001 · Capability: SUITABILITY-ENGINE · Status: in-progress Repo: suitability-engine · Source: docs/features/001-baseline-ported-pipeline.md Exposed to: Origo (external partner) Created: 2026-08-16

This is the baseline spec, not a design proposal. It documents what client-onboarding#2669 actually scaffolded into this repo — the state as of repo creation — so this repo starts SGE governance with a real, as-built Layer 3 artefact rather than zero specs. The originating design record is SPEC-152 in client-onboarding; read it in full before changing anything here that touches scope, auth, data-access, or deployment topology — those decisions were ratified there, not here. This spec exists so the four stages below (and the one genuinely new piece, the Data Assembler HTTP client) each have a governing artefact that current code can be checked against, per this repo’s Vision Layer 3.

What’s actually built (verified against source, 2026-08-16)

Section titled “What’s actually built (verified against source, 2026-08-16)”
StagePathStatusOriginating spec
Data Assemblersrc/data-client/client.tsTyped HTTP client shell, not a working integration. Every network call throws/fails — the internal read-API it targets (client-onboarding#2670) does not exist yet.SPEC-112 (design precedent only; this stage is a rebuild, not a move)
Recommendation Rulessrc/suitability-rules/ (index.ts, dfm.ts, charges.ts, platform.ts, portfolio.ts, summary.ts, wrapper-selection.ts, audit.ts, persist-audit.ts, errors.ts, types.ts)Moved as-is; import paths changed, behavior unchangedSPEC-113
Template Enginesrc/suitability-template/ (parser, resolver, validate, contract, filters/, charts/, fidelity/, benchmark/)Moved as-isSPEC-108, SPEC-109, SPEC-110, SPEC-121
Readiness / Lineagesrc/suitability-readiness/ (score.ts, trace.ts, field-source-map.ts)Moved as-isSPEC-122, SPEC-127, SPEC-133
Tenant configsrc/tenant-config/ (schema.ts, cache.ts)New glue — an in-memory cache (preloadTenantConfigs()) replacing client-onboarding’s @/lib/config/tenants-lookup direct import for the ported rule modules. Must be preloaded before derive() — no lazy fetch-on-read.n/a (new to this repo)
Public surfacesrc/index.tsLibrary entrypoint re-exporting derive, DataAssemblerClient, tenant-config accessors, readiness scoringn/a
HTTP serversrc/server/ (app.ts, auth.ts, index.ts)New — issue #1. Plain-Node-http server exposing POST /v1/tenants/:tenantId/clients/:clientToken/suitability/export (format=json wired to derive(); format=pdf|docx return 501 — no template rendering exists yet, see Gap 5 below) and GET /healthz. Gated by a SUITABILITY_ENGINE_SERVER_TOKEN shared-secret bearer token (timing-safe compare), mirroring client-onboarding’s SUITABILITY_ENGINE_INTERNAL_TOKEN pattern (client-onboarding#2673) for the symmetric direction. Dockerfile’s CMD now runs this.n/a (new to this repo)

Test coverage carried over: tests/unit/suitability-rules/*, tests/unit/suitability-readiness/*, tests/unit/suitability-template/* (parser + contract), plus one tests/integration/derive-pipeline.smoke.test.ts. No test exists yet for src/data-client/client.ts itself — there is nothing real to test it against until client-onboarding#2670 ships (see Gap 1 below).

Scope (unchanged from SPEC-152 — restated for traceability)

Section titled “Scope (unchanged from SPEC-152 — restated for traceability)”

In scope: the four-stage pipeline above, reached via the new internal read-API rather than direct warehouse access; tenant/branding config lookup for template + display fields.

Explicitly out of scope (per SPEC-152): the suitability-cohort triage layer (WTP/Benchmark-internal operational segmentation) and the end-client viewer UI (moves to client-portal, not this repo).

This spec does not restate SPEC-152’s auth model, deployment topology (Option D self-hosted-first), or data-access decision — those are Layer-0- adjacent ratified decisions covered in this repo’s own Vision and, in full, in SPEC-152 itself. This spec covers only what is built inside this repo’s boundary.

Known gaps (carried over from SPEC-152 and the scaffolding issue, not yet closed here)

Section titled “Known gaps (carried over from SPEC-152 and the scaffolding issue, not yet closed here)”
  1. Internal read-API does not exist yet (client-onboarding#2670). src/data-client/client.ts is a contract-shaped shell; every method will fail (404/ECONNREFUSED) against any real DATA_ASSEMBLER_BASE_URL until that API ships. This is the single hardest blocker to this repo doing anything end-to-end.
  2. Traceability rewire hard-blocker (SPEC-152 §“Traceability and per-client customisation”). As of SPEC-152, client-onboarding’s live export path does not call suitability-rules/derive() at all — it uses a separate hardcoded mapper. Until that’s rewired in client-onboarding, this engine’s rules output (however correct in isolation) is not what an external partner actually receives from any live WTP surface today. Verify current status in client-onboarding before assuming otherwise.
  3. Durable audit persistence. src/suitability-rules/persist-audit.ts posts to the (not-yet-built) internal API rather than writing to Postgres directly, per SPEC-152’s ratified Postgres-audit decision — but the receiving table/endpoint doesn’t exist yet either (same root blocker as Gap 1).
  4. Self-hosted licence-gating (SPEC-152 Open Question 5). See SPEC-152-Q5 — the technical mechanism is now designed (pending merge to main).
  5. No Origo-facing HTTP API yet — partially closed by issue #1. src/server/ now exposes derive() over HTTP (POST /v1/tenants/:tenantId/clients/:clientToken/suitability/export, format=json, bearer-token gated), so this repo is no longer library-only. What remains open: (a) this is a narrower, hand-shaped contract, not SPEC-152’s own “API contract (draft)” design — that section should still be read before treating this endpoint’s shape as final/Origo-facing; (b) format=pdf/format=docx are not implemented (501) — no DOCX template merge or PDF conversion is wired into src/server/, unlike client-onboarding’s route; (c) the endpoint takes already-assembled PartialSuitabilityData in the request body rather than fetching it server-side, because the Data Assembler stage still can’t (Gap 1) — once client-onboarding#2670 ships, a server-side fetch path via DataAssemblerClient should be added alongside the current body-supplied path.
  • Originating design doc: SPEC-152 in client-onboarding — the ratified scope, auth model, data-access decision, and deployment topology this spec’s baseline implements against.
  • Depends on (moved as-is, behavior must not drift): client-onboarding SPEC-108, SPEC-109, SPEC-110, SPEC-112 (design precedent for the rebuilt Data Assembler stage), SPEC-113, SPEC-121, SPEC-122, SPEC-127, SPEC-133.
  • Blocked by: client-onboarding#2670 (internal read-API — gates Gaps 1 and 3 above).
  • Blocks: client-onboarding#2516 (the client-onboarding-side refactor to consume this service once it’s real).
  • Source issue: client-onboarding#2669 (scaffolding issue that created this repo).