Problem
A resource's lifecycle ops (verify, release, refresh, views, reconcileUsage) can only call the provider's request.baseUrl. compileResource fuses the provider origin into every resource doc (shared/compiler/compile.ts, "resource ops target the provider origin"). Cross-origin calls from a fn get no credential (D16).
This blocks one provider with two resources on two hosts. TinyFish is the first case:
| resource | host | ops |
|---|---|---|
tinyfish/browser-profile | agent.tinyfish.ai | GET/DELETE /v1/profiles/{id} |
tinyfish/browser-session (per-minute billed) | api.browser.tinyfish.ai | GET /usage?session_id=…, DELETE /{session_id} |
The hosted catalog already serves both (tinyfish#browser-sessions/provision, /release). The PR that ports TinyFish's agent and profiles sets the provider baseUrl to the agent host and leaves browser sessions out for this reason.
Proposal (for discussion)
Let a resource def declare its own origin, mirroring the endpoint-level override:
defineResource({
slug: "browser-session",
request: { baseUrl: "https://api.browser.tinyfish.ai" }, // overrides the provider origin
// ...
});- The compiler fuses
def.request?.baseUrl ?? provider.request.baseUrl. Auth and timeouts stay provider-fused. - Credentials keep the D16 rule: they are injected only for the resource's own (resolved) origin.
- This is a resource doc-format change, so it needs an
ENGINE_VERSIONminor bump plusdoc_format_since/fn_abi_sincefacts and a D-numbered decision inrefine-resource-model/design.md(or a new change).
An alternative is a provider-level list of trusted origins for credential injection. It is broader than this case needs.
Once this lands
TinyFish browser sessions port as:
- an ESTIMATED usage line at $0.002 per MINUTE (the public list rate);
reconcileUsagereadingGET /usage?session_id=…hourly, with the window-overlap meter monid-services already drilled;verifycovering the vendor-reaped "abandoned" rows;- an idempotent
DELETEfor release.
Ported the profile half in #168; browser sessions wait on this.