ADR-007: Schema-Driven Configuration & Unified Annotation Keys
Status
Accepted
Date
2026-05-29
Context
As the project evolved, configuration parameters and Kubernetes metadata keys (labels/annotations) were scattered, duplicated, and hardcoded in multiple places:
- CLI Options: Hardcoded string arrays in the CLI wrapper (
src/cli.ts) for argument parsing, validation, and print help. - Documentation: Manual markdown tables in
README.md,getting-started.md, and other guides, leading to a high risk of code-doc drift. - Annotation/Label Keys: Magic strings (e.g.
"nogoo9/workspace-id","nogoo9/user-sub") duplicated across multiple files (src/k8s/annotations.ts,src/k8s/pods.ts,src/mcp/spawner.ts,src/server/auth.ts,src/server/ws-proxy.ts,src/server/routes/mcp.ts).
This duplication increased maintenance overhead, made adding new settings error-prone, and made verification difficult.
Decision
Consolidate configuration parameters and Kubernetes keys into a single schema-driven architecture:
- Modular Configuration Schemas: Restructure settings under
src/config/(categorized intoserver,tls,cors,k8s,auth,ui) as type-safe schema objects containing CLI flags, environment variables, default values, validations, and descriptions. - Single Source of Truth:
- CLI Parsing: Refactor
src/cli.tsto dynamically resolve flags, validate inputs, enforce types, and print help guides directly from the schemas. - Documentation Generation: Build a workspace script (
scripts/update-docs.ts) that extracts metadata directly fromsrc/config/index.tsand injects updated tables into markdown documents automatically via placeholder tags.
- CLI Parsing: Refactor
- Consolidated Annotation Constants: Move all Kubernetes label and annotation keys into
ANNOTATION_KEYSinsrc/config/annotations.ts. Re-export this map through the main config module and refactor the codebase to reference these constants instead of magic strings.
Alternatives Considered
Keep Hardcoded Logic
- Pros: Zero initial refactoring.
- Cons: High likelihood of forgetting to update the CLI help text, documentation files, or one of the many magic strings when adding features.
- Rejected: Does not scale and violates the codebase quality standards.
Use Third-Party Config Libraries (e.g., Convict, Zod Config)
- Pros: Ready-made schema validation.
- Cons: Adds external dependencies, increases bundle size, and introduces potential runtime compatibility issues across Deno, Bun, and Node.js.
- Rejected: A lightweight, native TypeScript schema implementation is simpler, cross-runtime safe, and easier to integrate with our custom markdown docs generator.
Consequences
- Zero Drift: Documentation and CLI instructions are guaranteed to be in sync with the codebase.
- Robust CLI: CLI arguments are validated (such as ensuring ports are numbers, or options are within allowed sets) and coerced automatically.
- Clean Codebase: Removed magic strings for Kubernetes metadata, eliminating typo risks and simplifying renaming or auditing keys.
- Cross-Runtime Safety: All schema parsing is built on standard JS/TS features, keeping compatibility green across Bun, Node, and Deno.
- Encapsulated Config: Deleted wrapper
src/config.tsand pointed all imports tosrc/config/index.js, sealing configuration logic inside thesrc/config/folder.
