Skip to content

Storage

Every app receives config.storageBucket. The manifest selects one authorization model.

Owner-prefix

yaml
storage:
  authorization: owner-prefix

Only authenticated users can access objects whose first decoded path segment equals their user ID.

js
const [config, session] = await Promise.all([
  opencloud.config(),
  opencloud.session(),
]);
if (!session) throw new Error("Sign in required");

const objectName = [
  session.userId,
  "attachments",
  crypto.randomUUID(),
  file.name.replaceAll("/", "_"),
].map(encodeURIComponent).join("/");

await opencloud.storage.request(
  `object/${encodeURIComponent(config.storageBucket)}/${objectName}`,
  {
    method: "POST",
    headers: { "content-type": file.type || "application/octet-stream" },
    body: file,
  },
);

Persist object names and metadata in an owner-isolated table. Verify cross-user read and forged-prefix write denial.

App-scoped

yaml
storage:
  authorization: app

Authenticated app members share one object namespace. A public app may expose public reads through the bucket, but writes still require an authenticated user.

Safety

  • Sanitize file names and encode each object-name segment independently.
  • Do not request S3 credentials.
  • Do not put secrets in object names or metadata.
  • Use only the runtime-advertised bucket.
  • Delete verification fixtures after tests.

Self-hosted infrastructure for agent-built applications.