Four open questions were scattered inline in builder.md and the POC findings doc. Moved them into the central OQ tracker under docs/architecture/questions/ and updated the index: - OQ-004: Discriminator::Field name type (&str vs String) — raised in builder.md during ADR-009 spec drafting - OQ-005: Union materialization shape (byte-offset vs field-name consistency) — raised in the POC findings - OQ-006: Builder spec Example 3 wrap Union in Struct — raised in the POC findings (doc fix; engine requires AlkType:Struct at top level) - OQ-007: Bytes materialization lossy UTF-8 — raised in the POC findings (blocks SFTP use case for validate_bytes) Index updates: - open-questions.md: new 'Schema Construction' and 'Validation' theme groups; new 'Open' section for active investigation targets (distinct from 'Deferred / Blocked' which holds scope-parked OQs) - README.md: OQ table extended with OQ-004 through OQ-007 - builder.md: inline OQ-004 replaced with a tracker reference - findings.md: inline OQ-005/006/007 replaced with tracker references Doc-only change; 369 tests pass.
9.1 KiB
status, last_updated
| status | last_updated |
|---|---|
| draft | 2026-08-11 |
Open Questions
Each open question lives in its own file under questions/,
named NNN-slug.md (mirroring the ADR convention). This file is the index:
theme-grouped tables for scannability, plus a cross-theme
Open section (active investigation targets) and a
Deferred / Blocked section that surfaces the
safe-exit deferrals with their blocking conditions inline — so "what's
currently on the architect's desk" and "what's currently parked and why"
are each answerable at a glance.
Status values:
open— Needs to be resolved now. Has a clear path to resolution.resolved— Decided. The resolution is stated cleanly, without caveats about how it could be changed later.deferred(scope)— Cannot be resolved yet. The information is genuinely missing — a crate spec, POC result, or use case that doesn't exist yet. Has a concrete blocking condition. Not a failure — scope management.deferred(unclear)— Cannot be resolved yet. The pieces exist (decided in other ADRs, existing types, existing patterns) but the composition — how they fit together — isn't clear yet. Resolution requires investigation (work through examples, maybe POC), not waiting. Has a concrete investigation target and an impacts field. Not a failure — honest uncertainty in a poorly-defined problem space.partially resolved— Some aspects decided, others deferred or open.dissolved— The question was reframed out of existence (e.g., superseded by an ADR that retires the premise). Kept for reference.
Impacts field: Every unresolved OQ (open, deferred(scope),
deferred(unclear), partially resolved) should have an Impacts
field stating what it blocks downstream. Be specific: "blocks the first
hub deployment because the hub dials workers" not "blocks the hub
crate." This is the triage signal that makes the deferral's urgency
visible.
Door type classifications describe reversal cost (how expensive it is to undo), not urgency:
- One-way door: Reversal requires rewriting significant code or permanently closes a capability. Getting it wrong is expensive — requires ADR before implementation.
- Two-way door: Reversal is cheap or additive. Getting it wrong is recoverable — decide, implement, revert if needed.
Door type is separate from whether a decision is made. A two-way door is a decision you make now and can revert later, not a decision to defer.
By Theme
Layout Engine
| OQ | Title | Status | Door | Pri |
|---|---|---|---|---|
| OQ-001 | Arrays of Variable-Length-Element Structs | deferred(scope) | two | low |
Platform Support
| OQ | Title | Status | Door | Pri |
|---|---|---|---|---|
| OQ-002 | no_std + alloc Support |
deferred(scope) | two | low |
Schema Construction
| OQ | Title | Status | Door | Pri |
|---|---|---|---|---|
| OQ-003 | Builder API for Schema Construction | resolved (ADR-009) | two | med |
| OQ-004 | Discriminator::Field name — &str or String |
open | two | low |
| OQ-006 | Builder spec Example 3 — wrap Union in a Struct |
open | two | low |
Validation
| OQ | Title | Status | Door | Pri |
|---|---|---|---|---|
| OQ-005 | Union materialization shape — byte-offset vs field-name consistency |
open | two | med |
| OQ-007 | Bytes materialization — lossy UTF-8 conversion |
open | one | med |
Open
Active investigation targets — questions with a clear path to resolution that need to be worked through, not waited on. Each has a concrete investigation target. This section exists so "what's currently on the architect's desk" is answerable at a glance.
OQ-004: Discriminator::Field name — &str or String
- Investigation target: Decide whether
Discriminator::Field { name }should borrow (&str) or own (String). The builder consumesSelfon setters, so&strwould require a lifetime parameter onDiscriminator(and transitivelySchema::union_). LikelyStringfor ownership simplicity. - Priority: low (doesn't block the chunk header POC; must be resolved before the SFTP Packet POC's field-name discriminator path)
- Full file: OQ-004
OQ-005: Union materialization shape — byte-offset vs field-name consistency
- Investigation target: The current
materialize_union_packedreturns inconsistent shapes for the two discriminator kinds (byte- offset produces{ "__discriminator": <u32>, ...fields }; field-name produces the struct fields directly). Decide on one consistent shape. Work through the SFTP Packetvalidate_bytesexample to surface what thejsonschemavalidator needs to see for aAlkType:Unionfield. - Priority: medium (blocks the SFTP Packet
validate_bytesPOC, the natural next round) - Full file: OQ-005
OQ-006: Builder spec Example 3 — wrap Union in a Struct
- Investigation target: Update builder.md Example 3 (SFTP Packet)
to wrap the
Unionin aStruct— the engine requiresAlkType:Structat the top level (ADR-002), and the wrapped shape matches SFTP's actual wire format ([length][type][payload]). The POC already uses the wrapped shape; the spec example just hasn't been updated. - Priority: low (documentation fix; doesn't block any implementation)
- Full file: OQ-006
OQ-007: Bytes materialization — lossy UTF-8 conversion
- Investigation target: The current materializer uses
String::from_utf8_lossyforAlkType:Bytesfields, which corrupts non-UTF-8 bytes. Decide on a round-trippable form (base64 with aformatconstraint, orValue::Arrayof u8 with a validator that accepts arrays). Work through SFTP's binaryhandle/datafields to surface whatvalidate_bytescallers actually need. - Priority: medium (blocks the SFTP use case for
validate_bytes; does not block the chunk header or call input schema) - Door type: one-way (changing what the validator sees is a semantic break for consumers that depend on the shape)
- Full file: OQ-007
Deferred / Blocked
The safe-exit visibility surface. These questions are parked because the information needed to resolve them does not exist yet — each has a concrete blocking condition. They are not failures; they are scope management. This section exists so "what's currently blocking the architect" is answerable at a glance, not by filtering the tables above.
Note
: OQ-003 (Builder API) was resolved by ADR-009 in v0.1.0 and is retained below for traceability — it's marked RESOLVED, not deferred. The currently-parked OQs are OQ-001 and OQ-002.
OQ-001: Arrays of Variable-Length-Element Structs
- Blocked on: A concrete consumer that needs arrays of structs with
variable-length fields, where the elements are interleaved
(
[fixed_0][str_0][fixed_1][str_1]...) and the engine must walk sequentially rather than use a fixed stride. The SFTPNamepacket hasVec<File>whereFilecontains strings, but SFTP serializes this as a sequence of length-prefixed strings (the serdeSeqAccesspattern), not as an array of fixed-stride structs. Arrays of fixed-size structs are fully supported. - Priority: low
- Full file: OQ-001
OQ-002: no_std + alloc Support
- Blocked on: An embedded use case that requires
no_std+alloc(e.g., a microcontroller running Rust withoutstd). The WASM target hasstdavailable viawasm-bindgen. The engine's core (offset computation, read/write) is already allocation-free; thejsonschemadependency is the onlyallocconsumer. - Priority: low
- Full file: OQ-002
OQ-003: Builder API for Schema Construction — RESOLVED
- Status: resolved by ADR-009 in v0.1.0.
- Unblocking condition: alkcall — the merged
alknet-call+alknet-channelsextraction from@alkdev/alknet— is the concrete consumer that needs programmatic schema construction in Rust. It builds both binary-layout schemas (channels' 8-byte chunk header) and JSON payload schemas (OperationSpecinput/output/error schemas) at runtime. - Resolution: A fluent Rust builder producing
serde_json::Value, covering AlkType kinds and standard JSON Schema. Implemented insrc/builder.rs; spec in builder.md. See ADR-009. - Full file: OQ-003