Skip to content

[Docs]: Add ADR for the @standard-schema/spec dependency choice #80

Description

@martyy-code

Current State

The package packages/errors depends on @standard-schema/spec (declared in package.json as a dependencies entry). The choice is consistent with rule 0006 (Technology Choices) — the spec allows consumers to use Zod, Valibot, ArkType, or any other compliant validator.

However, the choice is not documented. Rule 0006 requires every technology choice to be stated in writing, in a place a contributor will find it — an ADR in decisions/, a rule in rules/, or a comment at the boundary where the assumption bites.

Looking at the codebase:

  • docs/engineering/architecture/decisions/ exists but has only a README.md placeholder (verified at the time of this audit).
  • The fields parameter in error() accepts a StandardSchemaV1 value, but no inline comment explains why Standard Schema and not Zod directly.
  • The package.json description mentions the library is "inspired by Python" but does not explain the validator-independence choice.

Located in:

  • packages/errors/package.json (dependency declaration, no rationale)
  • packages/errors/src/error/error.ts:34 (JSDoc mentions "Zod, Valibot, ArkType" in the example, but does not explain the spec)
  • packages/errors/src/error/types.ts:32 (the schema?: StandardSchemaV1 field)

Proposed State

After this task, the choice is documented as an ADR in docs/engineering/architecture/decisions/. The ADR follows the four-question template mandated by rule 0006:

  • What is the choice? @standard-schema/spec as the runtime validator contract. Consumers pass any Standard Schema-compliant validator (Zod, Valibot, ArkType, etc.) to error({ fields: ... }).
  • What does it enable? Validator-agnostic consumer code. The library never imports a specific validator; the consumer chooses and the library accepts the inferred type.
  • What does it rule out? Direct Zod (or Valibot, etc.) types. Consumers who want z.infer<typeof schema> must do the inference at their boundary, not inside the library.
  • When would we revisit? If @standard-schema/spec is abandoned by its maintainers, if a successor spec emerges, or if the library's surface area grows to need validator-specific features (e.g. recursive schemas with a specific syntax).

The ADR is also referenced from:

  • A short comment in error.ts near the StandardSchemaV1 import (one line pointing to the ADR).
  • The README.md section on the public API (one sentence pointing to the ADR).

Expected improvements:

  • Rule 0006 compliance: the choice is documented in the canonical place.
  • A new contributor who asks "why Standard Schema and not Zod?" finds the answer without having to ask.
  • The decision is reviewable in the same way as any other ADR.

Motivation

This task is needed because:

  • Rule 0006 explicitly forbids undocumented technology choices: "A choice without a 'what does it rule out' is the smell. Every choice rules something out; an author who cannot name what is ruled out has not understood the choice."
  • The decision was made (the spec is the contract), but the rationale lives only in the author's head. A new contributor who wants to "simplify" the dependency to Zod has no counter-evidence to read.
  • The ADR is a one-page document; the cost of writing it is much lower than the cost of re-litigating the choice in code review.

Triggers for this work:

  • Technical debt accumulation
  • Maintainability concerns

Risks

Potential risks:

  • Risk 1: The ADR becomes stale if @standard-schema/spec evolves. — Mitigation: the "When would we revisit" question names the conditions that would prompt an update.
  • Risk 2: The ADR is too long or too short. — Mitigation: the four-question template constrains the shape; one paragraph per question is the target.

Migration Plan

Migration approach:

  1. Create docs/engineering/architecture/decisions/0001-standard-schema-for-runtime-validation.md.
  2. Add a one-line comment in packages/errors/src/error/error.ts near the StandardSchemaV1 import pointing to the ADR.
  3. Add a one-sentence reference in packages/errors/README.md in the section that introduces the public API.
  4. Run the test suite; no code change is involved.

Rollback plan: revert the PR.

Backward Compatibility

  • This refactoring maintains full backward compatibility (no code change)

Scope

Files/Folders affected:

  • docs/engineering/architecture/decisions/0001-standard-schema-for-runtime-validation.md (new file)
  • packages/errors/src/error/error.ts (one-line comment)
  • packages/errors/README.md (one-sentence reference)

Component(s) Affected

  • Multiple Components

Note: the component_affected dropdown is calibrated for a web template project. The affected components are packages/errors and docs/engineering/architecture/decisions/.

Priority

  • p0: Critical - Blocking major work or causing bugs
  • p1: High - Important, should do soon
  • p2: Medium - Normal priority
  • p3: Low - Nice to have

Estimated Effort

  • effort: xs - Few minutes

Test Coverage Requirements

  • Existing tests cover this code area (will update)
  • Need to add new tests for this refactor
  • This area lacks test coverage (technical debt)
  • Integration tests will be added/updated
  • E2E tests will be added/updated

Testing Approach

No code change; no tests required.

Related Issues / Pull Requests

  • Related audit: « Hors-P0 mais notables » in the internal audit of packages/errors/src/ against rules 0001-0016, August 2026.
  • Related rule: docs/engineering/architecture/rules/0006-technology-choices.md.

Relevant Documentation

  • Architecture doc: docs/engineering/architecture/rules/0006-technology-choices.md
  • Existing: docs/engineering/architecture/decisions/README.md

Pre-Submission Checklist

  • I have searched existing issues for related refactoring requests
  • Risks and migration plan are documented
  • Test coverage approach is defined
  • I understand this issue will be labeled according to the project taxonomy
  • This is NOT a security vulnerability (see security note above)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions