Atomic configuration. Each value is a tessera: one self-contained atom — name, validator,
docs, and secrecy in inert, importable data — bound explicitly per runtime (process.env on a
server, the request env on a worker, a literal in a test, a baked constant in the browser).
Secret by default: a tessera is a secret unless you mark it public, and secrets never reach the browser by construction.
Validation, live values, value inheritance, conditional config — all built in.
Design phase — no code yet. This repository is the design:
principles.mdis the constitution, andsite/presents it as documentation you can read as if the library already shipped.tessellum(a tessellation — many small tiles composing one gap-free surface) is reserved on npm as a0.0.0placeholder; each value is onetessera(Latin for a single mosaic tile, and the Roman token that carried a watchword or a bond of trust). Repo: github.com/rejifald/tessellum.
t3-env, envalid, and znv validate config correctly — but each loads and validates every value in
one import-time call. That monolith can't bind to a Cloudflare Worker's per-request env, and it
treats every value, secret or not, as an ordinary string. As per-value atoms, the same tessera
works across every runtime, and secrets are fail-closed by construction.
Declare the atoms once. Each runtime binds the same values — the tesserae never change.
// config/db.ts — inert tesserae. Importing this file costs bytes, not behavior.
import { tessera } from "tessellum";
import { z } from "zod";
export const dbUrl = tessera({
key: "DATABASE_URL",
schema: z.string().url(),
doc: "Primary Postgres connection string",
// exposure defaults to "secret" — fail closed
});
export const poolSize = tessera({
key: "DB_POOL_SIZE",
schema: z.coerce.number().int().min(1).max(100),
default: 10,
exposure: "public",
});// Node — eager validation of exactly what this entrypoint binds, at boot
import { bind, env } from "tessellum/node";
const cfg = bind({ db: env(dbUrl, "PLATFORM_PG_URL"), pool: poolSize });// Cloudflare Workers — the same tessera, bound to the per-request env bag
// (the case import-time validators structurally cannot serve)
import { bind } from "tessellum/workers";
const cfg = bind(dbUrl, { env }); // inside fetch(req, env) — the bag is required, never ambient// Tests — literal values, zero process.env mutation
import { bind, literal } from "tessellum";
const cfg = bind({ db: literal(dbUrl, "postgres://localhost:5432/test") });// Browser — no binding at all: config arrives as baked literals, secrets structurally excluded
import { config } from "./config.baked";tessellum has zero runtime dependencies; validators plug in through the Standard Schema interface, so any schema library that implements it works.
Every feature passes all of them, or it doesn't ship. The load-bearing few — the full set
(P1–P21) lives in principles.md:
- Tesserae are inert data. Constructing one does zero I/O, zero validation, zero registration, zero side effects.
- Values live only in explicit bindings. No ambient global, no module-scope cache; a read outside an active binding is a named error, never a silent fallback.
- Browser-first, runtime-universal core. No Node APIs in the core entry;
process.envand file sources live in subpath entries. - Fail-closed exposure.
secretis the default;publicis the explicit opt-in. - Bake is the only client delivery channel — it inlines public values as literals and leaves secrets out of the client entirely. A secret's value is never resolved at build time; it's read at runtime, where the value lives.
- Identity by value, not by import. A tessera's identity comes from its own definition — name, validator, sources, exposure — not from where it's imported. Two packages can agree on the same config contract without sharing a monolith, and a mismatch fails loudly instead of drifting silently.
- Config, not state. If it can change while the process runs, it's state — reached by an
explicit
livetessera over a re-readable source, never by streaming or subscriptions. - Honest claims. Every guarantee states its boundary in the same breath — what the leak scan
cannot see, what
pick()does not defend against. A security story that overclaims is itself a vulnerability.
-
Read the design as documentation. The fastest way to evaluate tessellum is to read the site as if the library already shipped:
cd site pnpm install pnpm dev # http://localhost:3000
Start at /docs and /docs/principles, then the concept pages (tessera, binding, identity, secrets, conditional config, freshness) and the runtime guides (Node, Workers, browser, testing, live config).
-
principles.md— the constitution: every hard constraint, every pitfall found through adversarial design review, and the full security model. -
docs/adr/— accepted design decisions, each recording why and what it costs (start with tessera inheritance). -
v0.1 proof gate: one tesserae file consumed unchanged by a Node server, a Cloudflare Worker, a Vite client (with bake failing the build on a planted secret leak), and a vitest suite with zero
process.envmutation.