Repository navigation
fix(packets): give each observation its own wire bytes in the detail API (port of upstream #2055) - #77
Conversation
Port of upstream Kpa-clawbot/CoreScope PR Kpa-clawbot#2055 (upstream issue Kpa-clawbot#1999). The store drops observations.raw_hex (Kpa-clawbot#881) on the belief that one content hash means one frame. Observations of one transmission carry different path bytes, so /api/packets/{hash} served the canonical frame for every observation and the hex view could contradict the path shown beside it. - db.go: ObservationRawHexForHash reads the stored frame per observation id in one indexed query, guarded by hasObsRawHex(). - routes.go: handlePacketDetail backfills after the store lock is released; a stored frame wins, the canonical frame is the fallback (also filling the DB-fallback path, which had no raw_hex at all). Fork adaptations: hasObsRawHex() is a self-healing schema flag here, not a bool field; the hash lookup uses a plain QueryRow (no stmtTxByHash); the contradictory "bytes already present win" comment from upstream is dropped. Tests: obs_raw_hex_test.go (upstream, adapted to the flag API). The two handler regressions fail without the routes.go change and pass with it; full cmd/server suite passes with -race. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Review feedback addressed (commit
|
…text leaks (#77 review) The review of #77 found the error branches after the transmission lookup in ObservationRawHexForHash untested: swallowing a failed observation query, scan or rows.Err left every test green. Cover all three through real SQLite schema changes made after the store loaded, with no test seam in production code: - query: observations.raw_hex dropped under a stale schema flag; - scan: observations replaced by a view whose id is not an integer; - iterate: a view whose raw_hex fails at runtime on frames after the first row, which the driver steps inside Query, so it surfaces from rows.Next. Each case asserts the wrapped error at DB level and a 500 from the packet detail handler. Both 500 tests now require exactly the generic body and reject DB error text, SQL/sqlite, table/column names and paths. Correct the index comment on ObservationRawHexForHash: both lookups are indexed, but EXPLAIN QUERY PLAN on the migrated e2e fixture shows the planner using sqlite_autoindex_transmissions_1 and idx_observations_tx_ts rather than the two indexes the comment named. Comment-only change in db.go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review feedback addressed (commit
Mutation check in a scratch copy, run against the focused tests: all 11 mutations fail the suite. These are the previous a–d and h, swallowing the query, scan or iterate error, and returning the DB error text in the body with or without the generic prefix. Local verification: the focused packet-detail/raw_hex suite passed 3× with Not covered: nothing from the review remains untested. |
Port of upstream
Kpa-clawbot/CoreScope#2055, which fixes upstream issue#1999.Problem
/api/packets/{hash}returns the transmission's canonicalraw_hexfor every observation. Observations of one transmission reach observers along different paths and carry different path bytes, so the packet detail hex view can contradict thepath_jsonshown beside it (for example, three hops in the path but two path bytes in the frame). Upstream measured this on a production DB: of the recent transmissions with more than one observation, 93% hold genuinely different frames.The fork has the same defect:
raw_hexper observation (cmd/ingestor/db.go, upsert withCOALESCE);public/packets.jsalready overlays the selected observation ({...pkt, ...currentObs});Fix
cmd/server/db.go: newObservationRawHexForHash. It returns the stored frame per observation id in one indexed query:transmissions.hash, thenobservations.transmission_id. It is guarded byhasObsRawHex().cmd/server/routes.go:handlePacketDetailbackfills once per request, after the store lock is released.enrichObsWithTxhas already put the canonical frame into every map.raw_hexon observations at all.Differences from upstream
hasObsRawHex()is a self-healing schema flag in this fork (a method), not a bool field. Code and tests are adapted:hasObsRawHexFlag.forceTrue().stmtTxByHash, so the hash lookup uses a plainQueryRow, like the existingDB.GetObservationsForHash.Tests
cmd/server/obs_raw_hex_test.gocomes from upstream, adapted to the flag API. It covers:Results:
routes.gochange: both handler regressions fail.cmd/serversuite passes with-race(165s).go vetis clean,gofmtis clean on the touched files, andgit diff --checkis clean.Not live-verified: the committed e2e fixture has no
observations.raw_hexcolumn, so the behaviour is verified at handler level only, not in a browser against real per-observation frames. Staging or real data would be the place to see it in the hex view.Not in scope, same as upstream
SELECT o.raw_hexand discard it.fetchResolvedPathForObsstill runs one query per observation.Not a hot path: one indexed query per packet-detail request.
🤖 Generated with Claude Code