# User File System MinIO/AuthZ Setup

The user file system is exposed through Beaver APIs and `user_files_*` tools. MinIO remains an implementation detail.

The ordinary Files page should only call Beaver's `/api/user-files/*` routes and render the virtual roots `uploads/`, `outputs/`, `shared/`, and `tasks/`. It should not show bucket names, endpoint fields, access keys, secret keys, object prefixes, or MinIO administration actions.

## AuthZ Settings

Each backend identity can store MinIO settings in AuthZ:

```bash
curl -X POST "$AUTHZ_URL/backends/$BACKEND_ID/settings/minio" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AUTHZ_ADMIN_TOKEN" \
  -d '{
    "endpoint": "minio.example.internal:9000",
    "access_key": "user-access-key",
    "secret_key": "user-secret-key",
    "bucket": "beaver-user-files",
    "namespace": "users/{backend_id}",
    "secure": false,
    "region": null
  }'
```

Public reads return masked settings. Internal reads require `AUTHZ_INTERNAL_TOKEN` and return the secret key for protected MCP services.

Deployed personal files use a shared bucket with a backend-scoped namespace. For backend `alice`, Beaver maps:

- `uploads/report.pdf` to `users/alice/uploads/report.pdf`
- `outputs/summary.md` to `users/alice/outputs/summary.md`
- `tasks/task-123/result.json` to `users/alice/tasks/task-123/result.json`

The MinIO policy for Alice's access key must be limited to `beaver-user-files/users/alice/*`. The frontend must still only show Beaver virtual paths, not the shared bucket or namespace.

Check the public, masked view:

```bash
curl "$AUTHZ_URL/backends/$BACKEND_ID/settings/minio" \
  -H "Authorization: Bearer $AUTHZ_ADMIN_TOKEN"
```

Check the internal protected view used by MCP services:

```bash
curl "$AUTHZ_URL/internal/backends/$BACKEND_ID/settings/minio" \
  -H "Authorization: Bearer $AUTHZ_INTERNAL_TOKEN"
```

## Protected MinIO MCP

Run the MinIO MCP service in protected mode:

```bash
bw-minio-mcp serve \
  --host 0.0.0.0 \
  --port 8001 \
  --authz-url "$AUTHZ_URL" \
  --authz-token "$AUTHZ_INTERNAL_TOKEN" \
  --resource-server-url "$MINIO_MCP_PUBLIC_URL/mcp" \
  --state-root /var/lib/bw-minio-mcp
```

In protected mode, the MCP service does not use static MinIO credentials at startup. Each authenticated tool call resolves the backend identity from the bearer token, loads that backend's MinIO settings from AuthZ, and constructs a per-call provider.

Outside protected mode, `bw-minio-mcp serve` requires explicit `--endpoint`, `--access-key`, and `--secret-key` values. It intentionally has no embedded production fallback credentials.

## Beaver Runtime

Beaver should register the MinIO MCP endpoint with backend-token auth when raw object tools are needed:

```json
{
  "tools": {
    "mcpServers": {
      "minio_mcp": {
        "url": "https://minio-mcp.example.internal/mcp",
        "auth": "oauth_backend_token",
        "authAudience": "mcp:minio_mcp"
      }
    }
  },
  "authz": {
    "baseUrl": "https://authz.example.internal",
    "backendId": "backend-user-id"
  }
}
```

Product-level file interactions should still go through Beaver's user file system:

- Frontend: `/api/user-files/status`, `/api/user-files/browse`, `/api/user-files/upload`, `/api/user-files/preview`, `/api/user-files/download`, `/api/user-files/delete`, and `/api/user-files/mkdir`.
- Agent tools: `user_files_list`, `user_files_read`, `user_files_write`, `user_files_delete`, and `user_files_mkdir`.
- Storage boundary: only `uploads/`, `outputs/`, `shared/`, and `tasks/` are valid user paths.

The local workspace browser APIs and generic filesystem tools are retained for runtime/development compatibility, but they are not the user-visible file boundary.

## Verification Checklist

- The Files page root renders exactly `uploads`, `outputs`, `shared`, and `tasks`.
- The Files page source does not call `/api/workspace/browse`.
- `/api/user-files/status` does not return local workspace paths or MinIO bucket details.
- AuthZ public settings responses mask `secret_key`.
- Protected `BW_MinIO_Mcp` returns a clear configuration error if a backend has no MinIO settings instead of falling back to another user's credentials.
