AI Router · CLI · MCPCheapest eligible quotes before you create
trust · consideration

Access control for MCP-generated media outputs

Explain owner checks, private storage, signed URL lifetime, refresh, and opt-in publication.

Get practical MCP creation notes
Related circuit

Use the MCP security directory for the wider authentication and transport review. Use the secret-redaction guide before logging download failures or support evidence, because a complete signed link is a live credential during its validity window. These next steps preserve this page's narrow ownership: generation-record authorization, private media delivery, temporary links, and opt-in public publication.

OAuth sequence

Treat every signed output URL as a temporary bearer credential

A signed URL is not owner-bound after it is issued. Cloudflare's R2 documentation says a presigned URL authorizes anyone holding it to perform the signed operation on the named object until expiry, without another authentication header. It can be reused during that window. The signature limits the object, operation, and time; it does not identify the person who presents the URL. Avoid placing a live link in prompts, model context, analytics, logs, screenshots, tickets, chat transcripts, or long-lived manifests.

Cloudflare documents an R2 expiry range from one second through seven days, but that provider range is not evidence of OfflineCreator's configured lifetime. The public Studio policy only says its links expire quickly. Choose and test the application lifetime against the download task, then publish the actual expiry in the response rather than teaching clients to guess. A link that expires mid-transfer should lead to a new authenticated mint request, not a public-object fallback or a longer hard-coded link.

Expiry is a risk limit, not immediate revocation. Once a bearer link leaves the service, the recipient can use it until it expires and can save the downloaded bytes permanently. Cloudflare's documentation therefore recommends short expirations for sensitive operations and sharing only with intended recipients. If access must stop immediately, an application needs a different delivery design, such as an authenticated proxy that checks current authorization on every request. This research did not test whether Studio uses presigned R2 URLs, a proxy, or another signing mechanism, so the provider behavior is presented as design and review evidence rather than a product implementation claim.

Do not store
The complete signed URLKeep a generation ID and request a new authorized link when the task resumes.
Do not infer
A long provider maximum is the product lifetimeVerify the deployed expiry and response metadata instead of extending the policy's “quickly” wording.
Test
Valid, expired, copied, and refreshed link behaviorInclude a different-account refresh attempt and confirm that it cannot mint access.
Privacy boundary

Keep private download, limited sharing, and publication distinct

Use three explicit access states. A private download stays behind the account-level owner check and receives only temporary delivery access. Limited sharing uses a deliberately issued bearer link and must disclose that anyone receiving the link can use it before expiry. Public publication is a separate product action that changes what unauthenticated readers may see. Never model these states as one `isShared` flag or turn a successful download into consent to publish.

OfflineCreator's current policy says generation media remains private unless the user chooses to publish a generation to the Community gallery. Publication makes that generation's media, prompt, and settings publicly visible until the user unpublishes it; the public homepage independently describes source media and outputs as authenticated by default and Community sharing as optional. This is an opt-in publication commitment, not evidence that every client exposes a publish tool. An MCP media-generation result should remain private unless a separately documented and authorized publication action exists.

The database policy and application query must agree on the transition. Supabase documents that grants decide which roles can reach a Data API object while RLS decides which rows those roles can access, and recommends both for exposed objects. Its RLS examples compare `auth.uid()` with a row's user identifier; its storage ownership guide also warns that recording an owner does not enforce access by itself. For a generation and Community post, verify owner-scoped select, publish, unpublish, and remint operations, including server-side paths that use elevated credentials. RLS is defense in depth, not a substitute for passing the authenticated account into every application query.

Unpublishing should remove the public read path without changing ownership of the private generation. OfflineCreator's policy promises that unpublishing removes public access, but it cannot retract copies already downloaded while public or eliminate every previously cached representation instantly. Test the public route, cache behavior, feed query, direct media path, and private owner download separately after unpublishing. Do not promise retroactive deletion from third-party caches or recipients.

Private
Owner-authorized, temporary deliveryDefault state for an MCP-created output.
Limited share
Explicit bearer-link disclosureThe recipient need not be the owner once the URL has been issued.
Public
Separate opt-in Community publicationMake the public fields and unpublish consequences visible before confirmation.
Retention ledger

Authorize the generation record before minting media access

Access control for an MCP-generated output should begin with the generation record, not with the object URL. Resolve the authenticated Studio account, load the requested generation through an owner-scoped query, confirm that it has completed and has an output, and only then mint a short-lived download link for that one object. Do not accept an object key, bucket name, or destination URL supplied by the MCP client as proof of ownership. OfflineCreator's current privacy policy states the narrower public commitment: signed download links expire quickly and require the account's authorization to mint.

Keep the media object private while that decision happens. OfflineCreator discloses Cloudflare as its private-media-storage provider and says media is private by default and not publicly listable. Its policy separately says database access is governed by row-level security and least-privilege credentials. Those statements support a layered review: an owner check on the generation or publication record, a private object-store boundary, and a narrowly scoped delivery mechanism. They do not prove the exact production policy expression, signing duration, route implementation, or deployed configuration.

For an MCP client, return the minimum delivery result needed to finish the task: the generation identifier, a short-lived URL, expiry information when available, and content type. Treat a request for a fresh link as a new authorization decision. Expiry should never be interpreted as permission to skip the account and ownership checks on the refresh path.

Turn the design into two-account evidence. Account A creates a private generation and can request delivery; account B cannot load that record or mint a replacement link from its identifier. After the first link expires, A can request a new bounded link only through a fresh authenticated decision. This route-level matrix is the page's unique focus, distinct from the owner-facing privacy policy and retention choices covered by the media-privacy page.

Record gate
Authenticated account owns the requested generationLook up by both account identity and generation identifier instead of fetching first and checking later.
State gate
Generation is complete and has a stored outputDo not mint access for a reserved, processing, failed, missing, or deleted object.
Delivery gate
One bounded link for one approved objectKeep storage credentials and unrestricted object paths on the trusted server.
Canonical plate

Evidence boundary and remaining release checks

The current public evidence supports a limited product description: OfflineCreator says media is private and not publicly listable by default, account authorization is required to mint quickly expiring download links, database access uses RLS and least-privilege credentials, and Community publication is explicit and reversible. The homepage corroborates the private-by-default and opt-in sharing boundary. Cloudflare separately documents that R2 buckets are not publicly accessible by default and require explicit enablement for public exposure. Cloudflare and Supabase documentation explain the underlying access-control properties reviewers should test, but they do not establish OfflineCreator's exact schema, policy SQL, link duration, signer, cache topology, or deployed route behavior.

The recent-evidence run was degraded and produced no sufficiently specific community evidence for generated-media ownership, link refresh, RLS, or Community publication behavior. Its surfaced items concerned other MCP projects and access patterns. No anecdote is used to claim prevalence, customer outcomes, or effective security. Failed, partial, and unconfigured source lanes also cannot establish that practitioners were quiet.

Before editorial review, obtain an externally reviewable implementation record or controlled test showing same-owner success, different-owner denial, expired-link denial, authorized remint, publication confirmation, public-field scope, unpublish behavior, and post-unpublish cache behavior. Verify elevated server credentials and direct object paths as separate bypass cases. Until that evidence exists, this page remains an unpublished, unreviewed research draft and its test design must not be rewritten as a claim that the deployment passes.