Skip to content

Replace Ecto with Peri for schema validation#2

Merged
holsee merged 1 commit into
mainfrom
feat/remove-ecto-peri-schema-validation
Mar 11, 2026
Merged

Replace Ecto with Peri for schema validation#2
holsee merged 1 commit into
mainfrom
feat/remove-ecto-peri-schema-validation

Conversation

@holsee

@holsee holsee commented Mar 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Swap {:ecto, "~> 3.11"} for {:peri, "~> 0.3"} in mix.exs
  • Rewrite TestCase and ToolCall from Ecto embedded schemas to plain defstruct + Peri defschema
  • Replace Ecto introspection in the OpenAI adapter with explicit json_schema/0 callbacks
  • Add ADR-0008 documenting the rationale; mark ADR-0002 as superseded

Why

Ecto's changeset pipeline is designed for casting external input into database-backed entities. Using it purely for in-memory struct validation caused three problems:

  1. cast_embed rejects structs — nested %ToolCall{} structs couldn't be passed through TestCase changesets; Ecto expects raw maps at cast time
  2. Two construction paths%TestCase{...} (direct struct) and TestCase.new!/1 (changeset) behaved differently, forcing callers to know which to use
  3. Wrong tool for the job — a ~2MB persistence library for simple "validate a map has the right keys and types" in a library with no database

Peri provides declarative schema validation on plain maps with no persistence assumptions.

Test plan

  • mix deps.get fetches Peri, removes Ecto
  • mix compile --warnings-as-errors — clean compile, no Ecto references
  • mix test — all 125 tests pass
  • grep -r "Ecto" lib/ test/ — confirms no remaining Ecto references

Ecto's changeset pipeline was designed for casting external input into
database-backed entities. Using it for pure in-memory structs caused
friction: cast_embed rejected structs, two construction paths behaved
differently, and a ~2MB persistence library was pulled in for simple
map validation.

Switch to Peri (lightweight schema validation) with plain defstruct.
Each schema module now exports json_schema/0, replacing the Ecto
introspection in the OpenAI adapter.

ADR-0008 documents the rationale; ADR-0002 is marked superseded.
@holsee holsee force-pushed the feat/remove-ecto-peri-schema-validation branch from e958672 to 8350610 Compare March 11, 2026 14:50
@holsee holsee merged commit 6faf5e7 into main Mar 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant