Authored theme contract evaluation
Internal evidence, compatibility boundary, and stop gates for Compify's legacy component-scoped themes.
Authored theme contract evaluation
Status: internal evidence and hardening boundary, not a released package or product commitment.
Evidence snapshot: 2026-08-08, verified main and production 82c1fc0084d04ded10d505b7f2fa6c3bdef1e634.
Decision
Do not create or publish @compify/theme yet. Compify has enough source evidence to
close unsafe nested API inputs, but not enough real authored-theme evidence to freeze a
portable package contract. The verified production database contains one blank theme
(factors: [], groups: {}, values: []), while the earliest retained off-host
production backup inspected for this evaluation contains no themes. Shipped fixtures
and editor code demonstrate implementation compatibility; they are not customer
adoption, portability, willingness-to-pay, or product-market-fit evidence.
The deployed safe step is an internal authored-content boundary shared by HTTP
writes and component forks. It validates the shapes the existing editor actually
uses and stops persisting derived c fields. It does not add a token platform, DTCG
import/export, theme CLI, modes, plugins, transformations, signing, or visual/runtime
claims. npm publication, tags, and releases remain paused.
Evidence in the current implementation
- Persistence only constrains the outer JSON kinds in
apps/api/src/entities/project/theme.entity.ts; nested content was historically accepted asany. apps/api/src/models/theme/insert-theme.dto.tspreserves the one supported legacy container normalization: exact emptygroups: []becomes{}.- The editor creates factor types
hue,saturation,lightness,slider, andvalue; group typespalette,value, andvaluesall occur in shipped code or fixtures. - Authored token values may be strings (including an unfinished empty draft) or finite
numbers. Factor
minandmaxare optional, and zero is meaningful. cis not authored authority.ThemeCompilerderives it fromvalue, and the CSS and flat-JSON emitter consumes the derived result. Incoming or storedcmay be absent or stale.- Resolution currently recognizes direct
--token, meta${token}and${--token}, a legacy numeric suffix, bounded arithmetic, and boundedcalc(...). Factor tokens precede canonical group-option tokens, which precede value tokens. Existing factor/value key overlap is therefore temporarily factor-first. - Application values export. Public group options export under the canonical
group-optionname and, temporarily, the deprecated unprefixed option alias. Factors and private groups remain resolution inputs rather than direct exports.
These observations describe legacy behavior; they do not establish a general token standard or compatibility with arbitrary CSS, Tailwind, DTCG, Tokens Studio, Figma, Style Dictionary, Theo, or Terrazzo inputs.
Compatibility-safe authored ingress
The internal write boundary accepts only:
- outer factor and value arrays plus a group object (and exact legacy
groups: []); - safe names matching
^[A-Za-z_][A-Za-z0-9_-]{0,63}$, excluding__proto__,prototype, andconstructor; - the shipped factor and group types listed above;
- string or finite-number values, boolean-or-absent
isPublic, and finite ordered factor bounds; - optional legacy string-or-finite-number
conly as a migration input, which is discarded before storage; - the existing factor/value overlap, while rejecting ambiguity within namespaces, canonical group-option collisions, and public export-alias collisions.
It rejects malformed nested containers, missing required fields, other unknown nested properties, unsafe names, non-boolean publication flags, non-finite or reversed bounds, excessive counts, and sources over the existing one-mebibyte write ceiling. Validation does not claim that references resolve, CSS is visually correct, the cascade is understood, or a runtime rendered successfully. Reference-language replacement requires representative authored fixtures and exact cross-runtime golden parity before it can move into a package.
Customer CSS, Tailwind configuration, DTCG/token repositories, and application code remain canonical. Compify's stored theme is component-scoped editor input, not an authority over those sources.
Offline styling-contract replay
The first preregistered public-source technical replay used the MIT-licensed,
archived Shopify Polaris token change a982763 with ten frozen story selections.
All 40 repeated base/head commands were byte-repeatable, but 0/10 head selections
inspected: nine failed closed on inherited TypeScript configuration outside the
bounded static alias contract, and one frozen story export did not exist. The
seven-of-ten inspectability gate therefore stopped the replay before handoff,
build, sidecar, or receipt evidence. All ten outcomes remain unknown.
This is a negative technical result, not a VTR or demand result. It does not
justify widening tsconfig evaluation or building a token graph. The exact
preregistration, denominator, logs, manifest, and checksums are retained under
evidence/theme-release-assurance/.
Source/theme atomicity design gate
The browser resolver is now bounded, but current component source and theme persistence still use separate mutation domains. The reviewed design target is documented in source-theme-atomicity.md. It uses immutable, version-addressed source objects and one aggregate PostgreSQL state revision/CAS so source, authored theme, and bounded component metadata commit or conflict together. That document is design-only: no aggregate revision schema, endpoint, bucket, migration, backfill, or activation claim exists yet.
Candidate package gate
A private packages/theme experiment may start only when all of the following exist:
- at least two sanitized, non-demo authored sources from qualified teams, covering the same concrete factor/group/value behavior;
- explicit permission to retain those sources as bounded compatibility fixtures;
- golden proof that one dependency-free, browser-safe implementation replaces both current compiler paths without changing authored input, generated CSS, or flat JSON bytes;
- the same parser used before API persistence so a package would replace duplication rather than add a third implementation;
- deterministic failure on cycles, depth/count/byte exhaustion, collisions, and CSS injection, with no partial output;
- a clean browser bundle and packed-consumer test with no Node built-ins, DOM/React dependency, filesystem, network, locale, time, or execution of customer code.
Even then the smallest candidate is parse, compile, and emit for the observed legacy shape. Rename/edit operations, DTCG import, modes, plugins, a CLI, registry integration, visual comparison, and signing stay out of v1.
Stop or keep the work as an internal validator if representative sources cannot be
projected after deleting only derived c; compiler outputs differ across runtimes or
input order; accepted inputs cannot be bounded; the API continues persisting derived
fields; or qualified pilots do not independently need source portability. Theme
Release Assurance recruitment, pricing, activation, repeat, renewal, and kill gates
remain defined in docs/product-market-fit.md; no outreach starts without explicit
owner approval.
Evidence categories remain separate
A valid authored source is schema evidence only. A deterministic CSS/JSON emission is static build evidence only. Neither is cascade, scope, runtime, visual, accessibility, deployment, adoption, retention, willingness-to-pay, or PMF evidence. Digest matching would prove byte equality only, not signature or third-party attestation.