Skip to content

fix: answer every refusal the site builds as a problem document - #64

Merged
jm-rivera merged 1 commit into
devfrom
fix/proxy-problems-timed-out
Oct 24, 2026
Merged

jm-rivera merged 1 commit into
devfrom
fix/proxy-problems-timed-out

Conversation

@jm-rivera

Copy link
Copy Markdown
Contributor

The site answered its own refusals in two shapes: problem documents for the routes website#54 touched, and {error, retry, detail} or {detail} bodies everywhere else, which the client contract in DevelopmentFinanceObservatory/spec-kit#20 now retires. A timed-out search part also showed "No data matched this query.", because the vendored client predated the timed_out no-data reason.

Every HTTP refusal the site builds is now an application/problem+json document from src/lib/proxy/problem.ts, with type, title, status, detail, code, retryable and trace_id, and the x-dfo-trace-id header. That covers the proxy's 429 (rate_limited, with its rate-limit headers and Retry-After) and 502 (transient_unavailable) in forward.ts, forwardAsset, the /codes/[code] and Studio routes, the Studio allowance in spendPrompt.ts, and the share, conversations, roadmap votes, events, source-doc, version-download, download-pin and live-share routes. A code the API registry or proxy-codes.json holds links type to /codes/<code>; a site code (guest_limit, live_*, refresh_pending, unauthorized and the rest) reads about:blank. problem() places extension members first, so none can override a core member. Readers read code: readShareAnswer, liveCards, cardDownload.liveRefusal (which takes the wait from Retry-After), and createSearchShare, which reads the platform's own code from platform_code only on a platform_refused share, so a 400 or 413 shows the generic share failure again.

vendor/developmentfinance-client-0.1.0.tgz is rebuilt from DevelopmentFinanceObservatory/sdk (the problem-document client), and only its integrity line moves in pnpm-lock.yaml. view.ts gains the timed_out text and readings.ts the breakdown basis note the new types require. docs/development.md notes that a local re-vendor needs the old copy under node_modules/.pnpm removed, since the file name does not change.

Left as they are: /api/feedback, which mirrors the brochure site's {ok, message}, and the plain-text s/[id]/download and docs-md responses. liveBackend.refusalOf keeps its error fallback because the dfo-ai backend still sends {error} bodies.

A reviewer should check the code chosen for each route and that relayed upstream responses pass unchanged.

Testing: pnpm typecheck and pnpm lint passed, prettier passed on the changed files, and pnpm test passed 1,879 tests including db/test against Postgres 18.4.

The proxy's own 429 and 502, the codes and Studio routes, the Studio
allowance, and the share, conversations, roadmap, events, source-doc,
version-download, download-pin and live-share routes answer
application/problem+json through src/lib/proxy/problem.ts, with a code,
retryable and trace_id; the 429s send Retry-After. A code the API
registry or proxy-codes.json holds links its type to /codes/<code>,
and a site code reads about:blank. Browser readers read `code`, and a
platform_refused share carries the platform's code in platform_code.

The vendored @developmentfinance/client is rebuilt from the SDK, which
adds the timed_out no-data reason (with reader text) and the breakdown
candidate basis.
@jm-rivera
jm-rivera merged commit 78a8348 into dev Oct 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant