Changes touching this path
- the error shipper (ADR 0101): every minute it reads the wide-event lines out of each named container Docker json-file log and writes them into loot_metrics, migration 0004: wide_event for 30 days, error_issue with no identifier, wide_counter where a minute printed twice adds, and wide_log_position, under a new errors_writer role, since the beacon writer role may never read an issue. issue.ts fingerprints by source, type and the top three in-app frames and regresses a resolved issue on an occurrence from another release after the resolve; db.ts applies events, issues, counts and the position in one transaction, so a batch read twice counts once; alert.ts posts to Discord at most once an hour per issue with the type, culprit, route, release and count and never the message; shipper-main.ts finds containers by the name in config.v2.json and fails when it finds none. bundled to .output/errors.cjs; ci/test-main.sh provisions the role. pinned in errors-ship.test.ts, 15 tests, and errors.pg.test.ts, 5 over Postgres 18; red under named mutations, each restored, failed and passed: a regression on the same release (1 and 13, and 1 and 8 on pg), the route in the fingerprint (1 and 13), vendor frames fingerprinted (1 and 13), the title in an alert (1 and 13), no hourly limit (1 and 13, and 1 and 8), a partial entry kept (1 and 13), consumed past the last line (1 and 13), a re-read counted again (1 and 8), a minute replaced not added (1 and 8), the beacon reading issues (1 and 8), and no expiry (1 and 8, after the test counted the rows left, where it first passed). an end-to-end run of the built bundle over the built server output made two issues and two Discord posts with no message. site gate green at 1063 passed. owes a site deploy with the scripts change (vuxxwrys)
9fdc1ae3 · dbf3dbe6… - a leaked secret in stored error text can be purged (ADR 0101): loot_metrics migration 0005 defines purge_error_text, callable only by the migrating superuser, which deletes every wide_event row holding the text as a literal substring in any text column, cuts a matching error issue title back to its type and keeps its fingerprint and counts, answers two counts, and refuses a text under 8 characters; the scripts repo errors:purge verb takes the text masked or from a file, never a command line. it also joins the lines Docker json-file splits past 16 KiB, which the first production tick of the error shipper dropped as partial=1 and which for a busy minute counter line loses the exact counts: parseDockerLog walks the bytes, joins consecutive entries per stream, drops a joined line only past 1 MiB, and reports safeBytes so the position never passes a line still being split. pinned in errors.pg.test.ts, 7 tests on Postgres 18, and errors-ship.test.ts, 17; red under named mutations, each restored, failed and passed: no delete, the title kept, anyone may purge, no length floor, the error text not searched (each 1 and 6), no join (1 and 16), the position past a split line (1 and 16, after the test put a whole stderr entry behind the split one, where it first survived), one pending line for both streams (2 and 15). owes a site deploy with the scripts change (ntkmpoqn)
568ee1cd · dbf3dbe6…diff - the operator reads errors at /metrics/errors (ADR 0101), the prototype A Inbox with its C Timeline as the operator chose: the error issues of one status with their counts, exact error rates, last seen and last 24 hours; the selected issue latest occurrence as cards and its kept occurrences as a timeline; the timeline of every kept event; and a page load or account journey from any row. Resolve, Ignore and Reopen are a server function behind the /metrics operator door and the CSRF middleware, the view one write: loot_metrics migration 0006 grants metrics_read UPDATE on status, resolved_in and resolved_at only, and a resolve names the release its source last ran. the door check is one function both readers share; /metrics links to the view. pinned in errors.pg.test.ts, 4 view tests over Postgres 18; red under named mutations, each restored, failed and passed: the rate without the counts, the sparkline reversed, a resolve naming no release, a reopen keeping the resolve, the whole issue writable (each 1 and 3). site suite 1071 passed (lwsvmskl)
c6963d13 · dbf3dbe6…diff - the browser reports its errors (ADR 0101): lib/error-capture.ts, eager on every page at about 944 bytes, sends an uncaught error, an unhandled rejection or a router-caught error with the page last 20 steps and a page load id held only in memory to POST /api/errors, which reduces it by the server rules and prints the wide-event line with no database credential; privateFetch carries the page load id and the private seam records it with the account reference, neither for a caller who objected and never failing the request; a browser error whose last step was a forge 5xx carrying x-loot-event is upstream and opens no issue, one with no forge event is ForgeUnreachable (ylmnvrtp); migration 0007 files page_load, account_ref and crumbs; /privacy gains the browser paragraph the operator approved, and its sentence that no identifier is kept now names the two. pinned in errors-client.test.ts, 15 tests, and errors.pg.test.ts, 8 over Postgres 18; red under 11 named mutations, each restored, each 1 failed of 15. site suite 1082 passed (pvypzlpl)
b908ba9f · dbf3dbe6…diff - adopt: catch up to landed main 1db898e8
86a7ca3c · dbf3dbe6…diff - the errors view reads a range with totals and a chart over four tabs, issues, events, routes and releases, each filtered and searched, and opens every event whole, its fields, spans, error chain, breadcrumbs and journey, and no page scrolls sideways at any width; route templates fold every public repository path to one per verb and key the per-minute counts and the issue routes, which migration 0008 folds and indexes, so a tab answers in 30 to 350 ms at the live shape where it took 14 to 26 s. pinned: the search fills nothing in, a template per verb, the event filter binds every value; red under named mutations, each restored. site gate 1093 passed, pg suites 18 passed over Postgres 18 (usyyyzkx)
Perf-Baseline: reset object_gets and graph_sorts moved with 587f93b, whose negotiation workload now builds the forge push a land makes (opywoozo); this change touches no Rust
71c23069 · dbf3dbe6…diff - the error shipper reads every container labelled build.loot.wide-events, where it read a list of names, and reads at most 8 MiB of one log a run, resuming from its position and widening a window that holds no whole line, so the forge log, never rotated, is read down over several runs; a run that finds nothing new records the check on the position, so wide_log_position says when the shipper last ran. the scripts half creates the site and forge containers with the label and a rotated log, and the forge with LOOT_FORGE_RELEASE. pinned: the bound, the widening, the check, the label filter; red under named mutations, each restored. site gate 1096 passed, errors pg suite 15 passed over Postgres 18 (mwvpnyss)
Perf-Baseline: reset object_gets and graph_sorts moved with 587f93b, whose negotiation workload now builds the forge push a land makes (opywoozo); this change touches no Rust
4cf1d1e1 · dbf3dbe6…diff - the errors view lists failures and slow requests unless a search, a journey, an outcome, a keep reason or all asks for more, says when the shipper last ran and turns red once it has stopped, sets each total beside the range before it where that fits the retention, and moves through its lists by keyboard, j and k, Enter, Esc and slash; files wvyoprtz, a forge test that failed on its sync-walk budget under load. pinned: the quiet rule and its SQL, the all flag, the previous range, the freshness; red under named mutations, each restored (xzxouptw)
Perf-Baseline: reset object_gets and graph_sorts moved with 587f93b, whose negotiation workload now builds the forge push a land makes (opywoozo); this change touches no Rust
31c8c9ef · dbf3dbe6…diff - an open error issue whose last hour holds ten or more occurrences and five times its hourly rate over the day before is alerted as spiking, at most once an hour, marked in the statement that finds it; the first shipper run from 14:00 UTC claims the day in error_digest (migration 0009) and sends the day's digest, the counts beside the day before, new and open issues and the three busiest by type and culprit, never a message. pinned over Postgres 18 and the alert text, red under named mutations, each restored (stzwopuy)
Perf-Baseline: reset object_gets and graph_sorts moved with 587f93b, whose negotiation workload now builds the forge push a land makes (opywoozo); this change touches no Rust
ef41eb8c · 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.