validate
tit.server.routes.validate ¶
POST /api/validate/{kind} -- field-level config validation, no side effects.
Deserializes config through :func:tit.config_io.deserialize_config for the dataclass that
kind maps to (see :func:cls_for), catching exactly what a config dataclass's own
__post_init__ (or a bad _type/field shape) can raise, and reports it as
{ok, errors: [{path, message}]} -- the UI never re-implements these rules (design rule R1);
this route only surfaces them. Exhaustive-search mask paths are also checked for
accessibility before a plan or costly leadfield load can proceed.
Kind -> config-class resolution¶
Most kinds map to exactly one dataclass in :data:tit.config_io.CONFIG_CLASS_REGISTRY
(:data:SIMPLE_KIND_CLASS). Two kinds do not: stats (GroupComparisonConfig or
CorrelationConfig) and blender (MontageConfig/VectorConfig/RegionConfig/SubcorticalConfig) --
the frozen PipelineConfig union in contracts/openapi.yaml lists all of them under the
same kind/path parameter with no other discriminant on the object itself. This module resolves
the ambiguity with a config["_type"] key (see :data:AMBIGUOUS_KIND_CLASSES), the same
discriminator convention :mod:tit.config_io already uses for union-typed fields (ROIs,
electrodes, montages) -- just applied here to the top-level kind/class choice. _type is not a
field of any of these dataclasses, so :func:~tit.config_io.deserialize_config silently ignores
it (documented behavior: "keys in data that are not fields of cls ... are ignored"), making
this additive rather than a contract change. NO_SCHEMA_KINDS is empty as of the runners
lane registering NiftiAverageConfig/NilearnConfig in
:data:~tit.config_io.CONFIG_CLASS_REGISTRY -- kept as a (currently-empty) frozenset rather
than removed outright since contracts/generated/config.schema.json has not been regenerated with these two
$defs yet (a B4/F1b follow-up: docker exec tit-v3-spike simnibs_python
dev/build_schema.py), so the desktop's generated types don't know about them even though
this route already validates/plans them for real.
This is a documented design decision by this track (B3), not something contracts/openapi.yaml
specifies -- flagged in the B3 report for F1a/the orchestrator in case a future contract revision
wants an explicit discriminant instead.
KindNotConfigurable ¶
Bases: ValueError
Raised by :func:cls_for for an unknown _type on an ambiguous kind.
cls_for ¶
Resolve kind (and, for an ambiguous kind, config_body["_type"]) to a dataclass.
Parameters¶
kind : str
A :data:ALL_KINDS member (callers should 404 first for anything else).
config_body : dict
The request's raw config object (read for _type only when kind is
ambiguous; never mutated).
Returns¶
type or None
None for a :data:NO_SCHEMA_KINDS member (nothing to validate against yet).
Raises¶
KindNotConfigurable
If kind is ambiguous and _type (or its default) does not name one of its
known classes.