Skip to main content

forkFromListing

Fork a published listing into a working v1 strategy owned by ownerID — the "fork a listing" path (internal/marketplace.LoadForkSource + ForkFromListing), which NEVER reads the source ent.Strategy. AUTHENTICATED; authorization checks the TARGET org ONLY (workspace__strategy__write on ownerID) — there is deliberately NO scope check against the source listing's own workspace: the listing IS the authorization (it was published, and it carries its own platform-wrapped fork payload). Gated additionally behind the marketplace_fork entitlement.

Entitlement and quota are enforced IN THE RESOLVER, exactly as createStrategy and forkStrategy enforce them: max_strategies (billing.EnforceStrategyLimit) and, for a freqai listing, reinforcement_learning (billing.EnforceRLFeatureForStrategy, detected from the SEALED code/config/uiBuilderConfig — never from the publisher's self-declared category). strategy.Create carries no quota check of its own, so nothing downstream would catch either.

ownerID is resolved through workspace.ResolveOwnerWorkspaceForCreateScoped before the row is written, so the forked strategy always lands under a validated workspace inside the caller's tenancy.

idempotencyKey makes a retry safe. A client that mints ONE key per fork intent and resends it on every retry of that intent gets the SAME strategy back from every call after the first that landed — including when that first call's response never arrived (an aborted fetch still commits server-side) — and the listing's fork count moves once. A replay is answered even after the workspace has reached max_strategies, because it creates nothing. Distinct keys are distinct forks (forking one listing twice to tune two variants is legitimate), and so is every call that sends no key. A key is scoped to (listing, target workspace), must be 1-255 bytes with no control characters, and is released if its fork is deleted.

forkFromListing(
listingSlug: String!
ownerID: ID!
idempotencyKey: String
): Strategy!

Arguments​

forkFromListing.listingSlug ● String! non-null scalar​

forkFromListing.ownerID ● ID! non-null scalar​

forkFromListing.idempotencyKey ● String scalar​

Type​

Strategy object​