Skip to content
oleks crane
Open-source libraryDesign phase

One value, every runtime.

A from-scratch design for atomic configuration: each value is an inert, validated descriptor, bound explicitly to whichever runtime reads it, secret by default. It’s for teams running one codebase across Node, Cloudflare Workers and the browser who’ve outgrown a single import-time-validated config object.

  • 21

    documented hard constraints

  • 11

    accepted architecture decisions

// 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",});

At a glance

Type
My own open-source library
Scope
Everything: the constitution (21 hard constraints), 11 accepted decision records, and the documentation site — no library code has shipped yet.
Status
Design phase — no code yet · as of 24 Sep 2026
Timeline

Started Jul 2026 · not released yet

Platforms
Designed for Node.js, Cloudflare Workers, the browser
Try it
No code yet — the design documents are the project for now.
Stack
TypeScriptNode.jsCloudflare WorkerstsupVitestESLintpnpm

The challenge

Most configuration libraries — t3-env, envalid, znv — load and validate every declared value in one import-time call, even when a given entry point reads only one of them. That works for a conventional server, but it can’t bind to a Cloudflare Worker’s per-request environment, has nothing to say about browsers, and treats every value, secret or not, as an interchangeable string.

  • Boot-crash coupling: an unrelated, unset variable can crash a service at startup.
  • Runtime lock-in: import-time validation can’t see a Worker’s per-request environment.
  • Undocumented strings: a raw environment-variable read has no type, docs or exposure rule.
  • One monolithic call: existing libraries validate everything at once, so nothing binds per runtime.

The constraints

The design has to behave the same way on a Node server, inside a Cloudflare Worker and in the browser, without smuggling Node-only code into a client bundle or leaking a secret by accident.

  • No Node APIs outside dedicated entry points — the core must run in a browser.
  • Zero runtime dependencies, with size budgets enforced in CI.
  • Secret by default — public is an explicit, deliberate opt-in.
  • No background timers, watchers or polling loops.
  • Nothing changes mid-request unless a value is explicitly declared live.

The solution

I modelled configuration as small, inert, content-addressed descriptors instead of one big validated object, so the same declaration binds safely to a Node process, a Worker’s per-request environment, a baked browser bundle, or a test literal. I wrote every hard rule — inert by construction, secret by default, no ambient state — down as one of 21 gates a feature has to pass, and recorded each contested choice as its own decision record, rejected alternatives included.

  • Inheritance is declared data, never a function

    A value that inherits another — a per-service log level falling back to a global default — sometimes needs to transform it first. A function can’t be hashed or safely run at build time, so the transform is a small, fixed set of data operations instead.

  • Secrets are a Proxy, not a plain string

    A spike proved a plain or boxed string can’t stop a secret leaking through structured cloning or an object spread. A Proxy blocks every one of those paths while still behaving like an ordinary string everywhere it’s used.

  • Bake ships handles, never the real config file

    An early version had client code import the real config declarations, which silently shipped an entire validation library to the browser — about 166 times the size. Bake now emits a lightweight stand-in with no validator attached instead.

  • An oversized atomic write is refused, never split

    Splitting one multi-value update across several database transactions means a crash between them can leave the database itself half-updated. Past the store’s own transaction limit, the write is refused outright before anything is sent.

  • Related config values are grouped on purpose, not by default

    The library can’t know on its own which values — a database host and its password — must never be read out of sync with each other. Related values are grouped explicitly, so only a group pays the cost of being re-read together.

Architecture

Tessera

Inert, validated descriptor

Node

Validates environment at boot

Cloudflare Workers

Binds the per-request environment

Browser (bake)

Inlines literals, no secrets

Tests

Literal values, no env mutation

Secret by default

Public is an explicit opt-in

One contract

Same descriptor, every runtime

One tessera, declared once, bound explicitly wherever it’s read — Node, Workers, a baked browser bundle, or a test — with secrets excluded from the client by construction.

I build — you own

Built to hand over

Tessellum hasn’t shipped code yet, but the design is public and finished enough to hand over — every item below is real, on GitHub today.

  • Constitution

    principles.md — 21 hard constraints (P1–P21), the security model and the non-goals, each pitfall found through adversarial review.

    View (opens in a new tab)
  • Decision records

    11 accepted ADRs, each recording the context, the rejected options and what the decision costs — start with ADR-0001.

    View (opens in a new tab)
  • Documentation site

    13 concept and guide pages, written as if the library had already shipped, plus a full API and decisions reference.

    View (opens in a new tab)

Results

Nothing has shipped as code yet: the design is the deliverable. What exists is the constitution, 11 accepted decision records, a documentation site written as if the library had already shipped, and a CI pipeline — already green — testing the placeholder package on Node 22 and 24.

  • 13

    concept and guide pages

  • Apache-2.0

    open-source licence

What’s next

The next milestone is v0.1: one tesserae file consumed unchanged by a Node server, a Cloudflare Worker and a Vite client — with bake failing the build on a planted secret leak — plus a Vitest suite that never mutates process.env.

Have a similar project in mind?

I’ll build it and hand it over: the code, the docs and the accounts are yours.

Discuss a project