Skip to content

The contract stops over-promising and under-recording - #60

Merged
lann merged 1 commit into
error-taxonomyfrom
contract-truthfulness
Aug 12, 2026
Merged

The contract stops over-promising and under-recording#60
lann merged 1 commit into
error-taxonomyfrom
contract-truthfulness

Conversation

@lannbot

@lannbot lannbot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Issue #13 findings C10, C9 (formats), D15, and the D17 remnant — the contract-truthfulness sweep discussed on the C/D tail. Doc rulings only; no behavior changes. Stacked on #59 (shared connect paragraph).

C10 — the dial narrowing is latitude again

"There is no fallback between dial paths" was v0 implementation latitude written as normative text — the one sentence that made an upstream-backed implementation of this WIT non-conformant by construction (upstream always races paths). connect now states dial-path selection as implementation-defined (prefer one entry, race several, or fall back — all conforming), with the failure split along #59's taxonomy: exhaustion without an answer is timed-out, refusal or handshake failure is connect-failed.

The narrowing itself doesn't move an inch: endpoint/src/lib.rs already records it ("no racing or fallback between dial paths"), and the matrix rows that lean on it ("a passing echo is the assertion that QUIC flowed over UDP") keep working — they assert this implementation's recorded latitude rather than the contract.

C9 — address string formats

  • relay: an http(s) base URL; one spelling per relay, normalization implementation-defined beyond the exact string (the current pool's trailing-slash insensitivity stays an implementation detail rather than becoming contract).
  • ip: ip:port, dotted-quad or bracketed IPv6; scope-id support implementation-defined; an entry that does not parse is ignored for dialing but preserved.

D15 — resolved as a ruling, not a declaration

The investigation changed the shape of this one. The built component imports a whole toolchain wasi 0.2 tailwasi:io, wasi:cli, wasi:clocks@0.2, wasi:filesystem, and wasi:random@0.2.9 — versioned by wasi-libc, not by this repository. Declaring wasi:random alone in the source world would be arbitrary (the world would still under-declare the rest of the tail), and pinning it at today's 0.2.9 would fight toolchain drift: on mismatch the declared import and getrandom's actual import stop unifying and the component imports both.

So the ruling, written at the world: the world names the deliberately-bound surface; the composed artifact's embedded WIT is the authoritative import manifest (wasm-tools component wit <component>); and bind's deliberate entropy use (reset and token keys) rides wasi:random through the language's entropy source — stated, not hidden, without a brittle declaration.

D17 remnant

read(max: 0) resolving some([]) without waiting or consuming is documented — the last of D17's unrecorded divergences.

Verified

just check, just matrix (15 rows), just exam-deltic (6/6). Doc-only, but the full gates ran anyway.

Addresses #13 (C9, C10, D15, D17).

Issue #13 findings C10, C9 (formats), D15, and the D17 remnant — all
doc rulings, no behavior change.

C10: connect no longer promotes the v0 dial narrowing to contract.
Dial-path selection from addr.addrs is implementation-defined —
prefer, race, or fall back are all conforming — so an upstream-backed
implementation of this surface (which always races) is no longer
non-conformant by construction. This implementation's actual
selection stays recorded where the narrowings live
(endpoint/src/lib.rs); the matrix rows that lean on no-fallback assert
that recorded latitude, not the contract.

C9: transport-addr's string formats are specified — relay is an
http(s) base URL with one-spelling-per-relay guidance (normalization
is implementation-defined beyond the exact string), ip is
dotted-quad or bracketed IPv6 with scope-id support
implementation-defined and unparseable entries ignored for dialing.

D15, resolved as a ruling rather than a declaration: the built
component's import set includes a toolchain wasi 0.2 tail (io, cli,
clocks, filesystem, random — bind's reset and token keys ride
wasi:random through the language's entropy source). Declaring one of
those interfaces in the source world at a pinned version would fight
toolchain drift and split the import in two on mismatch. The world's
doc now states what the world is (the deliberately-bound surface) and
names the artifact's embedded WIT as the authoritative import
manifest.

D17 remnant: read(max: 0) resolving some([]) is documented.

Addresses #13 findings C9, C10, D15, D17.
@lannbot lannbot mentioned this pull request Aug 12, 2026
@lann
lann merged commit 712e338 into error-taxonomy Aug 12, 2026
1 check failed
@lann
lann deleted the contract-truthfulness branch August 12, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants