Changes touching this path

  • the metrics dashboard ships as SIX STATIC PANELS behind an operator allowlist, and the two reviews moved it from a client-fetched page with a 401 to a server-rendered one that cannot be probed: 1623 settled Variant A, the Briefing - one column, one section per question, each caveat as PROSE beside the number it qualifies, which is the structural reason it won, since a caveat there cannot be skipped without skipping its number. the access decision is that being signed in is not the same as being the operator. anyone can sign up to this host and the data is site-WIDE - every visitor path, referrer host and install-funnel count - so the door is a custody list in the 1045 shape: a Clerk id is on it or it is not. it fails CLOSED in every branch, and the proof is that the fail-OPEN spelling was written and run: allowed.length greater than zero AND not includes, then return true, reads as careful and admits the entire internet the moment the list is empty, which is the state a box is in before its first deploy writes one. exactly two tests went red on it. the security review then found the route around that allowlist was the wrong shape twice over. the check sat INSIDE withPrivateSession, which maps an unauthenticated caller to 401 - so a stranger probing the endpoint got a 401 where an unserved path gets 404, and the refusal meant to hide the route confirmed it, while a load-bearing comment three lines up asserted the opposite. and the page itself answered 200 to anyone, rendering a document and only saying not found after a client fetch failed. both collapse into one server function returning null for BOTH refusals, which the loader turns into a real notFound: signed-out, signed-in-not-an-operator and a path we do not serve are now one answer. that rework is also what the ticket asked for and I had not done - the panels render into the HTML from a route loader rather than from a browser round trip, so the acceptance criterion about server-side rendering stops being approximated. the second finding is sharper than it looks: the route declared no headers, and every private route sets private no-store BECAUSE an nginx proxy_cache sits in front. an operator document without it is cacheable at the edge, which is the edge handing one caller a page meant for another. it now carries PRIVATE_HEADERS, and that constant own comment is widened to say it covers two tiers rather than left reading as private-only. one real data bug came out of the same review and no test I had written could see it: ordering a to_char MM-DD label sorts the series as TEXT, so any window crossing new year draws january before december - the sparkline scrambled about thirty days a year on the one chart whose job is a shape over time. grouped and ordered on the timestamp now, formatted on the way out, and pinned by asserting the grouped expression is not a to_char, verified by restoring the bug and watching it go red. built against the PRODUCERS rather than the schema, which is what the prototype was really for: visitor_key is null on every log-sourced row and permanently will be since 1632 took the address out of the log, so there are no uniques and no sessions here at all, and device, browser, os and country have no producer either. the panels that wait on one are rendered, named and marked rather than omitted - uniques on 1757, forge usage on 1758, downloads on 1647 and telemetry on 1658 - because a dashboard that silently drops what it cannot see is how you talk yourself into a wrong conclusion. not prerendered, and that is a security property rather than a build detail: a prerendered page is served as a static FILE with the static route headers, so an operator surface would exist as bytes anyone can fetch with the door never consulted - the same reason private joined that filter in 1043. asserted, and the mutation confirms the assertion bites. it is correspondingly absent from the byte budget, which discovers prerendered surfaces, and its styles stay in the route rather than styles.css because that sheet is eager on all sixty budgeted surfaces and an operator page has no business charging them (#1794) 2c969a0e · dbf3dbe6…
  • the dashboard reads the three sources that landed after it, each from where its facts actually live, and no raw identifier is ever selected into a result loot#1940, closing the one gap left on map #1615: /metrics was built against the log, and the beacon, the private tier and the CLI each wrote rows nothing read. People come from the ROLLUP, not from keys. rollup_day is the table built to survive, sessions are already derived there (same key, 30-minute gap, never an id), and its class is the one row rather than the NOT IN spelling because the rollup keeps bot and internal as their own rows. The series ends at the watermark and the panel says so rather than drawing a zero for a day still being counted. Docs by section comes from rollup_section_uniques - per section, never per page, labelled visitor-days because a returning reader counts once per day. Forge usage is the private tier by route shape, which is all its rows hold. The CLI panel counts reports, distinct ids and ids seen on two or more days inside the window, and states the bound ADR 0074 §11 sets: answerable for 30 days and never longer, because the rollup carries no id. Every one of those is an Awaiting state until its source has produced, and a CLI panel that has never received a report reads not measured rather than zero installs - the null-not-zero rule the download panel already keeps. A rule boundary inside the window is named across every headline (loot#1625). The read test list of columns nothing writes SHRANK from seven to one, because six gained a producer; the four that are written but unread stay refused for a different stated reason. The pin that matters is new: telemetry_id may appear COUNTED or GROUPED and never returned - every allowed form is stripped and nothing named telemetry_id may survive, with a control proving the strip removed something. The mutation that returns min(telemetry_id) as a column reddens exactly that pin. The header of read.ts stopped claiming the beacon is unbuilt and visitor_key is null forever, which had been false for a day. WINDOW_DAYS reaches the route from lib/, never as a value from the pg-backed reader (loot#1804). 639 site tests, budget and font gates green, the dashboard chunk 9 to 12 KB with no react-table in it. 6e8987f0 · dbf3dbe6…diff
  • the dashboard review fixes for 1940: every CLI query is under the default view, because the collector writes our own machines reports as internal and a dogfood run read as an opted-in install that keeps running, and returning now counts distinct UTC days like the rollup does; the docs-by-section panel reads only docs sections, since SECTION_SQL buckets every path and the panel titled docs was a site-wide top-8 with the root at its head; the rule-boundary marker is the union of the raw windows rule_version and the rollups own rule_versions array, which migration 0003 put on every rollup table for this read, so the two rollup-fed series carry their boundary too; the stale Forge product usage placeholder that #1949 left below the built panel is deleted and its one true sentence about edge-scrubbed forge paths moves into the built panels caveat. each of the three query fixes is pinned in metrics-read.test.ts and each pin went red under the defect it names. the hand-maintained counts (six panels, the three sources, seven columns and six of them, two stages have no producer) become the property they counted, the last hard-coded 30 days read WINDOW_DAYS, one exported dateOnly in rollup.ts replaces two byte-identical copies, one sinceDay spelling replaces the retyped rollup window and the test counts it, the Awaiting prop is why because it carries reasons rather than ticket numbers, and the dead alias in SparkVals is gone. tsc, the reader and rollup tests, the full suite, the build and the budget are green (#1940) 947fe6f3 · dbf3dbe6…diff
  • the metrics dashboard loads again: the installs-seen-again subquery was aliased returning, a reserved word in Postgres, so the statement never parsed, and because dashboard runs its queries under one Promise.all that one refusal took the whole page down for the operator with every gate green since 1940. the alias is seen_again. what let it through is that metrics-read.test.ts reads the SQL as text and nothing parsed it, so a new metrics-read.pg.test.ts, on the suites existing skip-unless-configured pg convention, runs the real reader as the real metrics_read role over site/migrations on a throwaway cluster: it went red with the production error word for word before the fix and is green after, along with both drill-down kinds and a seeded case that measures what the text pins could only describe, namely that an internal-class report is neither an install nor a return, that only docs sections reach the docs panel, that the rule versions are the union of the raw window and the rollup, and that the read role holds SELECT on every table the page reads. the text tests header now says what it cannot see and to run the pg test before landing SQL. tsc and the full site suite are green (#2010) 60af97d8 · dbf3dbe6…diff
  • the metrics dashboard reader test runs in CI instead of passing by running nothing: test-main.yml already ran every site pg test under LOOT_FORGE_TEST_REQUIRE_DATABASE, and metrics-read.pg.test.ts skipped there with a bare console.warn, so the guard 2010 added fired only by hand. the file now calls skippingLive like its siblings, and it went from exit 0 with all tests skipped to a failure under the flag with no keys. the workflow provisions loot_metrics the way the scripts repos metrics-db.js does, bare LOGIN roles, the database and CONNECT only, so every table, sequence and function grant comes from the migrations as in production; it then applies site/migrations in C-locale order from this commit, and sets the two metrics keys. the step was pulled out of the parsed YAML and run verbatim against a throwaway password-auth PostgreSQL 17, twice to show it is idempotent, and the test then passed 3 of 3 with the exact CI URLs under the flag and failed on syntax error at or near returning when that alias was put back. no CI run proves it yet: GitHub refused to start any Actions job over account billing. the text tests header says the land gate runs it only when the landers environment carries the keys (#2041) 7b84226b · dbf3dbe6…diff
  • a count of people is rounded before the dashboard draws it, because the exemption that keeps this site banner-free has an output condition nothing implemented: 1617s research recorded that the reports an operator reads must hold anonymous statistics only, holding under whatever combination of filters the operator selects, with present to the nearest ten as the recommended measure. that only began to bite when 1940 put people on the page, since before it every panel counted requests. presentPeople is the one place it is applied: a true zero stays zero, 1 to 9 carries no number at all and the page draws under ten rather than a zero over real activity, and anything larger goes to the nearest ten. it is a union rather than a number beside a flag, so an under-ten count has no n to read and a caller that wants a bar height has to ask for a magnitude and cannot print a floor as if it were a measurement; the boundary test proves 1 and 9 are indistinguishable and that no 4 survives into the value, and a floor that carried its count reddens exactly that pin. window totals are summed exactly and rounded once, which a mutation summing the rounded days reddens. what rounds is decided by the unit rather than by a list of panels: a field typed People rounds and a plain number does not, so a panel added later inherits the rule from its type. the rule lives in lib/metrics-drill.ts, not in read.ts, because a value import from the reader puts pg into every client bundle, which is 1804s defect and I had just written it. ADR 0087 records the decision, that under ten deviates from the recommended measure by disclosing that somebody was there, and why that beat a false zero on the operators own page (#1951) 71be502c · dbf3dbe6…diff

Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.