Tessera RP

PX-09

North Star

One system, drawn for two readers.

Engineers arrive wanting wire formats, table names, the tenancy mechanism and what happens when a source goes down. Finance and operations arrive wanting the value stream and the decisions it supports. Both drawings are here — pick a view.

Seven layers. Each owns a job the one above it is forbidden from doing, and every arrow names the contract that crosses it.

L1

Source

Your systems of record

Read where the data already is

customer-owned

L2

Ingest

Connector SDK

Knows source APIs, not the schema

lib/connectors

L3

Landing

Raw tier

Append-only JSONB, exactly as sent

raw.record

L4

Canonical

ERP-agnostic star schema

Above this line, nothing knows which ERP

wh.*

L5

Graph · soon

Entities and edges

Beside the star schema, not instead of it

Tessera DB

L6

Semantic

Governed catalog + compiler

One definition per metric. The only thing that emits SQL

lib/semantic

L7

Surface

Dashboards, Explore, alerts

Fifteen surfaces, all resolving the same definitions

app/*

Every layer

Tenancy

Row-level security in Postgres, forced

Scope

Row filters appended after the caller's

Sessions

Hashed token, tenant on the session

The invariant

Nothing writes SQL except the compiler.

QuerySpec

validate

resolve

scope

SQL

Every read path — a tile, the Explore UI, an alert, the assistant — emits the same object. There is no code path from model output to SQL text, which is why the assistant is safe to expose.

What the layering buys you

Add an ERP, keep the work

A new source is a connector and a mapper. Every metric, dashboard and alert above Layer 4 carries over untouched.

One number, everywhere

Contribution margin resolves the same catalog entry on a tile, in an export, in an alert and in an answer. Two surfaces cannot disagree.

Swap the engine, keep the metrics

The compiler emits engine-neutral SQL. Postgres today; the adapter is the seam for what comes next.

Isolation that survives a bug

Row-level security is enforced by the database, not by application filters — so a mistake returns nothing rather than somebody else's books.

Connected in an hour, useful the same afternoon.

01

Connect

Point it at your ERP and your storefronts. Read-only, and nothing is written back.

02

Model

Every source lands in one ERP-agnostic shape, with the costs your ERP books elsewhere attached to the order line that caused them.

03

Govern

229 metrics with an owner and one definition each — so no two surfaces can disagree.

04

Decide

Each role opens on their own numbers, asks in English, and gets alerted when something moves.

Semantic layer

Metrics

229 governed, across 14 domains

Dimensions

101

Query path

QuerySpec → validate → scope → compile. Nothing else emits SQL

Ratio metrics

SUM(numerator) / SUM(denominator) at result grain, never AVG(ratio)

Parameters

Every filter value bound; no string concatenation anywhere

Period-over-period

A `__prev` suffix resolved by the compiler, so a caller never hands it SQL

Catalog

Deep-frozen at module load — a request handler cannot mutate a metric

Warehouse

Engine

Postgres. Engine-neutral SQL behind a WarehouseAdapter

Model

Star schema — 6 conformed dimensions, 9 fact tables

Landed cost

7 components per order line; landed cost and contribution margin are GENERATED columns

Raw tier

raw.record, JSONB, append-only, replayable, content-hashed

Migrations

25, idempotent, run as a separate owner role

Data quality

Freshness, not-null, unique, referential, row-count and accepted-values tests

Analytics

Forecasting

Holt-Winters, for demand and cash

Anomalies

STL decomposition + robust z-score. No model involved

Elasticity

Log-log regression

Replenishment

Reorder point with service-level safety stock; stockout probability

Cohorts

Retention and contribution-margin LTV; CAC, LTV:CAC, payback

Working capital

Cash conversion cycle as DSO + DIO − DPO

Security & tenancy

Isolation

Postgres RLS, ENABLE + FORCE, on every tenant-scoped table

App role

NOSUPERUSER, NOBYPASSRLS, no DDL rights

Scoping

Row-level data scope appended by the compiler after the caller's filters

Roles

Owner 40 · admin 30 · analyst 20 · viewer 10

Sessions

Opaque random token; only its SHA-256 hash is stored

SSO

Schema-ready via sso_subject; password auth today

Audit

Append-only row for every mutation and every denied access

Secrets

Deep key-based redaction before anything reaches a log

Runtime & verification

Deployment

erp.par2labs.com · self-host · Docker · Kubernetes

Image

339 MB, runs non-root

Scaling

Horizontal behind a shared Redis for cache and rate limits

Degradation

Redis unreachable falls back to in-process buckets rather than failing

Observability

/api/health, /api/ready, Prometheus at /api/metrics, request-id on every line

Query bounds

Statement timeout and LIMIT max+1 — truncation is flagged, never silent

Tests

5,882 across 145 files

Gates

Format, lint, typecheck, tests, coverage, dependency audit and a production build, on every push

The coverage gate is deliberately left failing at 84% statements rather than lowered to match what the suite happens to achieve. A gate tuned to reality is not a gate.

Tessera RP is live.

It runs at erp.par2labs.com, with a seeded demo workspace you can sign into without a password. Self-hosting is a Docker image and one command.