Resolve OQ-BAST-001: keep Validation(ValidationError<'static>) (D-BAST-009)

Converts the open question into a closed decision. Rationale: consumer
ergonomics on the combined validate_json + validate_bytes path — one
uniform payload type means one match arm downstream. Option 2
(Validation(String)) would force validate_json to flatten its
structured errors to a String, losing information on the richer path to
accommodate the less rich one. The no_std/minimal-build angle that
option 2 was meant to enable is moot: validate_json requires jsonschema
regardless, so a bytes-only no_std build already has to give up
validate_json as a separate larger decision; dropping the type from one
error variant doesn't unlock it.

Updates Phase 1 step 5 to reference D-BAST-009 for the error
construction pattern, and rewrites POC Result observation 4 from
'deferred decision' to 'decided — see D-BAST-009'.

No semver-relevant change to the Validation variant. Doc-only.
This commit is contained in:
glm-5.2 committed 2026-08-15 10:13:47 +00:00
1 parent e77268c951
commit 89f05850f2
1 file changed
+34 -14
+34 -14
View File
@@ -950,7 +950,9 @@ through JSON Schema trees do not.
4. Update `AlkTypeEngine::compile()` to accept a BAST document + root
type name
5. Implement the BAST-native validator (production version, informed
by the POC)
by the POC). Constructs `AlkTypeError::Validation` via
`jsonschema::ValidationError::custom` per [D-BAST-009](#d-bast-009-alktypeerrorvalidation-payload-shape)
— the `Validation` variant's payload type is unchanged.
6. Update `validate_json()` to accept a consumer-provided JSON Schema
and build a standard `jsonschema::Validator` (no custom keywords)
7. Update the builder API to produce BAST JSON (public methods unchanged)
@@ -1154,9 +1156,9 @@ Future crates (alktty, tunnels, sftp, git) will use BAST for their
binary formats. The codegen feature (future) will generate
readers/writers from BAST documents for these crates.
### OQ-BAST-001: `AlkTypeError::Validation` payload shape (open)
### D-BAST-009: `AlkTypeError::Validation` payload shape
**Status: open — to be decided at pivot time, not in the POC.**
**Status: decided.** Keep `Validation(jsonschema::ValidationError<'static>)`.
`AlkTypeError::Validation` currently wraps
`jsonschema::ValidationError<'static>`. Under the BAST pivot the
@@ -1164,7 +1166,7 @@ readers/writers from BAST documents for these crates.
the [POC](#poc-result--bast-native-validator) — observation 1), so the
error payload on that path is constructed via
`jsonschema::ValidationError::custom` purely to keep the variant's type
unchanged. There are two options:
unchanged. The two options were:
1. **Keep `Validation(jsonschema::ValidationError<'static>)`.** Simplest —
`ValidationError::custom` is public and `'static`, so the bytes path
@@ -1182,9 +1184,28 @@ unchanged. There are two options:
wants to drop `jsonschema` from the bytes-only path (relates to
OQ-002).
The POC deferred this — it used option 1 to keep the error type
unchanged. The decision belongs to the production refactor (Phase 1
step 5) and should be made before the validator module lands.
**Rationale for option 1:** The deciding factor is consumer ergonomics
on the *combined* path. Consumers like alkcall use both `validate_json`
(channel 0, JSON-RPC) and `validate_bytes` (binary channels) and handle
`AlkTypeError::Validation` in one place. A single uniform payload type
means one match arm covers both sources — no `Validation(jsonschema_err)
vs Validation(string)` branching downstream. Option 2 would force
`validate_json` to flatten its structured errors (instance path, schema
path, keyword) to a `String` via `Display` just to match a bytes-path
shape — the more information-rich path loses data to accommodate the
less rich one. That is the wrong direction.
The `no_std`/minimal-build angle (OQ-002) that option 2 was meant to
enable is moot in practice: `validate_json` requires `jsonschema`
regardless, so a bytes-only `no_std` build already has to give up
`validate_json` as a separate, larger decision. Dropping the type from
one error variant does not unlock that build — the dependency is load-
bearing on the other validation path. The right place to revisit this is
when/if OQ-002 is actually pursued, not preemptively.
The POC already used option 1 (via `ValidationError::custom`); the
production refactor (Phase 1 step 5) follows the same construction
pattern. No semver-relevant change to the `Validation` variant.
## Risks and Mitigations
@@ -1330,13 +1351,12 @@ validator only enforces what the materializer cannot:
4. **The `AlkTypeError::Validation` variant still wraps
`jsonschema::ValidationError<'static>`.** The POC uses
`jsonschema::ValidationError::custom` to construct these so the
error type is unchanged. The production version could either keep
this (simplest — `ValidationError::custom` is public and
`'static`) or introduce a small `Validation(String)` shape to drop
the `jsonschema` dependency from the error type. The latter is a
public-API change (the `Validation` variant's payload type changes),
so it's a semver-relevant decision to make at pivot time, not in the
POC.
error type is unchanged. This is now the decided shape for the
production refactor — see [D-BAST-009](#d-bast-009-alktypeerrorvalidation-payload-shape).
The rationale is consumer ergonomics: a single uniform payload type
means one match arm covers both `validate_json` and `validate_bytes`
errors downstream, and `validate_json`'s structured errors are worth
preserving rather than flattening to a `String`.
5. **The materializer and validator share the BAST-walking code
structure.** Both walk the same `kind`/`fields`/`mapping` tree. The