> ## Documentation Index
> Fetch the complete documentation index at: https://docs.casebender.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Storage support policy

# Storage support policy

This policy describes storage behavior implemented in the current CaseBender
codebase. It does not announce or imply a MinIO retirement date. MinIO remains a
supported provider for releases whose release notes include it; any future
lifecycle change requires a separately published notice and migration window.

## Provider support matrix

| Provider             | Status                                                                             | Authentication                                     | Required production controls                                                                                  | Known constraints                                                                                                                                                                             |
| -------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Local filesystem     | Supported for development, single-node installs, and validated RWX PVC deployments | Filesystem permissions                             | Persistent `/data`, backup, encryption at rest from the volume layer, arbitrary-UID write test                | No signed URLs; metadata uses adjacent `.meta.json` files; multi-replica use requires coherent RWX semantics                                                                                  |
| MinIO                | Supported as externally managed object storage                                     | Access/secret key                                  | TLS with trusted CA, least-privilege bucket policy, server-side encryption, versioning/backup, integrity test | Native provider attempts to create a missing bucket; pre-create it. The legacy deletion path described below must be removed before other providers have complete attachment lifecycle parity |
| AWS S3               | Supported                                                                          | IAM role preferred; static keys accepted           | TLS, bucket encryption, versioning, Block Public Access, least privilege, audit logging                       | Custom endpoints force path-style access and are supported only after the contract suite passes                                                                                               |
| Google Cloud Storage | Supported                                                                          | Workload Identity/ADC preferred; key file accepted | TLS, uniform bucket access, encryption, versioning/retention, least privilege                                 | Availability check attempts bucket creation when absent; pre-create it. Signed URLs require signing capability                                                                                |
| Azure Blob           | Unsupported                                                                        | N/A                                                | N/A                                                                                                           | Configuration types exist, but the factory intentionally throws and no provider implementation is exported                                                                                    |

“Supported” means the provider implements upload, download, delete, exists,
list, metadata, copy, and availability methods behind `StorageService`. It does
not mean every S3-compatible product/version is certified. Record the product
version and contract-suite result for each customer deployment.

## Configuration contract

Always set `STORAGE_PROVIDER` explicitly in production. Auto-detection is a
developer convenience and must not select a backend during a release rollout.

* `local`: `STORAGE_PATH=/data`
* `minio`: `MINIO_ENDPOINT` is a hostname, `MINIO_PORT`, `MINIO_USE_SSL=true`,
  `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_BUCKET`, optional
  `MINIO_REGION`
* `s3`: `S3_BUCKET`, `AWS_REGION`, optional IAM-provided credentials, optional
  HTTPS `S3_ENDPOINT`
* `gcs`: `GCS_BUCKET`, optional `GCS_PROJECT_ID`; use Workload Identity/ADC

Store credentials in the deployment secret provider, not a ConfigMap, manifest,
image, support bundle, or command history. In production, fail the deployment
when object-storage TLS verification fails. Do not set `MINIO_USE_SSL=false` or
use an `http://` S3 endpoint outside an explicitly isolated development system.

Application object keys are durable references in the database. Preserve keys
byte-for-byte during migration. Attachment keys currently use
`attachments/<entity>/<timestamp>-<sanitized-name>`.

## Direct MinIO reference inventory

The supported boundary is `apps/web/lib/storage/index.ts`, with provider
construction in `apps/web/lib/storage/factory.ts`.

Expected direct SDK usage inside provider adapters:

* `apps/web/lib/storage/providers/minio.ts`
* `apps/web/lib/storage/providers/s3.ts`

Legacy direct runtime usage:

* `apps/web/lib/minio/minio.ts` constructs a MinIO client from a database-backed
  integration and can create buckets.
* `apps/web/server/routers/attachment.ts` deletes attachment objects through the
  legacy MinIO service instead of `StorageService`. This bypasses
  `STORAGE_PROVIDER`, so deletion is incomplete for local, S3, and GCS.
* `apps/web/services/attachment/index.ts` imports `MinioService` but does not use
  it. Uploads correctly delegate to `services/attachment/server.ts`, which uses
  `StorageService`.

The MinIO settings UI and MinIO tests are integration/configuration surfaces,
not additional production client construction sites. Compose and installer
references configure providers or provision a MinIO service; they are not
runtime storage API calls.

Attachment deletion is routed through the existing
`deleteAttachmentFile`/`StorageService.delete` path, so local, MinIO, S3, and
GCS use the same lifecycle boundary. A storage deletion failure blocks deletion
of the database record and is surfaced to the caller for operational follow-up.

## Startup health contract

Before serving writes:

1. validate the explicit provider and all required values;
2. resolve the endpoint and establish a verified TLS connection;
3. authenticate with the runtime identity;
4. confirm the existing bucket/container or writable `/data`;
5. perform a namespaced write/read/hash/delete canary;
6. expose failure through readiness without logging credentials.

Current provider `isAvailable()` methods can create absent MinIO/GCS buckets.
Therefore pre-create storage and validate it with deployment credentials before
application startup. Runtime credentials should normally have object CRUD/list
permissions, not account-wide administration.

## Provider contract and integrity

Run `scripts/storage/validate-storage.sh` with credentials scoped to a dedicated
test prefix. The test verifies startup access, upload, metadata/list visibility,
download SHA-256 integrity, copy integrity, and deletion. Run it:

* before installation and after credential/CA rotation;
* against every S3-compatible product/version offered for support;
* before and after a provider migration;
* during release qualification from the same network and CA trust context as
  the application.

The script is destructive only within its unique
`casebender-contract/<timestamp>-<pid>` prefix. A passing CLI test supplements,
but does not replace, an application attachment lifecycle test.

## Data protection and operations

* Enable bucket/volume encryption, versioning or snapshots, and independently
  protected backups.
* Apply retention/object-lock only after validating CaseBender delete and legal
  hold workflows; retention can make deletes intentionally fail.
* Deny public access. Signed URLs must be short-lived and audited.
* Monitor availability, latency, throttling, capacity, failed deletes, and
  checksum mismatches.
* Include storage and database in one documented consistency set.
* Test restore and the copy-verify-rollback runbook at least once per supported
  release train.

Follow `storage-migration-runbook.md` for migration and
`storage-release-security.md` for release evidence and SBOM handling.
