Commit Graph

11 Commits

Author SHA1 Message Date
380160cc2b refactor(validation): decompose XSD instance validation into composable rules
The two monolithic XSD content/identity rules only satisfied the OpenAPIKit
validation idiom at the wrong granularity: no per-constraint removability,
no isolable failing/near-miss tests. Split them into 32 named rules, each
finding tagged at its origin and cached per XSDContext so the walk still
runs once per document (the #101 decision against duplicating XSD's
recursive type resolution still holds). Wired the streaming path's ID/IDREF
and identity checks through the same framework instead of calling the
validators imperatively, and added the unwrapAndLookup combinator the rule
already named as required.

Also includes the mandated repo-wide swiftformat/swiftlint pass.
2026-07-12 14:12:17 +02:00
ad44fe77b9
fix(schema): reject a simpleContent restriction that relaxes a required attribute (#326)
derivation-ok-restriction.2 (a base required attribute may not become
optional in a restriction) ran only over complexContent restrictions, so
a simpleContent restriction that relaxed a required attribute was accepted.
The attribute-use restriction check now runs over both derivation roots.
Closes XSTS particlesZ030_d, which libxml2 also rejects, so this aligns
with the reference rather than exceeding it. XSTS invalid-schemas-accepted
10 to 9 with valid-schemas-rejected held at 0 (full archive). Guarded by
SimpleContentAttrRestrictionTests; the XSTSSuiteTests baseline is updated.
2026-06-26 11:35:33 +02:00
49fe824601 feat(schema): locate attribute-pass schema diagnostics
Convert the three attribute-pass compile checkers to located findings so
each error attaches to its declaring node instead of the schema root (#169):
an attribute declaration in the XSI namespace locates on the attribute
(xsiNamespaceAttributeFindings); a duplicate attribute use or a second
ID-typed attribute locates on its declaring complexType or attributeGroup,
and an attribute reference contradicting a global fixed value locates on the
reference (attributeUseFindings); and a complex-type restriction that
relaxes a base attribute use or widens the attribute wildcard locates on the
restriction (attributeRestrictionFindings).

Each predicate, traversal order, and reason string is unchanged; only the
location each finding carries differs. The set-level uniqueness/single-ID
findings reuse the existing attributeSetErrors helper, mapping each onto its
declaring container node. An attribute restriction violation has no source
node of its own (the attribute use is a resolved model value), so it locates
on the restriction performing the illegal narrowing. The three checkers had
exactly one caller each, so each is renamed in place and the .unlocated wrap
dropped. Adds a located-diagnostics test per checker family.
2026-06-21 16:28:10 +02:00
ceca006c45 fix(schema): a restriction's attribute wildcard must subset the base's (#145)
cos-ct-restricts.4: a base type with no attribute wildcard admits none (so a
restriction may not introduce one), and a wider namespace constraint such as
##any over ##other, or a weakened processContents, is not a subset. Reuses the
wildcard subset check (ParticleRestriction.narrows, now internal).

XSTS invalid-schemas-accepted 131 to 128, no other bucket moved.
2026-06-17 18:46:04 +02:00
c029505c3e fix(schema): a restriction may not add an attribute outside the base wildcard (#145)
An attribute a complexContent restriction declares with no matching base
attribute use must be admitted by the base type's anyAttribute wildcard
(cos-ct-restricts.3); e.g. a no-namespace attribute is not admitted by a
##other wildcard. A prohibited declaration still validly removes an attribute.

XSTS invalid-schemas-accepted 132 to 131, no other bucket moved.
2026-06-17 18:31:40 +02:00
229d7df3d0 feat(validation,schema): composable validation framework and cross-document composition
Ship the OpenAPIKit-style validation layer (builtin rules, warnings channel,
Validator tiers, coverage gates) and wire XSD compile checks through it. Advance
#161 with chameleon include validation, multi-container reference resolution,
and include targetNamespace composition rules so merged schema sets compile
correctly when a schemaLoader is provided.
2026-06-16 09:57:43 +02:00
9004efe400 fix(schema): inherit and prohibit attributes under complexContent restriction 2026-06-15 18:52:23 +02:00
31fe3e7c22 feat(schema): enforce particle element type restriction and bypass prohibited attributes 2026-06-15 18:10:21 +02:00
b6575150e8 feat(schema): enforce attribute restriction type derivation (derivation-ok-restriction.1)
Require that any restricted attribute has a type validly derived by restriction from its base counterpart. Validates atomic built-in derivation, list item type restrictions, and union member/subset relationships recursively. Updates baseline to 362 accepted invalid schemas.
2026-06-15 17:46:15 +02:00
f86a7c9ade feat(schema): enforce attribute fixed value constraint under restriction 2026-06-15 16:24:32 +02:00
b80e31d562 feat(schema): a restriction may not relax a required base attribute (cos-ct-derived-ok)
In a complexContent restriction, an attribute the restriction redeclares that the
base type marks use="required" may not be made optional or prohibited. Only
attributes explicitly redeclared that also exist in the base are checked; an
omitted attribute is inherited unchanged. The base reference must resolve to the
schema's own target namespace, and the check stands down for a schema that
composes other documents.

The matching fixed-value clause is deliberately not enforced: it requires
comparing the two fixed values in the attribute type's value space, not lexically
(a list-typed fixed value differing only in whitespace is the same value), so a
string comparison wrongly rejects valid schemas. That clause is left for a later
change (a disclosed under-rejection).

XSTS: invalid schemas accepted 394 to 390, no other bucket raised.
2026-06-15 16:09:02 +02:00