toolup-forgetoolup-forge

Phase 69o — Client Remoting proxy convention adoption (migration)

Phase 69o — Client Remoting proxy convention adoption (migration)

What changes

This is a consumer-side adoption sweep, not a substrate change. The transport-level per-call header read was already implemented earlier (the send-time CsrfClient request-guard installed at the XHR + fetch seam) and codified as a convention in docs/platform/client-remoting-proxies.md. What remained was the consumer-side cleanup: convert the older defensive let private api () = ... per-call shape to module-level values.

See docs/platform/client-remoting-proxies.md for the canonical convention statement. This phase doesn't change the convention; it sweeps the remaining sites that hadn't adopted yet.

Diff to apply (per consumer)

For each *.Client module that still declares let private api () = …:

- // Built per call (not module-level): `Api.makeProxy` captures
- // `withRequestHeaders` once and the transport historically froze the
- // header list, so a module-level value would snapshot an empty
- // `X-CSRF-Token` before the SDK's async CSRF prefetch resolved — 403
- // on every mutating call under `DefaultSecurityHardening`.
- let private api () =
-     Api.makeProxy<FooApi> (customOptions = UserSession.withRequestHeaders)
+ // Module-level per the SDK convention — see
+ // `toolup-forge/docs/platform/client-remoting-proxies.md`. The
+ // `UserSession.withRequestHeaders` customiser is a passthrough; CSRF /
+ // auth headers attach at send time via `CsrfClient`'s request-guard,
+ // not at proxy-build time.
+ let private api: FooApi =
+     Api.makeProxy<FooApi> (customOptions = UserSession.withRequestHeaders)

Then sweep call sites: (api ()).Method argsapi.Method args. If your editor has find/replace, the simplest pair is (api ())api (and (configApi ())configApi where present). Run Fantomas after.

Verification

  • dotnet build <your-app>.sln — clean.
  • dotnet fable -o output --noCache for the consuming client project — clean. Browser smoke-test that mutating calls still carry the X-CSRF-Token header (DevTools → Network → any POST to /api/*).
  • A diff vs the previous build's Fable JS shows the per-call proxy-construction code removed; the proxy is constructed once during module init.

Rollback

Revert the diff above. If a future change re-introduces a header-snapshot customiser on UserSession.withRequestHeaders — see the convention doc's "When per-call would be needed" section — the per-call shape becomes correct again, but the right place to relitigate that trade-off is the customiser PR review, not a consumer-module defensive scattering.

See also