Catalog as the contract
Every observable behavior is a named, Zod-validated entry. Refactors are safe; tests assert against the catalog; coverage flags entries no test exercises.
Bring your own catalog. Get typed emit, publisher fan-out, request context, test harness, and a coverage report. ~600 lines, no runtime dependencies.
import { defineCatalog, consolePublisher } from '@rachelallyson/spectra'
import { z } from 'zod'
const catalog = defineCatalog({
'app.started': z.object({ env: z.string(), version: z.string() }),
'guest.created': z.object({ tenantId: z.string(), guestId: z.string() }),
})
catalog.setPublishers([consolePublisher()])
catalog.emit('app.started', { env: 'production', version: '1.0.0' })
// ^ TypeScript and Zod both validate thisMost observability is unstructured console.log plus whatever Sentry sees. That works until it doesn't โ and when it doesn't, you spend an hour grepping logs for the one signal that would have closed the case in seconds.
The Stratum pattern fixes this by making every observable behavior a named, typed entry in a catalog. The catalog becomes the contract: every emit validates against it, tests assert sequences against it, and a coverage report flags which catalog entries no test ever exercises.
Spectra ships the patterns, not the framework. ~600 lines, no runtime dependencies, full type safety, designed to be read in one sitting.
Spectra deliberately doesn't try to replace OpenTelemetry โ it's the typed-events-and-business-state layer that sits above OTel traces and metrics.