Compare commits
1 Commits
19a84a5aae
...
ee9bf03403
| Author | SHA1 | Date | |
|---|---|---|---|
| ee9bf03403 |
31
README.md
31
README.md
@@ -1052,19 +1052,24 @@ driving the real code with hostile values — and, for every field whose only
|
||||
defence is that nothing dereferences it, by booting the real popup entry point
|
||||
over that value onto every view the popup can reopen onto. That last part is
|
||||
what makes the claim falsifiable, because this defect class lives on the restore
|
||||
path rather than on the home screen: a field one of those boots corrupts and a
|
||||
restorable view dereferences on its render fails `make check`, at either
|
||||
polarity — a value nothing writes is a wrong-typed one and therefore truthy, so
|
||||
each such field is also driven falsy, or proven unable to be falsy after the
|
||||
floor. So does a field that gains a floor while its row still claims it has
|
||||
none, and so does a field added to `PERSISTED_FIELDS` with no row at all. Two
|
||||
things the boots do not drive: a MIX of polarities, since one boot puts every
|
||||
corrupted field on the same slot, so a branch reached only when one is truthy
|
||||
and another falsy is not entered; and whatever no stored record reaches by
|
||||
itself — a view only forward navigation opens, and anything behind a click. The
|
||||
per-field justification that used to live in the header of
|
||||
`src/shared/stateSchema.js` shipped a false claim in three consecutive changes,
|
||||
each caught only by a reviewer re-deriving thirty fields by hand.
|
||||
path rather than on the home screen: whenever one of those boots reaches a
|
||||
structural dereference on the view it restored onto, `make check` fails —
|
||||
including a dereference that takes two corrupted fields at once, because the
|
||||
verdict is the combined boot and the per-field re-boot that names a culprit can
|
||||
only decorate the message. Each swept field is driven at both polarities, or
|
||||
proven unable to be falsy after the floor, since a value nothing writes is
|
||||
wrong-typed and therefore truthy and would otherwise leave every `if (!state.x)`
|
||||
branch unentered. So does a field that gains a floor while its row still claims
|
||||
it has none, and so does a field added to `PERSISTED_FIELDS` with no row at all.
|
||||
What the boots do not drive is every combination: four value combinations per
|
||||
view, not the product of the twelve swept fields. The last of the four is itself
|
||||
a mix — every falsy-capable field falsy against the ones that cannot be falsy —
|
||||
so many two-field interactions are driven; one needing a pairing none of the
|
||||
four produces is not. Nor is anything no stored record reaches by itself — a
|
||||
view only forward navigation opens, and anything behind a click. The per-field
|
||||
justification that used to live in the header of `src/shared/stateSchema.js`
|
||||
shipped a false claim in three consecutive changes, each caught only by a
|
||||
reviewer re-deriving thirty fields by hand.
|
||||
|
||||
The `allowedSites` case is why the entry check is not optional. A stored
|
||||
`{"0x…": "notalist"}` is a well-formed object holding a malformed entry: it
|
||||
|
||||
10
TODO.md
10
TODO.md
@@ -86,8 +86,14 @@ but the review is broader than any of them.
|
||||
both polarities — a value nothing writes is wrong-typed and so truthy, so a
|
||||
falsy slot is driven too, or the field is proven unable to be falsy after the
|
||||
floor. A field with no row, a field that gains a floor while its row still
|
||||
claims it has none, and a field one of those boots corrupts and a restorable
|
||||
view dereferences on its render now all fail `make check`.
|
||||
claims it has none, and any structural dereference one of those boots reaches
|
||||
on the view it restored onto now all fail `make check` — including a
|
||||
dereference that takes two corrupted fields at once, because the verdict is
|
||||
the combined boot and the per-field re-boot that names a culprit can only
|
||||
decorate the message. What is not driven is every combination: four value
|
||||
combinations per view rather than the product of the twelve swept fields, so
|
||||
an interaction needing a pairing none of the four produces goes unseen, as
|
||||
does anything no stored record reaches by itself.
|
||||
- 2026-08-23: A swap amount and the token it is counted in now always come from
|
||||
the same hop, on both sides of the approval screen
|
||||
([#359](https://git.eeqj.de/sneak/AutistMask/issues/359) and
|
||||
|
||||
@@ -38,15 +38,24 @@
|
||||
// real popup entry point onto EVERY view the popup can reopen onto.
|
||||
//
|
||||
// That last part is the whole point, because this defect class lives on the
|
||||
// RESTORE path and not on Home: a field one of those boots corrupts and a
|
||||
// restorable view dereferences on its render turns that suite red, at either
|
||||
// polarity — a value nothing writes is wrong-typed and so truthy, so each such
|
||||
// field is also driven falsy, or proven unable to be falsy after the floor. So
|
||||
// does a field that gains a floor while its row still claims it has none. Two
|
||||
// things the boots do not drive: a MIX of polarities, since one boot puts every
|
||||
// corrupted field on the same slot; and whatever no stored record reaches by
|
||||
// itself — a view only forward navigation opens, and anything behind a click. A
|
||||
// field added to PERSISTED_FIELDS with no row fails the suite too.
|
||||
// RESTORE path and not on Home: whenever one of those boots reaches a
|
||||
// structural dereference on the view it restored onto, that suite goes red —
|
||||
// including a dereference that takes two corrupted fields at once, since the
|
||||
// verdict is the combined boot and the per-field re-boot that names a culprit
|
||||
// can only decorate the message. Each swept field is driven at both
|
||||
// polarities, or proven unable to be falsy after the floor: a value nothing
|
||||
// writes is wrong-typed and so truthy, which would otherwise leave every
|
||||
// `if (!state.x)` branch unentered. So does a field that gains a floor while
|
||||
// its row still claims it has none, and a field added to PERSISTED_FIELDS with
|
||||
// no row at all.
|
||||
//
|
||||
// What the boots do NOT drive is every combination: four value combinations
|
||||
// per view, not the product of the twelve swept fields. The last of the four
|
||||
// is itself a mix — every falsy-capable field falsy against the ones that
|
||||
// cannot be falsy — so many two-field interactions are driven; one needing a
|
||||
// pairing none of the four produces is not. Nor is anything no stored record
|
||||
// reaches by itself: a view only forward navigation opens, and anything behind
|
||||
// a click.
|
||||
//
|
||||
// That test exists because this comment did not work. It carried a
|
||||
// hand-written justification per field, and it shipped a false one in three
|
||||
|
||||
@@ -44,11 +44,22 @@
|
||||
// reason, and a field that cannot be falsy after the floor says so in its row
|
||||
// and is proven so.
|
||||
//
|
||||
// What that buys: a field any restorable view dereferences on that view's
|
||||
// render turns this file red, at either polarity. What it does not buy is a
|
||||
// MIX of polarities — one boot puts every swept field on the same slot, so a
|
||||
// branch reached only when one swept field is truthy and another falsy is not
|
||||
// entered. Booting every field separately at every value would be several
|
||||
// What that buys: whenever one of those boots reaches a structural
|
||||
// dereference on the view it restored onto, this file goes red — INCLUDING a
|
||||
// dereference that takes two corrupted fields at once, because the verdict is
|
||||
// the combined boot itself and the per-field re-boot below can only decorate
|
||||
// the message. That is the one thing an earlier version of this file got
|
||||
// wrong: it asserted on the per-field list, so an observed dead popup that no
|
||||
// single field reproduced was reported green.
|
||||
//
|
||||
// What it does NOT buy is every combination — four value combinations per
|
||||
// view are driven, not the product of twelve fields. Note that the last slot
|
||||
// is itself a MIX rather than a uniform polarity: every falsy-capable field is
|
||||
// falsy on it while the neverFalsy ones stay hostile-truthy, so many two-field
|
||||
// interactions are driven and fatal. One that needs a pairing none of the four
|
||||
// slots produces is not driven at all. Nor is anything no stored record
|
||||
// reaches by itself: a view only forward navigation opens, and anything behind
|
||||
// a click. Booting every field separately at every value would be several
|
||||
// hundred boots and most of the suite's budget; this is forty-four.
|
||||
//
|
||||
// The three claims this replaced, all false, all caught here by construction:
|
||||
@@ -100,6 +111,19 @@ const swept = (row) => row.kind === KIND.LOOSE || Boolean(row.alsoSweep);
|
||||
// `if (!state.x) { state.y.deref() }`, so the falsy slot is not optional.
|
||||
const sweptValues = (row) => [...row.hostile, ...(row.falsy || [])];
|
||||
|
||||
// What may count toward a row's POLARITY: the swept values, plus only those
|
||||
// `hostileRestore` entries driven onto every restorable view. An entry that
|
||||
// carries `views: [...]` reaches only those renderers, so counting it would
|
||||
// let a future row claim a polarity that one view sees and the other ten do
|
||||
// not. No current row does that — the restricted entries are all viewData's,
|
||||
// and viewData is neverFalsy — and this is what keeps it so.
|
||||
const polarityValues = (row) => [
|
||||
...sweptValues(row),
|
||||
...(row.hostileRestore || [])
|
||||
.filter((entry) => !entry.views)
|
||||
.map((entry) => entry.value),
|
||||
];
|
||||
|
||||
// ------------------------------------------------------------------ the table
|
||||
//
|
||||
// `hostile` is values a stored record can carry that nothing in src/ ever
|
||||
@@ -586,10 +610,9 @@ describe("both polarities of every swept field are driven", () => {
|
||||
test(`${row.field}: truthy and falsy`, () => {
|
||||
// What the boots below actually drive, floored the way a renderer
|
||||
// sees it — not what the row says it drives.
|
||||
const driven = [
|
||||
...sweptValues(row),
|
||||
...(row.hostileRestore || []).map((entry) => entry.value),
|
||||
].map((value) => floored(row.field, value));
|
||||
const driven = polarityValues(row).map((value) =>
|
||||
floored(row.field, value),
|
||||
);
|
||||
|
||||
expect({
|
||||
truthy: driven.some((value) => Boolean(value)),
|
||||
@@ -738,17 +761,23 @@ describe("a hostile routing value restoring onto", () => {
|
||||
// routing turns this red and has to declare `routes` and take the individual
|
||||
// sweep above.
|
||||
//
|
||||
// Combining does hide one thing, and the last slot is what stops it. A hostile
|
||||
// Combining hides one thing, and the last slot is what stops it. A hostile
|
||||
// value is wrong-typed and therefore TRUTHY, so on a boot where every swept
|
||||
// field is hostile, no `if (!state.x)` branch is entered — and a dereference
|
||||
// inside such a branch would go unseen however loudly it throws. The last slot
|
||||
// is the falsy one: every swept field that CAN be falsy is falsy on it, which
|
||||
// is also the state an ordinary install boots in for three of them, while the
|
||||
// fields that cannot be falsy stay hostile. Beyond that, a throw fails the boot
|
||||
// whichever field threw, and a renderer that never ran is what `restored`
|
||||
// forbids. When it does go red, the same view is re-booted one field at a time
|
||||
// so the failure names the fields rather than leaving a reader to bisect twelve
|
||||
// of them.
|
||||
// fields that cannot be falsy stay hostile-truthy. That makes it a MIX, and a
|
||||
// deliberate one — the interaction between a falsy flag and a still-hostile
|
||||
// theme is a shape a stored record really produces.
|
||||
//
|
||||
// The verdict is the combined boot, always. When it goes red the same view is
|
||||
// re-booted one field at a time, so the failure NAMES a culprit instead of
|
||||
// leaving a reader to bisect twelve fields — but that loop only decorates the
|
||||
// message. It cannot clear the failure. A dereference that needs two corrupted
|
||||
// fields at once is reproduced by neither field alone, and a version of this
|
||||
// file that asserted on the named list reported exactly that case green while
|
||||
// watching the popup die.
|
||||
const UNROUTED = CONTRACT.filter((row) => swept(row) && !routes(row));
|
||||
const HOSTILE_SLOTS = Math.max(
|
||||
...UNROUTED.map((row) => sweptValues(row).length),
|
||||
@@ -774,12 +803,14 @@ describe("every field the router does not read, corrupted at once, onto", () =>
|
||||
restoringOnto(view, fields),
|
||||
view,
|
||||
);
|
||||
if (together.errors.length === 0 && together.restored) {
|
||||
expect(together).toEqual(RESTORED);
|
||||
return;
|
||||
}
|
||||
|
||||
// The per-field re-boot only DECORATES the message. The
|
||||
// verdict is `together`, unconditionally: a dereference that
|
||||
// needs two corrupted fields at once is reproduced by NEITHER
|
||||
// field alone, so an assertion on the named list would report
|
||||
// an observed dead popup as green.
|
||||
const named = [];
|
||||
if (together.errors.length > 0 || !together.restored) {
|
||||
for (const row of UNROUTED) {
|
||||
const one = await restoredHealth(
|
||||
restoringOnto(view, {
|
||||
@@ -789,14 +820,25 @@ describe("every field the router does not read, corrupted at once, onto", () =>
|
||||
);
|
||||
if (one.errors.length === 0 && one.restored) continue;
|
||||
named.push(
|
||||
`${row.field}=${JSON.stringify(fields[row.field])}: ` +
|
||||
`${row.field}=${JSON.stringify(
|
||||
fields[row.field],
|
||||
)}: ` +
|
||||
(one.errors.join("; ") || `fell off ${view}`),
|
||||
);
|
||||
}
|
||||
expect({ view: view, fields: named }).toEqual({
|
||||
if (named.length === 0) {
|
||||
named.push(
|
||||
"no single field reproduces it; it takes two or " +
|
||||
`more of ${JSON.stringify(fields)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
expect({
|
||||
view: view,
|
||||
fields: [],
|
||||
});
|
||||
together: together,
|
||||
fields: named,
|
||||
}).toEqual({ view: view, together: RESTORED, fields: [] });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user