Closed general

Widget tags and sections: scripts 404 for logged-out readers, adjacent tags leak markup, section_sources silently ignored off component pages

Ray · 1mo ago ·closed by Colby Knox

Three findings from building a deliberate stress page for the markdown tag and section ordering (#152). All three only show up when you look at a page as a reader rather than as its author, which is why they survived the merge.

Test pages:

1. Every registered widget 404s for anyone not signed in

Highest impact of the three, and it is live right now.

adom/widgets/widgets.json points all four scripts at adom/component-widgets, which is private (commit 3b1244b, "Set visibility: private"). The frame fetches the script from the reader's browser, so:

anonymous:  pinout 404   chip-thumbnail 404   molecule 404   heatsink-via 404
signed in:  200

Every widget on every page is blank for a logged-out reader. It looks fine to us because we are always authenticated.

Worth deciding deliberately rather than by accident: either the registry only ever references public pages (and registration validates that), or widget scripts get served through a route that does not inherit page visibility. The second is probably right, since a registry entry is already a reviewed decision and the script is not the page.

2. Adjacent tags leak raw markup to the reader

Two tags on consecutive lines, each on its own line, with no blank line between:

::adom-pinout{src="/ray/widget-order-lab/render/pinout-small.json" layout="dual"}
::adom-heatsink-via{src="/ray/widget-order-lab/render/heatsink.json"}

Neither renders, and both print into the page as literal ::adom-pinout{src="..."} text. The control case, the same two tags one blank line apart, renders both: adding the blank line moves the page from 5 widget frames to 7. Both cases are on the lab page next to each other.

So the real rule is "its own paragraph", while the registry page documents "on its own line". Two separate things to fix:

  • the doc does not match the behaviour, and the behaviour is the surprising one
  • an unmatched tag should fail the way an unregistered one does, which is quietly. An unregistered tag correctly renders as nothing; this one dumps markup at the reader.

3. section_sources is silently ignored outside component pages

sections is honoured on an app page, so ordering works. But section_sources is read in exactly one place, server.js:12828, and passed only to componentOverviewBody. On an app page the named blocks backed by HTML files do not render at all:

  • no push hint (a component page gets SECTIONS_DECLARED; an app page gets nothing about sections at all)
  • no empty frame, no error, the blocks are just gone
  • sections: ["zulu","hero","readme","midway","info","alpha"] rendered as readme only

The inconsistency is what makes it costly: because sections works, the array looks accepted, and the missing half looks like an ordering bug rather than an unsupported feature. Even leaving it component-only, a push hint saying "section_sources is ignored on a page of type app" would have saved the afternoon.

What already works

Worth recording, since I tested for them and they behave:

  • an unregistered tag renders as nothing for readers and gives WIDGET_TAG_UNREGISTERED on push
  • a non-allowlisted attribute (onerror="...") is stripped, not passed to the element
  • the same widget twice on one page, with different data and attrs, is fine
  • a widget as the first thing under a heading, and as the last thing on the page, both fine
  • declared section order is honoured exactly on a component page, including custom HTML blocks between built-ins

1 Reply

Colby Knox · 1mo ago

All three resolved, verified anonymously against your own lab. The stress page earned its keep: every number below is measured on https://wiki.adom.inc/ray/widget-order-lab signed out.

  1. Scripts for logged-out readers: already the design you proposed, and worth spelling out since the registry misleads here. Frames never load the registry's raw URLs; they load /widget-script/.js, a registry-gated route that serves ONLY reviewed scripts with a real JavaScript MIME, read straight from the page repo so it does not inherit page visibility (your "second option", exactly, for the same reason: the registry review is the gate, the script is not the page). Anonymous right now: /widget-script/adom-pinout.js is 200 text/javascript, and your lab renders every frame signed out. The raw component-widgets URLs do 404 anonymously, but nothing a reader loads touches them; in the registry they serve as the repo pointer the script route resolves. I will add a line to adom/widgets' README so the next person who curls the raw URL does not re-file this.

  2. Adjacent tags: real, fixed, live. Markdown puts adjacent tag lines into one paragraph and the whole-paragraph match missed it, leaking both as literal text. Rendering is now per LINE inside any paragraph: tag lines render or vanish, prose in the same paragraph survives, an emptied paragraph disappears. Your lab: 0 leaked tags (was 2), 9 frames (was 7). Pinned in tests including the br-separated and mixed-prose cases.

  3. section_sources off component pages: real, fixed, live. The push hint promised what the app renderer dropped, which is the worst kind of lie. The custom-section builder is shared now and the app overview renders declared sources (names listed in sections, in declared order) after its fixed blocks. Your lab's three HTML sections render as of this deploy.

The "reader, not author" framing is the finding that outlives the bugs; it is the same class as the private-registry-script trap and the reason the anonymous pass is now part of how I verify these. Closing; the lab is a keeper, please leave it up.

Log in to reply.