fed-sx-types Phase 4: object-schema validation stage in pipeline
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 54s

pipeline:apply_object_schema/2 (+ stage_object_schema/1 factory) — the
object-schema stage between activity-type validation and the kernel
append (plans/fed-sx-host-types.md step 4). When an inbound activity's
:object declares a refinement type ({type, TypeName}), resolve it
(Cfg type_index: TypeName -> TypeCid; then peer_types:lookup_or_fetch/2,
a local hit or a wire fetch) and apply the record's refinement schema
to the object's :field_values, rejecting on schema-fail with
{error, {validation_failed, object_schema}}.

The schema is either a 1-arity Erlang predicate (substrate stand-in,
locally stored) or a term_codec-safe {required, [Field,...]} constraint
(so a wire-fetched record validates too). Default
strict_object_schema = false: an unresolvable type is let through (the
skip is where a validation_skipped log belongs); strict rejects.
Objects with no declared type, and names absent from the local index,
are skipped (open-world).

Test: next/tests/object_schema.sh (15) — local hit, wire fetch, fetch
failure strict/non-strict, no peer_types, untyped object, undeclared
name, fun + data schema forms, no-schema record, stage composition.

No regression: pipeline_signature, pipeline_driver green. Plan doc
steps 1-4 marked done.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-30 15:50:45 +00:00
parent 441a895737
commit 89dd23c287
3 changed files with 306 additions and 10 deletions

View File

@@ -68,7 +68,7 @@ Cfg-supplied `type_fetch_fn :: fun ((TypeCid, Cfg) -> {ok, Bytes} |
record. No fn → `{error, no_fetch_fn}`; fetch error or bad bytes do not
poison the cache. Test: `next/tests/peer_types.sh`.
### Step 3 — `/types/<cid>` route + `discovery_type_fetch.erl` — TODO
### Step 3 — `/types/<cid>` route + `discovery_type_fetch.erl` — DONE
`http_server.erl` serves `GET /types/<cid>` with
`Accept: application/vnd.fed-sx.type-doc`: the cached TypeRecord
@@ -76,15 +76,21 @@ poison the cache. Test: `next/tests/peer_types.sh`.
holds the live-HTTP closure that `peer_types:lookup_or_fetch` calls.
Tests: `next/tests/peer_types_route.sh`, `next/tests/discovery_type_fetch.sh`.
### Step 4 — object-schema validation stage in `pipeline.erl` — TODO
### Step 4 — object-schema validation stage in `pipeline.erl` — DONE
A new `apply_object_schema/2` stage between activity-type validation
and the kernel append. When an inbound object carries `{type, TypeName}`,
resolve the TypeRecord (local Define-name index → CID →
`peer_types:lookup_or_fetch`) and apply its refinement schema to the
object's field-values. Default `strict_object_schema = false`: an
unresolvable type is let through with a `validation_skipped` log;
opt-in strict mode rejects. Test: `next/tests/object_schema.sh`.
`pipeline:apply_object_schema/2` (+ `stage_object_schema/1` factory)
sits between activity-type validation and the kernel append. When an
inbound object carries `{type, TypeName}`, resolve the TypeRecord
(Cfg `type_index`: TypeName → TypeCid; then
`peer_types:lookup_or_fetch/2`) and apply its refinement schema to the
object's `:field_values`. The schema is either a 1-arity Erlang
predicate (the substrate stand-in, for locally-defined types) or a
term_codec-safe `{required, [Field, ...]}` data constraint (so a
wire-fetched record validates too). Default `strict_object_schema =
false`: an unresolvable type is let through (the non-strict skip is
where a `validation_skipped` log belongs); opt-in strict rejects.
Objects with no declared type, and type names absent from the local
index, are skipped (open-world). Test: `next/tests/object_schema.sh`.
## Out of scope (deliberately)