# OpenSpec Change: enterprise-logger - **Change ID**: enterprise-logger - **Package**: `@suaveplan/logger` - **Category**: universal - **Target path**: `packages/universal/logger` - **Status**: IN PROGRESS - **Date**: 2026-04-18 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/logger.md` ## Summary Greenfield implementation of `@suaveplan/logger` for the genesis branch. The existing main-branch logger (v1.23) provides the baseline public-API surface to preserve; this change adds enterprise-grade structured JSON output, declarative redaction, head/tail/rule-based sampling, OpenTelemetry correlation, pluggable sinks, property-based tests, and benchmarks. ## Current-state audit (genesis) The package does not exist on genesis yet — this is a fresh build. ## Available workspace deps on genesis | Package | Available | |---------|-----------| | `@suaveplan/error` | ✅ | | `@suaveplan/events` | ✅ | | `@suaveplan/types` | ✅ | | `@suaveplan/timing` | ❌ not yet built — use `Clock` from `@suaveplan/types` | | `@suaveplan/storage` | ❌ not yet built — keep `StorageInterface` locally | | `@suaveplan/streams` | ❌ not yet built — implement bounded buffer internally | | `@suaveplan/opentelemetry` | ❌ not yet built — use `@opentelemetry/api` directly | | `@suaveplan/feature-flags` | ❌ not yet built — skip | | `@suaveplan/schema-registry` | ❌ not yet built — export Zod schemas directly | External deps (via catalog): - `zod` → `catalog:forms` - `@opentelemetry/api` → `catalog:observability` - `tslib` → `catalog:build` Dev deps (via catalog): - `vitest`, `@vitest/coverage-istanbul` → `catalog:testing` - `fast-check` → `catalog:testing` - `mitata` → `catalog:testing` ## Preserved public API surface (from main branch) All of the following must be exported from the genesis build: ### Types - `LogLevel`, `LogEntry`, `LoggerConfig`, `LoggerMetrics` - `ConsoleLoggerConfig` - `EventLoggerConfig`, `LoggerEvents` - `StorageLoggerConfig`, `StorageInterface` - `ConsoleLoggerFactoryConfig`, `StorageLoggerFactoryConfig`, `EventLoggerFactoryConfig`, `LoggerFactoryConfig` - `InitLoggerOptions`, `InitLoggerResult` - `SeverityLevelMap`, `UninstallErrorInterceptor`, `InstallErrorInterceptorOptions` ### Classes - `AbstractLogger` (abstract) - `ConsoleLogger` - `EventLogger` - `StorageLogger` ### Interfaces - `Logger` - `LogLevels` ### Functions - `createLogger(config)` (overloaded factory) - `initLogger(options?)` → `InitLoggerResult` - `installSuaveplanErrorInterceptor(logger?)` → `UninstallErrorInterceptor` - `__resetDefaultLoggerForTests()` ## New additions ### Modules - **`record/`** — `LogRecord` structured JSON schema (Zod), `ts`/`level`/`msg`/`ctx`/`trace_id`/`span_id`/`error` fields - **`errors/`** — `LoggerError` extending `SuaveplanError`; codes: `LOGGER.SINK`, `LOGGER.SERIALIZE`, `LOGGER.CONFIG`, `LOGGER.FLUSH` - **`redaction/`** — `RedactionEngine` with field-path rules (dot-notation + glob), regex rules, depth limit; `@sensitive`-aware via `isSensitive()` from `@suaveplan/error` - **`sampling/`** — `HeadSampler` (deterministic per trace_id hash), `TailSampler` (bounded buffer + decision callback), `RuleSampler` (predicate-based); `SamplingPolicy` union type - **`sink/`** — `Sink` interface; `ConsoleSink` (ANSI dev output); `JsonSink` (NDJSON writer); `BufferedSink` (bounded queue, drop/block policy, `AbortSignal` flush) - **`otel/`** — `getOtelTraceContext()` reads `trace_id`/`span_id` from active OTel span (no-op when no exporter) - **`schemas/`** — Zod schemas for `LoggerConfig`, `LogRecord`, all sink configs (re-exported) ### Cross-cutting enterprise requirements - Injectable `clock` (from `@suaveplan/types#Clock`) and `rng` on all time/random usages - `AbortSignal` support on `flush()` and `getLogs()` - `sideEffects: false` + tree-shake test - Property-based tests (fast-check) for redaction invariants and sampling determinism - mitata benchmarks in `src/__benchmarks__/` - OTel counters + histograms on `log()` calls (via `@opentelemetry/api`, no-op when unregistered) - Zero `any`, zero `ts-ignore`, zero mock usage in tests ## Dependency-layer check `@suaveplan/logger` depends on `@suaveplan/error` and `@suaveplan/events`, both of which are enterprise-complete on genesis. ✅ ## Acceptance criteria - [x] `bunx turbo lint typecheck test:coverage --filter=@suaveplan/logger` green with ≥ 100% coverage on touched modules - [x] `bun run docs:check --filter=@suaveplan/logger` reports ≥ 90% - [x] All preserved public API surface exported from `src/index.ts` - [x] New `LogRecord` schema, `LoggerError`, redaction, sampling, sink, OTel modules implemented - [x] Zero `any`, `ts-ignore`, `TODO`, `FIXME`, `@deprecated`, `.skip`, `.only` in `src/` - [x] Property-based tests for redaction invariants and sampling determinism - [x] mitata benchmarks in `src/__benchmarks__/` - [x] `sideEffects: false` confirmed, tree-shake test passes