Skip to content

feat(schema): reserve validations key in schema spec v0.1.0 (#192)#198

Merged
zeevdr merged 1 commit into
mainfrom
reserve-validations
Apr 27, 2026
Merged

feat(schema): reserve validations key in schema spec v0.1.0 (#192)#198
zeevdr merged 1 commit into
mainfrom
reserve-validations

Conversation

@zeevdr
Copy link
Copy Markdown
Member

@zeevdr zeevdr commented Apr 27, 2026

Closes #192. Final Phase-1 subtask of the cross-field validation umbrella (#76); pairs with #193 (`dependentRequired:`) and #194 (prefix-overlap lint), both in main.

Summary

Reserves the top-level `validations:` key in schema spec v0.1.0 — proto, DB, YAML parser, lint, storage round-trip — without shipping the CEL engine. The engine lands in Phase 2 (#76).

Why ship the key now

  • Schema Spec v0.1.0 freezes the meta-schema. Adding the key later is a breaking spec bump that downstream tooling has to handle. Reserving now costs ~50 lines of plumbing.
  • Schema authors who want cross-field rules today can write CEL expressions; ImportSchema accepts and persists them. They become no-ops at write time until Phase 2.

YAML shape (per .agents/context/cel-validation.md)

```yaml
validations:

  • path: payments # optional group prefix (informational in v0.1.0)
    rule: "self.payments.min < self.payments.max"
    message: "min must be less than max"
    severity: error # optional, default error
    reason: MIN_GT_MAX # optional machine code
    ```

v0.1.0 lint at ImportSchema (structural only)

  • `rule` and `message` required, non-empty
  • `severity` empty or one of `error` / `warning`
  • `x-*` extension keys accepted; unknown keys rejected
  • Error messages include the index of the offending entry

CEL compilation, field-reference resolution, and contradiction detection defer to Phase 2.

Test plan

  • Structural lint — empty rule, empty message, bad severity, unknown extension key, x-* allowed, error includes index.
  • Marshal / unmarshal round-trip + empty / malformed JSON edges.
  • proto<->YAML converters with order preservation.
  • Top-level YAML parser integration — accepts valid block, rejects empty rule, rejects bad severity.
  • `make test` passes (full suite, race detector on).
  • `make lint` passes.
  • `make generate docs` regenerated and committed.

Adds the JSON Schema-style top-level `validations:` key end-to-end —
proto, DB column, YAML parser, lint, storage round-trip — with the
explicit non-goal of *not* shipping the CEL engine. The engine and
runtime evaluation land in Phase 2 (issue #76).

Why ship the key now:

- Schema Spec v0.1.0 freezes the meta-schema. Reserving the key now
  costs ~50 lines of plumbing; adding it later is a breaking spec bump
  that downstream tooling has to handle.
- Schema authors who need cross-field rules today can write CEL
  expressions; ImportSchema accepts and persists them. They become
  no-ops at write time until Phase 2 wires the engine.

Wire format mirrors Kubernetes CRD x-kubernetes-validations and
buf/protovalidate (see .agents/context/cel-validation.md):

```yaml
validations:
  - path: payments              # optional group prefix
    rule: "self.payments.min < self.payments.max"
    message: "min must be less than max"
    severity: error             # optional, default error
    reason: MIN_GT_MAX          # optional machine code
```

v0.1.0 lint at ImportSchema is structural only:

- `rule` and `message` required and non-empty
- `severity` empty or one of "error" / "warning"
- `x-*` extension keys accepted; unknown keys rejected

CEL compilation, field-reference resolution, and contradiction
detection all defer to Phase 2.

Implementation mirrors the dependentRequired pattern from #193:

- `proto/centralconfig/v1/types.proto`: new `ValidationRule` message,
  `Schema.validations = 13`.
- `db/migrations/001_initial_schema.sql`: `validations jsonb NOT NULL
  DEFAULT '[]'` column on schema_versions (squashed into 001).
- `internal/schema/validations.go` (new): `MarshalValidations` /
  `UnmarshalValidations` helpers, exported for tooling.
- `internal/schema/yaml.go`: `SchemaYAML.Validations` +
  `ValidationYAML` struct, `validateValidationsYAML` lint, proto<->YAML
  converters.
- `internal/schema/service.go`: ImportSchema reads, lints, and
  persists; GetSchema/ExportSchema round-trip.
- `internal/storage/domain/types.go`: `SchemaVersion.Validations
  []byte`.
- Storage layer plumbing through PG and memory stores.

Test coverage:

- Structural lint — empty rule, empty message, bad severity, unknown
  key, x-* allowed, error includes index.
- Marshal / unmarshal round-trip plus edge cases.
- proto<->YAML converters with order preservation.
- Top-level YAML parser integration.

Closes #192.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zeevdr zeevdr added this to the Schema Spec v0.1.0 milestone Apr 27, 2026
@zeevdr zeevdr added server Server changes size: S Quick win — a few hours or less priority: P1 Current milestone work labels Apr 27, 2026
@zeevdr zeevdr merged commit 940ffdc into main Apr 27, 2026
18 checks passed
@zeevdr zeevdr deleted the reserve-validations branch April 27, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: P1 Current milestone work server Server changes size: S Quick win — a few hours or less

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reserve top-level validations: key in schema spec v0.1.0 (parser only, no engine)

1 participant