Status: Superseded by ADR-289 — its D1-D3 are D31-D33 there
Date: September 24, 2026
Target Version: Nikaia 0.0.182
Answers: open-decisions.md’s may a route be
refused by what its handler touches?, decided by the owner — option 1, and
against that page’s recommendation of 3
Related: ADR-033 D4 (the touches column), ADR-108
D4 (the listing that does earn its keep), ADR-084 (a keyword is the
most expensive thing a language adds), ADR-010 D1 (which reading
gets the word), ADR-195 D5 (the last time this page’s framing was
corrected by its answer)
Every function in this language carries a touches column, inferred from its
body and closed over what the body calls. So at the moment a program writes a
handler, the compiler already knows whether that handler reaches the filesystem —
transitively, which no other language’s http.server knows, because no other one
has the column.
The question was what to do with that, and it named three options: refuse nothing
(1), let a route declare what it may reach and refuse more (2), or list it
in nikaia --trust and refuse nothing (3). The page recommended 3.
There is no reaching: at a route, no word for it in the language, and no NK
code. A handler that reads a file is a handler that reads a file.
The page’s own argument for this half stands and is not re-made here: a refusal
earns its keep by refusing programs that would otherwise be wrong, and this one
would mostly refuse programs that are right — Part III
C.4’s cost paid for a property nobody was surprised by.
The coarse version is also answered by a granularity the column does not have:
touches says file(path) read, where the path is a parameter’s name and not a
value.
nikaia --trust gains no section.This is the half the page got wrong, and the owner’s reason is the one that decides it: in a real application almost every route reaches something. A report whose rows are nearly all non-empty tells a reviewer nothing they can act on. It is the argument this project already makes about a gate — a gate that is a fifth false alarm teaches people to ignore it (the ADR index’s own note on the citation guard) — and a report every row of which fires is the same mistake in the other tool.
A listing is not free. The page treated 3 as the cheap direction on the
grounds that the listing is the data a later refusal would read, so nothing has
to be undone. What it did not count is the design a useful one needs, and
which nobody has done: which touches are ordinary for a handler and therefore
filtered, and which a person asks for on purpose — a switch along the lines of
--extended or --including http. That is a question with its own answer, and it
is not a 0.1.0 target.
Option 1 costs nothing and stays extendable, which is the whole of why it is the right one now: no word is added to the language, no report grows a section nobody reads, and the column is still there the day somebody designs the filter.
ADR-108 D4’s listing works, and it is worth saying why, because it
is what made 3 look free. That report lists every site that writes
fs::Root::Anywhere or a literal "/" root — a way around a check. Such a
list is short by construction: it holds the exceptions, and a program with none
prints none. A list of what every handler touches is long by construction, and
a report that is long by construction is read once.
So a report earns its keep the way a refusal does — by what it leaves out.
And this corrects a sentence this project wrote at 0.0.178. The question’s
entry gained a paragraph saying fs::Root’s arrival was option 3 arriving for
the filesystem before this question is answered for a route. It is not: one lists
exceptions and the other would list the ordinary case, which is the difference
between the two reports and not a step from one to the other. This is the second
time an answer has corrected how open-decisions.md
framed its own question (ADR-195 D5 was the first), and both
corrections are the page working rather than failing: an entry written to be
answerable is an entry whose framing can be argued with.
--trust keeps the two sections it has: the input’s provenance
(ADR-010 D7) and ADR-108 D4’s roots with nothing to
check against.touches column keeps its consumers — the ordering analysis
(ADR-033) and the build-time rule
(ADR-075 D1) — and gains none.The listing is not refused for ever; it is refused for now, and what it would take is written down here so it does not have to be found again:
--extended, --including http, or a name nobody has picked. Whether it is one
switch or a set is part of the same question.touches can, and that
asymmetry is a thing to design around rather than to average away.