Task · CFO-0079.05

Bound extreme Cloudflare rate-limit pauses and cover malformed GraphQL error envelopes

Description

CFO-0079.04 (per-class Cloudflare rate limits driven by response headers) honours retry-after, Ratelimit and GraphQL budget errors with no upper bound on a valid but extreme pause, so one upstream header could stall a whole request class for hours. Its tests also cover only well-formed GraphQL error envelopes; mixed or malformed envelopes (errors alongside data, missing extensions, non-string codes) were not exercised. Raised as an open question at the loop22 closeout; owner admitted it for loop23 ahead of the attribution measurement.

Acceptance Criteria

Definition of Done

Implementation Plan

Loop23: isolated H1 implementation with authentic base-red/candidate-green fake-upstream witnesses, frozen nested max_pause config and malformed GraphQL handling; CodeRabbit and independent security review before push, local check plus repeated race gate, exact-SHA CI and composed gate. Root owns tracker; no push after H1 until fenced L1 ends.

Implementation Notes

Loop23 H1: one implementation change-and-verify attempt; initial full gate plus two infrastructure retries blocked at lint by sibling global golangci-lint mutex. New fake-upstream witnesses base-red/candidate-green, actual 1.00-1.01s REST ceiling against 3s header, unchanged GraphQL 300s; CodeRabbit complete zero findings. No full just check/repeated race, security review, commit or push. Preserved candidate in isolated worktree; evidence /tmp/cf2otel-H1-evidence/manual-notes.log and /tmp/cf2otel-H1-evidence/candidate.diff. Resume once sibling lint contention resolves, remaining required gate/review/CI; acceptance unchecked.

Resume correction: runner removed the isolated worktree at lane completion; no live candidate tree remains. Durable diff /Users/rob/repos/cf2otel/codex/h1-loop23/candidate.diff SHA256 f2c16bf06c5add666ed8228f74356ebcabbde78f460acf42fd3d47cbb7f3cdbf plus base-red/candidate-green/fake-upstream/CodeRabbit/gate logs preserved alongside it. Reconstruct in a fresh isolated worktree on named base and reconcile current main before any resumed gate; do not treat missing old path as a retained tree.

Landed from the main thread on 2026-10-05. Reconstructed the loop23 candidate (diff sha256 f2c16bf0…) on base d936bef with no changes. just check exit 0 (lint no longer blocked: the lint recipe now passes –allow-parallel-runners, fixing the cross-repo golangci-lint lock that blocked loops 19, 20 and 23). go test -race -count=3 -timeout=20m ./internal/cfapi/ ./internal/config/ ./internal/collectors/selfobs/ exit 0. Base-red and fake-upstream green evidence is from loop23 (codex/h1-loop23). CodeRabbit for this candidate: complete, 0 findings, 12/12 files (loop23).

Final Summary

REST Retry-After and Ratelimit pauses are capped by cloudflare.rate_limit.max_pause (default 5m, range 1s-60m, documented in docs/configuration.md and config.example.yaml), with one warning per capped pause. GraphQL budget detection parses each error entry independently, so a malformed sibling cannot hide a budget code, and missing or non-string codes never pause. No existing test was changed; new tests cover the ceiling at config, process and fake-upstream level, plus malformed and mixed envelopes. Verified with just check and the repeated race gate on the landed tree, plus the loop23 base-red and candidate-green logs.

View the source file on GitHub