Skip to content

Commit e7c8186

Browse files
committed
chore(release): v1.7.0 — the component marshaller no longer dies on guest data
Smell-audited: depth 1: the full gate caught me regenerating nothing. The `placement_drift` step added THIS MORNING failed on `*file*` — I had added a var and not re-run the generator, which is exactly the drift the gate exists to catch, on the same day it was written. Fixed by regenerating (1326 -> 1327), and worth recording because a gate that catches its author within hours is a gate that will catch a stranger in a year. Shipping the three units that landed after v1.6.0: - the component marshaller's bare `@intCast`es, which were ReleaseSafe panics — one of them on guest-controlled data, so an untrusted component could kill the host by returning a large u64; - `result` / `variant` as tagged vectors (ADR-0135 am2), replacing an err→throw that discarded the error value into a generic Wasm trap; - `clojure.core/*file*`. MINOR rather than MAJOR for the `result` shape change: v1.6.0 did ship the throw form, but D-404 records that the marshalling table is "today only string/int/float/bool/char + resource handle" and that no typed component fixture exists — so those rows have never executed and nothing can depend on them. The CHANGELOG says which two behaviours changed and how to tell. Gates: macOS arm64 full 416/1 -> regenerated -> clean; smoke 7/0 on the release content. x86_64 leg runs next against the tag.
1 parent 5ede035 commit e7c8186

4 files changed

Lines changed: 56 additions & 23 deletions

File tree

