Skip to content

Release: develop -> main - #40

Merged
TaprootFreak merged 1 commit into
mainfrom
develop
Sep 10, 2026
Merged

Release: develop -> main#40
TaprootFreak merged 1 commit into
mainfrom
develop

Conversation

@github-actions

Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 1 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

* fix(invite): one list for a file-looking segment, one rule per path, two tests that prove something

Four follow-ups the reviews of #34 and #37 left open.

The gate that decides whether this pass owns a path and the parser that reads
the code out of it both asked whether a suffix names a file, with two different
sets: the gate carried jpg|jpeg|webp|ico|txt|xml that the parser lacked, the
parser carried html that the gate lacked. So /invite/AB.HTML passed the gate
and then lost its code, while /invite/AB.JSON never reached the gate at all.
Both read one constant now, and a case asks the two as a single question across
every suffix — the sweep includes html, a suffix that names no file type, and a
mixed-case spelling — so a set that grows on one side and not the other fails
there rather than in production.

The two still ask it of different things, deliberately: the gate of the whole
path, because /invite/AB12CD/logo.png is an asset request whoever owns the
first segment, and the parser of the code segment alone. A case pins that
difference as well as the agreement.

html is not in the list for one reason: a code that happens to end in .HTML
stays a code. The shell needs no help from the list — the parser names
index.html outright — and the 308 that canonicalises it comes from the platform
and is handed on either way.

public/_headers had a rule for /invite/ and another for /invite/*, and the
first matches the second. Every answer that matched both carried the value
twice: measured on the deploy, /invite/ answered

  cache-control: public, max-age=60, public, max-age=60

Pages concatenates what every matching rule says rather than letting one win,
and a parser takes the first. The rules the wildcards already cover are gone,
the bare paths keep theirs, and /invite/invite.js keeps its own rule above the
wildcard — the restatement below it, added when the match order was thought to
be uncertain, only appended a third value nobody reads. check-site.mjs now
requires the wildcard, rejects a rule the wildcard covers, and rejects the same
exact path declared twice, which its own header parser had been merging out of
sight.

Two tests could not tell a working build from a broken one. The clipboard stub
resolved and discarded what it was handed, so the case named after copying the
canonical invite URL passed on any string, or on none; it records now, and the
case requires exactly one write, equal to the href the canonical link names.
And the fifteen-second lookup budget was asserted against its own constant and
nowhere else: a request that never answers now has to leave the loading state
by itself, and the case measures how long that took against the budget the page
itself reports.

* test(invite): say which of the two claims does which job

The comment said the budget is read from the page rather than restated here,
and the line under it restates it. Both belong there — the size is pinned
outright, because bounds computed from the page's own number would follow it
anywhere, and the elapsed time is measured against that number so another timer
cannot pass for this one. The comment now says that instead of denying half of
it.

* test(invite): three comments that claimed a little more than the code

The sweep's comment implied it catches any divergence between the two sides,
where it walks a list of its own and catches a divergence on what it
enumerates. The .PDF case called it a dot that names no file type, where PDF is
a file type this rule simply does not call an asset. And the timeout case said
the budget was asserted against itself, where the unit suite pinned it against
a literal and went no further.

* fix(invite): catch any covered rule, and start the clock where the wait does

The covered-path check listed the four rules that happened to be there, so a
rule added later would have slipped past it. It now rejects any exact path a
landing wildcard covers, with the script's own rule kept on purpose: it wants a
longer cache than the shells, and a parser takes the first of the two values.
Proven by adding a rule for /invite/foo and watching it fail.

The budget case took its timestamp before the navigation, so a slow page load
counted against the budget and could push the upper bound over on a busy
machine. It starts when the page says it is checking, which is when the timer
the case is about was armed.

---------

Co-authored-by: TaprootFreakAI <315477232+TaprootFreakAI@users.noreply.github.com>
@TaprootFreak
TaprootFreak merged commit 8e436bd into main Sep 10, 2026
6 checks passed
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