Storage → Files is the current Explorer workspace. The separate Files navigation item is a legacy API and data model. Use Storage for every new workflow.
What Storage governs
The durable entry is authoritative for identity, access, lifecycle, and audit. Uploaded bytes without a finalized Storage entry are not a consumable application artifact.
Navigate the UI
Open Storage. The workspace tabs and available actions are calculated by the API for the current principal.
The grid supports folder navigation, breadcrumbs, name search, paging, sorting, archive views, and server-side filters. Entry details expose status, version, tier, MIME type, extension, size, ACL state, retention, metadata, references, creator, updater, archive reason, and text-analysis status when present.
Create a folder
Select Create folder and configure:
When no ACL fields are sent and the parent is restricted, the backend copies the parent’s ACL to the new folder. Regardless of the child’s own flag, every restricted ancestor remains an effective read boundary.
Upload a file
The advanced upload panel exposes:- file selection and final name;
- content type hint;
- lifecycle tier:
HOT,WARM,COLD, orFROZEN; - optional text analysis;
- retention: keep the default, never expire, TTL, or absolute expiration;
- User and Group ACLs;
- user metadata.
direct upload session, transfers bytes to the returned resumable URL, then waits until the session becomes FINALIZED. For text-like files, Analyze text content requests background analysis. The UI displays Processing, Ready, or Processing failed from durable metadata.
If a file with the same normalized name already exists, the UI asks whether to overwrite it. Replacement keeps the stable storageEntryId, requires the version observed during confirmation, and produces a new entry version.
Portable folder paths
Do not copy folder UUIDs between development, staging, and production. Resolve an exact root-relative path once per execution, or ensure it idempotently.resolveFolderPath() and ensureFolderPath():
- match each segment case-insensitively under its parent;
- accept optional leading and trailing
/; - reject backslashes, empty or dot segments, paths over 1,024 characters, and more than 32 named segments;
- fail when a segment is inaccessible, archived, deleted, or a file;
- never mutate ACL or provider settings on existing folders;
- apply ensure options only to segments created by that call.
Hierarchical access control
Storage evaluates authorization in layers:- The caller needs
FILE_READorFILE_ADMINto enter the public Storage API. - Restricted entries admit their creator, explicitly assigned Users, assigned Groups, and supported Group-owner relationships.
- A restricted ancestor must also admit the caller.
- The workspace may further remove actions or require an owning product boundary.
restricted, restrictedByAncestor, and effectiveRestricted let the UI show why an entry is protected. Making a child unrestricted never bypasses a restricted parent.
For a restricted file-processing pipeline, grant the Job template’s service account access to the destination folder before activating the Event. A developer’s interactive access does not transfer to the unattended principal.
Retention and expiration
Files accept exactly one of the following retention intents:retention preserves the current/default policy. ttlSeconds must be a positive integer, expiresAt must be a future ISO 8601 timestamp, and the two fields are mutually exclusive. Folders do not accept retention.
For an upload session, TTL starts when the file is finalized—not when the session is created. Before expiresAt, download URLs are capped so that they cannot outlive the file. At expiration, reads and mutations fail immediately even if maintenance has not yet changed the database status.
Instance maintenance then transitions the file to ARCHIVED with archiveReason: TTL_EXPIRED. Restoring it requires either new retention or retention: null. Archived-entry purge follows the instance garbage-collection retention window; after permanent deletion, Storage does not offer restore.
Entry lifecycle and version safety
Every consequential mutation carries the current entryversion.
Bulk archive and delete accept 1–100
{ storageEntryId, version } roots. If both a folder and its descendant are selected, the backend processes the topmost root once.
Choose an upload path
Upload sessions are durable and their
expiresAt is authoritative. The default service lease is one hour, but deployments can configure it. extendUploadSession() renews an active session; it does not revive FAILED, ABORTED, EXPIRED, or FINALIZED sessions.
Incremental upload from low-code
Text analysis, stats, and bounded reads
computeStats controls derived metadata for readable text files:
Stored statistics contain
lineCount, separator, encoding, batchSize, batches, and a byte-offset map. The default line batch size is 100,000 unless the caller requests another positive size. Replacing file bytes invalidates derived metadata so stale offsets are not reused.
Storage computes line-oriented text statistics. It does not publish a word-count or character-count contract.
getText() uses maxChars only to bound the returned window.Read one text batch
getFileData() returns base64. Direct binary reads are limited to 10 MiB. For a larger object, request buffer: true with byte start/end ranges of at most 10 MiB, use getDownload(), or stream the entry to HTTP.
The UI previews text up to 5 MiB and supported raster images up to 20 MiB. HTML and SVG are intentionally excluded from inline preview. These are preview limits, not download limits.
Finalization is the publication boundary
Incoming file → Event → Job → output
This pattern turns an uploaded CSV into a governed processing pipeline.1
Prepare governed folders
Create
imports/bank/incoming and imports/bank/processed. Restrict both to the operations group and the Job service account.2
Configure upload
Upload into
incoming with metadata such as documentType: bank-transactions and choose synchronous stats if the first Job must see line counts immediately.3
Create the Event
Subscribe a Job template to
STORAGE_CREATED. In the UI, filter message properties kind = FILE, metadata.documentType = bank-transactions, and optionally mimeType = text/csv. The builder adds the persisted message. prefix automatically.4
Process by stable ID
The Job receives
{ type, metadata, message }. Read message.storageEntryId, reload the authoritative entry under the Job principal, process bounded batches, and write a new Storage result.5
Operate the run
Correlate Event History, Job History,
operationId, input entry ID, and output entry ID. Make retries safe by recording a deterministic source-version/idempotency key.async and the Job depends on ready offsets, target STORAGE_SYNCHRONIZED instead of STORAGE_CREATED. Do not subscribe the same non-idempotent workflow to both topics.
Storage lifecycle events
Lifecycle messages carry the public entry projection, including the stable ID and version. Reports namespaces deliberately suppress these events. Event acceptance and file finalization are separate from target Job success—follow Event History and Jobs for downstream evidence.
Failure and recovery semantics
- If byte transfer fails before completion, abort the session. Do not treat partial bytes as a file.
- If confirmation is uncertain, query
getUploadSession()before retrying.FINALIZEDis success;FAILED,ABORTED, orEXPIREDrequires a new session. - A version conflict means another actor changed the entry. Reload and deliberately reapply the change.
- An upload-name conflict can represent a completed existing file or an active reservation. Choose replacement only after comparing the existing entry and version.
- Async text-analysis failure does not roll back the finalized file. The entry remains readable; the UI exposes failure and a later
getFileStats({ reloadStats: true })can recompute. - Lifecycle event enqueue failure is logged after the Storage commit; the finalized entry remains authoritative. Reconciliation must start from Storage state, not from an assumed event.
- Signed preview and download URLs are temporary credentials. Request a fresh URL, and never persist or log one.
Legacy Files versus Storage
See Files (legacy) before maintaining an existing
fileId integration.
Production checklist
- Resolve logical folder paths at runtime; do not deploy folder UUIDs across instances.
- Put confidential data below a restricted folder and test with the actual service account.
- Select retention explicitly for transient inputs, exports, attachments, and evidence.
- Treat
FINALIZEDas the only upload success boundary. - Use
computeStats: 'sync'when the immediate event target requires stats; otherwise use async and react toSTORAGE_SYNCHRONIZED. - Process large text files by
batchNumber; use byte ranges or streams for large binary files. - Preserve entry IDs and versions, never signed URLs or internal object paths.
- Make Event replay and Job retry idempotent against source entry ID and version.
- Archive before permanent deletion and understand the instance purge window.
Related guides
HTTP and Storage
Stream remote requests, responses, and conversions without buffering file bytes.
SDK storage and batching
Use runtime batching, upload sessions, and bounded reads from Node.js.
Storage low-code reference
Search every current, non-deprecated
storage.* method and signature.Events
Filter Storage messages and route them to governed Jobs or Agents.
API reference
Inspect Explorer, upload-session, lifecycle, workspace, and provider-config operations.
Files (legacy)
Understand the compatibility surface and plan migration from
fileId.