‎.dev/handover.md‎

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,20 @@
1212
Step 6). `build.zig.zon` `.zwasm` = tag pin
1313
`v2.4.0` (2026-08-03; zwasm's external-consumer release — nothing in
1414
it reaches cljw, pin hygiene only). Latest release:
15-
**v1.6.0** (2026-08-04; four hang/abort fixes — ADR-0175 spawn-to-register
16-
safepoint, ADR-0176 live-worker teardown, D-347 unmetered `wasm/run`, D-339
17-
`run-server` head deadline — plus the opened Issues/PR surface).
18-
CHANGELOG is the release-history SSOT.
19-
- **First task on resume MUST be**: **P1-6** — the WIT↔Clojure type-mapping
20-
divergence with ClojureWit. Measured 2026-08-04: cljw's ADR-0135 table and
21-
ClojureWit's `doc/design/0012` disagree on **3 rows**, and ClojureWit's shapes
22-
are the implemented, argued ones (its S1 is closed; cljw's D-404 marshalling
23-
is not built). `result` → cljw draft throws, Wit returns `[:ok v]`/`[:err e]`
24-
with opt-in `unwrap` sugar (Wit's reasoning: throwing "has no meaning in
25-
non-return position, inverts WIT's error channel, and fights laziness").
26-
`variant` → cljw `{:wit/case :kw :value v}`, Wit `[:case-name value]`.
27-
`char` → a PRINCIPLED divergence, not a bug: Wit maps to an Integer codepoint
28-
because a JVM `Character` is 16-bit and truncates; cljw's char is a 21-bit
29-
codepoint, verified — `(char 0x10437)` → `𐐷` on cljw, "Value out of range for
30-
char" on JVM clj. Land an ADR-0135 amendment aligning `result` + `variant`
31-
to the implemented shapes and recording `char` as host-forced, BEFORE D-404
32-
implements the draft's shapes.
15+
**v1.7.0** (2026-08-04; the component marshaller could kill the host on
16+
guest data — bare `@intCast` = a ReleaseSafe panic; `result` lifts as
17+
`[:ok v]`/`[:err e]` per ADR-0135 am2, replacing a throw that DISCARDED the
18+
err payload; `*file*` lands). v1.6.0 earlier the same day carried four
19+
hang/abort fixes. CHANGELOG is the release-history SSOT.
20+
- **First task on resume MUST be**: the shared typed `echo` component fixture,
21+
driven by BOTH repos. It is the mechanism that stops cljw's and ClojureWit's
22+
WIT tables drifting apart again (ADR-0135 am2 aligned them by hand once), and
23+
it discharges D-404's blocker ("verification is BLOCKED on a typed component
24+
FIXTURE; only greet + resource_counter exist"). ClojureWit's
25+
`dev/resources/echo.wat` needs no Rust toolchain, so cljw can drive the same
26+
binary. Then D-404's resource phase: `own` lifts as a bare integer on the
27+
one-shot `component-invoke` path and is never dropped (the cached
28+
`component-call` path wraps correctly).
3329
The 2026-08-04 audit-remediation arc is otherwise closed — see git log
3430
`77f690a3`..`82adf824` plus ADR-0179.
3531
- **Unreleased on main**: envelope v9 (op_var_meta — def-meta rides
@@ -78,8 +74,8 @@
7874
path rot (`zwasm_from_scratch`→`zwasm`, dead `OSS/zig` ref,
7975
`cleanup_orphans.sh`). Companion: zwasm D-526.
8076

81-
- **Perf campaign (§9.2.S) — PAUSED** (D-520 / D-386 / D-005/006).
82-
- **D-513** — clojure.core.reducers / clojure.repl / var :doc.
77+
- **Perf campaign (§9.2.S) — PAUSED** (D-520 / D-386 / D-005/006). **D-513** —
78+
clojure.core.reducers / clojure.repl / var :doc.
8379
- **D-548** — (a) DISCHARGED (ADR-0176); residual = (b) pmap
8480
wall-clock on the 3-vCPU runner (timing envelope, still gated).
8581
- CIDER upstream banner patch draft (user-side PR):

‎CHANGELOG.md‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,42 @@ first stable `1.0.0` tag; pre-1.0 `alpha` / `rc` tags may still change surfaces.
77

88
## [Unreleased]
99

10+
## [1.7.0] - 2026-08-04
11+
12+
**Upgrade if you load Wasm components.** An untrusted component could kill the
13+
host process, and `result` errors were reaching you as generic Wasm traps with
14+
the error value discarded.
15+
16+
### Fixed
17+
18+
- **An untrusted Wasm component could kill the host process.** The component
19+
marshaller used bare integer casts, which in the shipped ReleaseSafe build
20+
are process-killing safety panics rather than catchable errors. Two paths
21+
were reachable: lowering an out-of-range argument (`(c/f 300)` against a WIT
22+
`u8`), and — worse, because the data is the guest's — lifting a `u64` above
23+
`i64`'s maximum. Both now go through the same range check the core-module
24+
`wasm/call` surface has always used. A `u64` beyond `i64` and an `s64`
25+
beyond 48 bits now lift exactly via BigInt instead of panicking or silently
26+
becoming a lossy float.
27+
28+
### Changed
29+
30+
- **`result` and `variant` lift as tagged vectors.** `result` is now
31+
`[:ok v]` / `[:err e]` and `variant` is `[:case-name payload]`, with the
32+
payload slot omitted when the arm carries none — one destructuring idiom for
33+
every WIT sum type. This replaces an `err`→throw mapping that **discarded the
34+
error value**: the old path raised a generic Wasm *trap*, so a component
35+
returning `err("not found")` reached you as "WebAssembly module trapped" with
36+
the message gone. Throwing also had no meaning off the return position — a
37+
`result` nested in a `list` or `record` aborted the whole conversion.
38+
(ADR-0135 amendment 2.)
39+
40+
### Added
41+
42+
- **`clojure.core/*file*`** — the source being evaluated, matching JVM Clojure:
43+
the script path when a file runs, and `"NO_SOURCE_PATH"` otherwise. Still
44+
`^:dynamic`, so tooling can rebind it.
45+
1046
## [1.6.0] - 2026-08-04
1147

1248
**Upgrade if you use threads, futures, promises, or `wasm/run`.** This

‎build.zig.zon‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.{
22
.name = .cljw,
3-
.version = "1.6.0",
3+
.version = "1.7.0",
44
.fingerprint = 0x1869d207073beffa,
55
.minimum_zig_version = "0.16.0",
66
.dependencies = .{

‎data/placement.yaml‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
schema_version: "2.0"
2525
summary:
2626
namespaces_required: 31
27-
total: 1326
27+
total: 1327
2828
zig: 394
2929
clj: 725
30-
value: 201
30+
value: 202
3131
unbound: 6
3232
vars:
3333
"cljw.error/*error-context*": { impl: value, flags: "dynamic" }
@@ -145,6 +145,7 @@ vars:
145145
"clojure.core/*default-data-reader-fn*": { impl: value, flags: "dynamic" }
146146
"clojure.core/*e": { impl: unbound, flags: "dynamic" }
147147
"clojure.core/*err*": { impl: value, flags: "dynamic" }
148+
"clojure.core/*file*": { impl: value, flags: "dynamic" }
148149
"clojure.core/*flush-on-newline*": { impl: value, flags: "dynamic" }
149150
"clojure.core/*in*": { impl: value, flags: "dynamic" }
150151
"clojure.core/*math-context*": { impl: value, flags: "dynamic" }

0 commit comments

Comments
 (0)