Changes touching this path
- private api answers carry a Server-Timing header from withPrivateSession, recorded by the new site/src/server/timing.ts: each timed step names itself where it is written, the session verify as verify.pem or verify.jwks and each pool wait and statement as identity, owner, member or membership .wait and .query, each name with its summed duration and run count, then total. a private request looks its account up once through the new sessionAccount, where /repo had looked it up 2 or 3 times and /repos once plus once per key. clerk.ts verifies over CLERK_JWT_KEY, the instance public key, when it is set: without it @clerk/backend refetches the JWKS whenever its copy is 5 minutes old, 12 fetches over a simulated hour at one request every 30 s against at most one per key id with the key, so the clerk.ts header claim of a networkless verify was false and is corrected, as is docs/specs/loot-forge.md. a key id goes to the static key only after a token under it verified over the JWKS, since Clerk files the static key under any key id a token names, in an unbounded cache, before the signature check; a signature the static key refuses goes to the JWKS, refetched at most once a minute, and a key id the JWKS then verifies stays with the JWKS and warns once, so a changed instance key keeps verifying under a new or the same key id, and a refusal on a claim never falls back. measured on a local Postgres through the live suites, the database side of an owned or a member repo read took 1.7 ms with one identity query, and the verify costs about 150 us in process over either key. pinned in private-timing (9 tests), clerk-verify (8) and one test each in owner.pg and member.pg. red under named mutations, each restored: the account looked up per ask (5 failed and 4 passed of 9, and 1 failed and 89 passed over the live suites), the header dropped (3 and 6), the static key for an unlearned key id (5 and 3 of 8), fallback on any refusal (1 and 7), no fallback (5 and 3), no demotion to the JWKS (2 and 6), no forced refetch (2 and 6), refetch unbounded (1 and 7), CLERK_JWT_KEY ignored (6 and 2), escaped line breaks kept (4 and 4). cargo test green, 4831 passed over 144 test result lines with 15 ignored, the site gate green at 909 passed, and the site live suites 90 passed through ci/local.sh. CONTEXT.md gains Private request timing. owes a site deploy, which should set CLERK_JWT_KEY in the site env half (uyzzknlm)
3cfbe0dd · dbf3dbe6… - each statement of a private route is named in its Server-Timing: a pool query takes the name of its statement beside its SQL and records it under the pool prefix, owner.tickets.graph for one, where every statement of a pool summed under one name such as owner.query; the transaction statements are begin, bind, commit and rollback, the identity transaction is timed too, the anonymous read pool takes the names as well, json times writing the answer as answer, and the Tickets fold is tickets.first. the Tickets read reads what it answers by key: the head ticket files from tickets/ on in the tree key, in byte order and without the published flag it never answered, the history as the parent edges walked from the head, and the touches from tickets/ on in the repo touches, each id as hex from Postgres, where it read the whole head tree, every change and parent edge of the repo through views that read every change on the forge, and every touch of the repo, and turned each id into hex in the site. the answer is the same but for the order of its files. measured on a throwaway Postgres 18 shaped like this tracker, 5,463 ticket files at a head 1,400 changes deep with 3.8M ticket entries in the history trees, the read and its JSON took 78 ms before and 33 ms after, medians of 15 in two rounds, and with a second repo of 200,000 changes 151 and 152 ms before and 32 ms after; the two answers compared equal, files as a set. pinned in the new owner.pg tests that count a generation across a merge and past a parent the repo does not hold and that read the Tickets view files, history and touches through keys, in the pool timing tests now expecting each statement by name, and in private-timing, which names the writing of its answer. red under named mutations, each restored, over the 5 selected live tests: roots taken without asking the change view (1 failed and 4 passed), the walk step without OFFSET 0 (1 and 4), the step as a plain join (1 and 4), the touches without their bound (1 and 4), the files without their bound (1 and 4), the owner pool under one name (1 and 4); and the answer untimed (2 failed and 8 passed of the 10 private-timing tests). not taken: grouping the touches by change in the answer, since writing the whole answer took about 2 ms. the site gate green at 914 passed and the site live suites 92 passed; no Rust changed. CONTEXT.md says so. owes a site deploy; it also carries comments on uyzzknlm, zsxqmrtm, woyvmtwq and kwlxstko (ylrvoopz)
2a747a82 · dbf3dbe6…diff - the site server records every request as one wide event and prints it as one JSON line (ADR 0101): lib/wide-event.ts holds the rules the browser will share, the declared field catalogue and its reductions, the error capture that scrubs a message and drops it on /private and /api/private, and the tail sampler that keeps every error, every request of 2 s or more and every signed-in surface and 5 percent of the rest at a recorded sample_rate; server/wide-event.ts is the per-request recorder, which also prints exact per-minute counts. start.ts runs every request under it first, timing.ts spans land on it, withPrivateSession and withSession record their caught error on it where they printed it raw with console.error, and router.tsx reports the loader and render errors the router answers 500 without throwing, seen live as a 500 event with a null error before that seam. no identity yet. ADR 0101 section 6, the glossary and ylmnvrtp now name the browser as the forge caller, since the site server reads the forge database directly. pinned in test/wide-event.test.ts, 21 tests; red under named mutations, each restored, failed and passed of 20: the private message kept (1 and 19), a raw path kept (2 and 18), an undeclared key kept (1 and 19), an error sampled like the rest (5 and 15), the quote scrub gone (2 and 18), only kept events counted (1 and 19), a throw not recorded (1 and 19), our own traffic not marked internal (1 and 19), spans not forwarded (1 and 19), the owner seam printing raw (1 and 19), the middleware off (1 and 19), and of 21: the router seam off (1 and 20). site gate green at 1049 passed. owes a site deploy (oqqwzwkp)
bb784ff1 · 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.