Changes touching this path

  • the browser opens what the forge cannot: own-private read ships an owner read tier, a once-per-device unlock, and a grant mailbox that never acks (#1043) c8dd4da1 · dbf3dbe6…
  • the collaborator can read someone else's namespace: migration 0015 adds the fourth role forge_member and eleven forge_member views, one per relation 0009 serves, so the shared prefix-parameterised TreeReader reads either family unchanged - and the gate is strictly stronger than 0009's, because the app names only the account the Clerk session resolved to while the membership join sits INSIDE the barrier view, so the application cannot name a repo it is not a member of even by mistake. metadata_public is absent as both column and predicate, and repo_member is named exactly once, by the gate. Two premises did not survive, and the first is a defect in the decision itself: ADR 0077's and the ticket's literal current_setting of loot.reader_tenant cast to bigint DOES NOT fail closed. It fails closed for an UNSET parameter and not for a CLEARED one, because set_config with NULL leaves the empty string behind and casting that to bigint RAISES - which 0009 never met because decoding an empty string as hex does not. Proved by removing the fold from the shipped migration and reading invalid input syntax for type bigint, so the gate ships as nullif and then the cast, malformed values still raise deliberately, and withMember validates a positive decimal with the pin on both sides. The second is a defect in #1727, which landed earlier tonight: its exact-set spelling, that the views naming repo_member equal the forge_member family, is satisfiable ONLY by a family of one, because the ten chained views name the GATE view and never the base table - so a second member view gaining the roster, which is precisely the disclosure ADR 0077 forbids, read as CORRECTNESS under the old spelling. It is re-spelled to exactly forge_member_repo whenever the family exists, its vacuity guard extended to require the member family non-empty, and its positive control now plants four breaks where it planted two. The row-level-security interaction is proved rather than assumed, as three readings on one database in one moment: the seven enabled tables this family reads really carry relrowsecurity, read as a set; the role handed a direct SELECT on repo reads ZERO rows, which is 0014's own named accident and shows the policy system live for that role; and the same role on the same connection at the same moment reads its repo through the gate view and gets one. The mechanism is then named from the catalogue and red-proved by setting security_invoker, which takes the read to insufficient_privilege, and the failure text names the non-superuser deployment case so a future deploy diagnoses itself. The isolation break is ADR 0077's own named careless shape rather than an invented one - the gate keeps its repo_member join and loses only the correlation to repo, which passes every text guard in migrate.rs - and seven of eight tests fire on it. Rows are planted from tests and from the site, outside account_tier.rs's scan of src, the way rls.rs already recorded, so the tripwire is untouched and green. forge_member ships NOLOGIN and provisioning is a different repo, so the class answers 404 rather than 500 and is not an existence oracle (#1726) e76ca863 · dbf3dbe6…diff
  • an api route answers an undeclared method with the same 404 an unserved path gets, and the all-platforms table goes through the counted hop with the direct link beside it loot#1925 and the last site item of loot#1647, in one change because both are about what a URL on this site tells a stranger. The router looks up handlers[method], then handlers.ANY, and on neither falls through to SSR - so GET /api/beacon answered 200 with 5 KB of HTML while /api/definitely-not-a-route answered 404, measured live the day the beacon deployed. The difference told a prober which routes exist, which is the oracle the download hop refuses to be. One ANY_NOT_FOUND spread into every api.* route answers the bare 404 an unserved path gets. NOT a 405: an Allow header is the polite answer and exactly the one that confirms the route and lists its methods. A declared method still wins, and that is pinned as a fact about the router read from its source rather than assumed. A test walks every api.* file, so a new endpoint cannot arrive without the fallback. The table links and the sentence about them moved TOGETHER, which loot#1647 insisted on: switching the links alone produces a page that counts a click it calls anonymous. Each row now links through loot.millerbyte.com/dl with the direct R2 URL visible beside it, hopHref is null for anything the hop would refuse so a row can never render a counted link that 404s, and the manual- install note says the hop counts the release, the platform and the time and sends you on to the CDN that serves anonymously. The checksum instructions still fetch sha256.sum direct, because the hop refuses it on purpose - every land fetches that file and admitting it would count every land as a download. Rendered: all five rows carry both links, the note reads as one sentence. 610 site tests, budget green. 7c4f1a17 · 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.