IR contract (Plugin API v1)¶
This document freezes the intermediate representation that Plugin API
version "1" may rely on. Semver for plugins follows
PLUGIN_API_VERSION, not the core package minor.
Roots¶
Type |
Role |
|---|---|
|
Frozen model + ordered |
|
|
|
Field name, annotation, metadata, aliases |
|
|
|
|
|
|
|
|
|
Structured skip/warn records (Plugin-visible; prefer not to depend on fields from Application code) |
All IR dataclasses are frozen (slots=True). Phase-1 IR never stores
SQLAlchemy columns.
Operators¶
Portable operators extracted by core: gt, ge, lt, le,
multiple_of, min_length, max_length, pattern, literal, enum.
Opt-in operator (when emit_type_checks=True): type_check with
TypeSpec values. Core extracts IR only — no portable translator
(same pattern as pattern).
Frozen marker operator names: json_contains, json_has_key,
array_contains, array_overlap, range_contains, range_overlap,
fulltext_match.
pattern values are PatternSpec (or legacy str via pattern_text()).
Always call pattern_text(constraint.value) in translators.
type_check values are TypeSpec. Always call type_spec(constraint.value)
in translators.
Application vs Plugin use¶
Application: prefer
compile/Compiler/ markers / exceptions. Treat IR types as advanced (two-phasecompile_model/bind).Plugin: may depend on
Constraint,PatternSpec,TypeSpec,CompilationContext,ModelIR,TranslatorRegistry, markers,pattern_text, andtype_spec.
Whole-model type matrix¶
Every field annotation on a compiled model must be inside the type support
matrix — including unconstrained fields. Unsupported types (for example
timedelta) raise even when the field has no constraints. Split filter
models from DTOs that carry unsupported types.
Not in IR (1.0)¶
max_digits and decimal_places are rejected at extract time. Unknown
Field metadata keys are rejected rather than turned into invented
operators.