# ADR-0001 — Stored file keys keep the user's filename

The repository's architectural decision, rationale and consequences.

# ADR-0001 — Stored file keys keep the user's filename

**Status:** accepted · 2026-07-13. Isolation clarification · 2026-10-01.

## Context [#context]

`packages/storage` shipped a `sanitizeFileName` helper — lowercase, strip unsafe characters, collapse whitespace, preserve one extension — that **nothing in production ever called**. It was exercised only by its own tests.

An architecture review flagged this as a gap: user-supplied filenames become object keys unsanitized. The obvious fix is to wire the sanitizer in at the upload boundary.

We are deliberately not doing that.

## Decision [#decision]

A stored file's key keeps the name the user gave it. The sanitizer is deleted rather than wired in.

## Why [#why]

**The raw name is a feature, not an oversight.** The upload composer lets a user _edit_ the name a file is stored under before uploading it, and that name becomes the key. Sanitizing would silently overwrite an explicit choice the user just made — a file the user named `Relatório Final.PDF` would come back as `relatorio-final.pdf`. The file gallery displays `file.name || file.key`, so the change would be visible.

**The filename does not choose the Organization.** The gateway applies `orgs/<organizationId>/` server-side after checking the current Session and membership. This organization prefix replaced the original user prefix under [ADR-0003](0003-organizations-are-the-tenant.md). Client-supplied names cannot choose or escape the organization prefix. Object-storage keys are flat strings, so a `..` segment is a literal character sequence rather than a parent directory.

**Uploads are already gated where it matters.** `validateUpload` enforces the size limit and the MIME allowlist. That is the boundary that protects the system; the filename is presentation.

## Consequences [#consequences]

- Arbitrary user input (spaces, unicode, long names) appears in stored keys and in URLs derived from them. Anything consuming a key must treat it as opaque and encode it for transport — not assume it is URL-safe.
- If a future requirement _does_ demand sanitized keys (a storage backend with key restrictions, say), the display name must be preserved separately so the user still sees the name they chose. Reopen this ADR rather than sanitizing in place.
- `sanitizeFileName` and `packages/storage/src/keys.ts` are gone. Do not reintroduce them without revisiting this decision.

## Related [#related]

- Supersedes the "wire the sanitizer in" candidate raised in issue #36.
- The current organization isolation rule lives in the files gateway's `keyPrefix` and [ADR-0003](0003-organizations-are-the-tenant.md). The historical discussion in #32 deleted a second, contradictory key-building rule.

