# AWS S3 Storage

`s3` stocke les objets dans AWS S3 ou dans un backend compatible S3 comme MinIO.

## Installer

```bash
uv add "arclith[s3]"
```

## Configuration

```yaml
# config/adapters/outbound/storage.yaml
adapter: s3
bucket_name: "arclith-files"
prefix: "uploads"
region_name: "eu-west-3"
endpoint_url: null
force_path_style: false
multitenant: false
```

| Champ | Role |
|---|---|
| `bucket_name` | bucket cible en single-tenant |
| `prefix` | prefixe applique devant les objets |
| `region_name` | region AWS passee a `boto3.Session` |
| `endpoint_url` | endpoint custom, utile pour MinIO |
| `force_path_style` | force le path-style S3 pour les compatibles S3 |
| `multitenant` | autorise les coordonnees S3 dans `TenantContext` |

## Credentials Et Secrets

En single-tenant, l'adapter ne declare pas de champs `aws_access_key_id` dans
`StorageSettings`. Il laisse `boto3` utiliser sa chaine standard: role IAM du
runtime, profile AWS, variables standard du SDK ou credentials injectes par la
plateforme.

En production, preferer un role IAM ou workload identity. Si les credentials
varient par tenant, les fournir via `TenantContext` avec ces cles:

```text
bucket_name
prefix
region_name
endpoint_url
force_path_style
profile_name
aws_access_key_id
aws_secret_access_key
aws_session_token
```

Ces valeurs tenant doivent venir de Vault ou d'un secret manager. Elles ne
doivent pas etre commitees dans `storage.yaml`.

## MinIO Local

```yaml
# docker-compose.minio.yml
services:
  minio:
    image: quay.io/minio/minio:latest
    command: server /data --console-address ":9001"
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: minioadmin
    volumes:
      - minio-data:/data

volumes:
  minio-data:
```

Configuration Arclith locale:

```yaml
# config/adapters/outbound/storage.yaml
adapter: s3
bucket_name: "arclith-files"
prefix: "uploads"
region_name: "eu-west-3"
endpoint_url: "http://127.0.0.1:9000"
force_path_style: true
multitenant: false
```

Demarrer MinIO, creer le bucket `arclith-files`, puis lancer le smoke test du
[quickstart](quickstart.md) avec des credentials de developpement injectes dans
l'environnement local.

## IAM Minimal

Pour le contrat actuel, borner les droits aux objets du prefixe utilise:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::arclith-files/uploads/*"
    }
  ]
}
```

`FileStoragePort` ne liste pas les objets. Ajouter `s3:ListBucket` uniquement si
un use case applicatif introduit explicitement du listing, avec une condition de
prefixe.

AWS documente que les operations objet S3 comme `GetObject`, `PutObject` et
`DeleteObject` ciblent les ARN objets, y compris avec un prefixe. Voir
[How Amazon S3 works with IAM](https://docs.aws.amazon.com/AmazonS3/latest/userguide/security_iam_service-with-iam.html).

## Limites Connues

- Pas de creation automatique de bucket.
- Pas de policy lifecycle ou retention.
- Pas d'URL signee dans le port initial.
- Pas de listing objet.
- Pas d'upload multipart expose au client final.

## Validation

```bash
uv run python -c "from arclith import Arclith; Arclith('config').file_storage()"
uv run python scripts/storage_smoke.py
```

Ne jamais lancer un smoke test destructif sur un bucket de production.
