Commit 458dc8c
fix(portal): wave-4 review — five medium fixes (store parity, monotonic head, schema-degradation bounds, bounded realtime probe) (#44)
* fix(portal): wave-4 review — five medium fixes (log re-match parity, monotonic head, per-field schema bound, stream block-field degradation, bounded realtime probe)
Five fixes from a four-lens validation review of the portal layer, each
mutation-verified (reverting the fix hunk fails the named regression test):
1. assembleRange re-matches logs per-filter (isLogFilterMatched +
isAddressMatched) — factory pre-creation logs and a bounded filter's
out-of-range logs no longer diverge the sync store from the RPC path
(INV-6/INV-2); a dropped log's parent tx/block no longer rides in.
2. The cached Portal head is monotonic (LB replicas answer stale-LOW), and
stream mode's known-head-below-interval branch is FATAL instead of
returning [] — closing the reopened G4/C11 silent-gap class (INV-9).
3. stream()'s schema-degradation bound keys on the table-qualified fieldKey,
not the bare column name — a dataset missing the same column in two
tables (logs_bloom in blocks AND transactions) no longer crash-loops.
4. /stream 400 degradation covers droppable block.* fields, not just
transaction.* — completing review B3 (a mix_hash-less dataset no longer
refuses stream mode after backfilling fine).
5. portalFinalizedHead delegates to the shared bounded probe
(probeFinalizedHead, issue #14/PR #16 hardening) — a hung
/finalized-head can no longer freeze finalize emission or startup;
deletes the duplicated weak probe.
Suite green on 0.16.6 and 0.15.17 grafts (197 tests, 7 new).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(portal): wave-4 review round 2 — matched-log needed-field gate + #47 INVARIANTS candor
Addresses the CHANGES_REQUESTED on #44 (two narrow deltas).
2 (medium) — the needed-field fatal counted raw `cd.logs.size`, but the new log
re-match (INV-6 store parity) can drop every log a chunk added (a factory child's
pre-creation logs / a bounded filter's out-of-range logs). A tail of all-dropped
logs over a dataset missing a needed field armed a false `neededMissing` fatal →
G1 evict → crash-loop, for data the indexer never keeps — the exact class of #20's
trace/transfer residual, created here by the new re-match boundary. `runStreams`
now counts only logs surviving `logMatched` toward the growth check (trace/tx/block
sources keep the raw map-size delta; the #20 trace/transfer residual is unchanged).
New `buildRawLogMatcher` reuses `buildMatchers` + `toSyncLog`, so the seam count and
`assembleRange` agree by construction over the same discovery-complete childAddresses.
Mutation-verified: reverting the seam to the raw `cd.logs.size` delta fails exactly
the new `portal.test.ts` regression.
1 (INVARIANTS candor) — reworded the INV-9 row + the wave-4 monotonic bullet: the
`max`-keep guarantees only that the cached head never exceeds the true finalized head;
range completeness against the *serving* replica is not verified (a phantom-coverage
hole pre-existing on main per PR #15 FIX 1, widened to process-lifetime by max-keeping).
Both now reference #47; the client-side range-completeness guard is deferred there
pending one empirical check of Portal 204 semantics. INV-13 residual note updated
(logs now matched-precise; trace/transfer the remaining #20 slice).
Gates: 0.16.6 + 0.15.17 `--test` green (198 each, +1 test); biome clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 37892f8 commit 458dc8c
12 files changed
Lines changed: 737 additions & 169 deletions
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
167 | 167 | | |
168 | 168 | | |
169 | 169 | | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
170 | 253 | | |
171 | 254 | | |
172 | 255 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
| |||
105 | 106 | | |
106 | 107 | | |
107 | 108 | | |
| 109 | + | |
108 | 110 | | |
109 | 111 | | |
110 | 112 | | |
| |||
125 | 127 | | |
126 | 128 | | |
127 | 129 | | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
128 | 143 | | |
129 | 144 | | |
130 | 145 | | |
| |||
165 | 180 | | |
166 | 181 | | |
167 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
168 | 201 | | |
169 | 202 | | |
170 | 203 | | |
| |||
260 | 293 | | |
261 | 294 | | |
262 | 295 | | |
| 296 | + | |
| 297 | + | |
263 | 298 | | |
264 | 299 | | |
265 | 300 | | |
266 | | - | |
267 | | - | |
268 | | - | |
269 | | - | |
270 | | - | |
271 | | - | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
276 | 314 | | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
277 | 324 | | |
278 | 325 | | |
279 | 326 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
212 | 212 | | |
213 | 213 | | |
214 | 214 | | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
215 | 255 | | |
216 | 256 | | |
217 | 257 | | |
| |||
0 commit comments