Files
twenty/packages
Félix Malfait 8156bf2b89 perf(twenty-server): drive immutable file caching from fileFolderConfigs on both serving paths (#22510)
Follow-up to #22166 (now merged). Single commit, rebased onto main.

## Why

#22166 introduced a `Cache-Control` header for avatar responses, gated
on a hardcoded `CACHEABLE_PICTURE_FILE_FOLDERS = [CorePicture]` list.
Two limitations:

- The list is an ad-hoc second classification of `FileFolder`,
maintained separately from the central `fileFolderConfigs`.
- The header is only set on the stream branch of `getFileById`. On S3
deployments with presigned URLs enabled, the controller 302-redirects
before `setFileResponseHeaders` runs and the presigned S3 response
carries no `Cache-Control` at all — so the header never fires where it
matters most.

Whether a folder's bytes are cacheable-forever is a property of how the
folder is written, and the codebase already has a per-folder source of
truth: `fileFolderConfigs`.

## What

- Add `immutable: boolean` to `FileFolderConfig`. `true` for folders
whose write paths mint a fresh `v4()` file id embedded in the resource
path on every upload — so the bytes behind a given URL can never change:
`CorePicture`, `FilesField`, `Workflow`, `AgentChat`, `EmailAttachment`,
`Dpa`. `false` everywhere else, notably:
- `PublicAsset` — path-addressed, overwritten in place on app
(re)install (including the new manifest logo import)
- `AppTarball` — reuses `tarballFileId` and a stable
`${registrationId}/app.tar.gz` path across version bumps
- `setFileResponseHeaders` reads the flag instead of the ad-hoc list
(list deleted).
- Thread `responseCacheControl` through
`FileStorageService.getPresignedUrl` → `StorageDriver` → `S3Driver`,
which passes it as `ResponseCacheControl` on the `GetObjectCommand`, so
presigned S3 responses return the same `Cache-Control: private,
max-age=86400, immutable` on the redirect path.

`private` is kept because responses are gated by a per-workspace file
token; `immutable` is safe because a changed file always gets a new id
and URL.

## Tests

- `setFileResponseHeaders` spec: header set for each immutable folder,
not set for mutable folders (`PublicAsset`, `AppTarball`, deprecated
picture folders) or when no folder is provided.
- `S3Driver.getPresignedUrl` spec: asserts `ResponseCacheControl` is
forwarded onto the `GetObjectCommand`.

https://claude.ai/code/session_01AKwhTxYFDhWhCZ4b7sf35W
2026-07-03 12:32:15 +02:00
..