Repository navigation
0.30.1
Security
-
№658 (gh#1159) — the VM break/continue parity (the behavior change,
fail-closed; AFFECTS 0.30.0 AND EARLIER on the VM backend; the audit
guard scenario: abreak/continueinside a loop body — top-level,
inside anifguard, inside a match arm, in a nested loop — was
silently IGNORED by the VM: the body ran to the condition cap as if
the statement were absent, and a top-level form kept an unresolved
Jump(0)placeholder that tripped the infinite-loop guard, while the
tree-walking backend honored both statements; the X-1/Y-1/Q-1
silently-wrong control-flow class, the №652-a finding): the VM loop
path mirrors the TWControlFlowcontract 1:1 — every
break/continuereaches its NEAREST enclosing loop on BOTH backends
(breakexits the loop;continuestarts the next iteration — the
condition re-test forwhile, the next item for
each/each_with_index). The compiler now resolves every loop jump
from the loop-stack entry: the shared statement compiler registers a
Jump(0)placeholder in the NEAREST entry at any nesting depth and
the loop compiler patches it from the POPPED entry (the stale-local
patch loops — the pre-№658 root cause — are gone). The norms
S-BLK-011/012 + five conformance pairs pin the record; the TW is
unchanged. Found by №652 (the spec topic 2 probe); the repair follows
the №651/№629 precedent. The fix lands 2026-10-09 (this PR; after the
v0.30.0 tag b4b9abb lineage — the published tag is affected on the VM
backend; no re-tag — the №620 precedent). -
№651 (gh#1145) — the TW/VM condition parity (the behavior change,
fail-closed; AFFECTS 0.30.0 AND EARLIER on the VM backend; the audit
guard scenario: a composite or an opaque value in a condition — e.g.
if [items] { … }orif hash_password(pw) { … }— silently chose a
branch on the VM (a non-empty List took THEN, an opaque handle took
ELSE) while the tree-walking backend refused; the X-1/Y-1/Q-1
silently-wrong-guard class): the VM condition path (the new
Instruction::JumpIfNotCond, emitted for if / else-if / while / the
match guards) mirrors the TWValue::as_bool1:1 — the truthy set of
a condition is exactly {true Bool, Float ≠ 0.0, non-empty String},
Unit is falsy, and every composite / opaque / Fluid value refuses
with the stable[TYPE_MISMATCH]code on BOTH backends (the norm
S-VAL-013; the №629 loud-refusal class). The soft truthiness of
&&/||(the №532 twin, compiled to the legacyJumpIfNot) is
unchanged and stays pinned. Found by №645 (the spec-carcase
conformance build, the finding №645-a); the repair follows the №629
precedent. The fix lands 2026-10-08 (this PR; after the v0.30.0 tag
6eafee1 — the published tag is affected on the VM backend; no re-tag
— the №620 precedent).
Fixed
- #1169/#1170 (the office VM-pilot staging, FO-050; PR — this fix) —
the VM serve-boot db bootstrap (the interpreter-parity boot path; the
behavior change, fail-closed at boot; Fixed-class → rides the
0.30.1 train):db { url: env("NAME") }on the VM serve lane
resolved the URL inside EVERY route handler (the №758 lazy
first-db-access semantics), so the same read went through the №259
serve-route gate — withoutMETALOGOS_ENV_ALLOWLISTevery request
500'd with ENV_NOT_PERMITTED (the interpreter resolves the url
expression at BOOT in the Process context and serves the same file +
env with 200), and the schema-DDL bootstrap only ran when a request
first touched the db — on the office's real corpus (30 routes) a
fresh DB stayed at 0 tables and the first request died with an
unrelated arity 500 instead of an honest bootstrap diagnostic
([vm/db] Connectedwas already on the boot log — the TW
registration lane opened the file — while the VM request lane kept
re-resolving and re-refusing per request). The fix: at VM serve boot
(run_server+ the test harness, on the compiled Program BEFORE it
is shared)boot_resolve_db_urlresolves the env name ONCE in the
Process (boot) context — the resolved literal replacesdb_url_env,
so the request path performs NO env() reads at all — and replays the
schema DDL eagerly on a boot connection (same open + WAL +
DDL-tolerance steps as the lazy open), so a fresh DB carries the
schema BEFORE the first request (the #1169 interpreter parity); an
unset variable is a LOUD BOOT error naming the variable and the
remedy (was: a silent OK boot — the TW registration error line was
swallowed by the merge, then per-request 500s); a non-sqlite URL is
the same LOUD boot error it used to be at the first access (№758
text moved to boot time). The №259 serve-route env gate is
UNCHANGED for program-levelenv()calls — the boot read is the
Process-context class (the №259 contract, the №457 registration
zone). The lazy per-request connection open stays for requests that
never touch the db (№409 cost contract);reset_for_reusesemantics
unchanged (№403 4/4). Contract tests
metalogos-server/tests/issue_1169_1170_vm_boot_db.rs(T1: the
db-touching route serves WITHOUT the allowlist — was 500
ENV_NOT_PERMITTED per request; T2: the fresh DB carries the schema
table immediately after boot; T3: the unset variable fails the BOOT
loudly naming the variable — was a silent OK boot; T4: the
literal-URL twin — no regression on the №758 surface); №758 5/5, №259
7/7, №160 23/23 (1 ignored), №403 4/4, №457 5/5, №399 4/4 GREEN.
TheTeamSkillWired expects 2 argsfirst-request symptom of #1169
(the office corpus) is NOT reproduced minimally and is NOT claimed
fixed — it is expected to disappear with the empty-schema state gone;
the minimal-repro ask stands in the issue thread.