## 41. P2 — 그러나 R0 경계가 문서에만 있고 compile 경로에서 닫히지 않는다

미배선이 선언돼 있는데도, **설정은 그 capability를 계속 받아들이고 런타임은 자격증명을 쥔 presigner를 실제로 만든다.**

1. `ObjectCapabilityRequirement.DIRECT_UPLOAD` / `DIRECT_MULTIPART`는 destination 요구사항으로 선언 가능하고, `ObjectStorageBindingCompiler:206-207`이 그것을 provider capability로 번역한다.
2. `S3ProviderBinding.compileProfiles`는 **MinIO에 대해서만** 이 두 capability 주장을 거부한다("the exact MinIO release cannot claim native conditional managed mutation support"). **AWS profile에는 대응하는 거부가 없다.**
3. 그러면 `S3ObjectStorageProviderContribution:112-150`이 `directUploadEnabled || directMultipartEnabled`일 때 `presignerFactory.apply(clientPolicy)`로 `S3Presigner`를 할당하고 `S3DirectTransferProvider` / `S3DirectMultipartProvider`를 만들어 `SelectedObjectStorageProviderFactory`에 넣는다.
4. 그리고 그 둘을 factory에서 **꺼내 가는 코드가 없다**(`154-...` §8.1c, 매치 0).

즉 AWS binding에서 `direct-upload`를 요구하는 배포는 — startup을 통과하고, presigner를 할당하고, 두 provider를 조립하고, **직접 전송 port는 여전히 하나도 얻지 못한다.** README가 말한 R0는 사실이지만, 그 사실을 강제하는 것은 문서뿐이다.

이 leaf 안에 정반대의 사례가 있어서 대비가 분명하다 — `filesystem-local-dev`는 `prod`/`production` 프로파일에서 **compile 시점에 거부**되고, MinIO의 capability 과대 주장도 compile 시점에 거부된다. 같은 파일이 같은 종류의 "이 조합은 자격이 없다"를 AWS + DIRECT_* 에 대해서만 하지 않는다.

**판정: P2.** 데이터 위험은 없다 — 없는 port는 호출될 수 없다. 위험은 (a) 운영자가 켰다고 믿는 기능이 없다는 것과 (b) 아무도 쓰지 않는 서명 자격증명 핸들이 프로세스 수명 동안 살아 있다는 것이다. 수정은 셋 중 하나다: coordinator를 조건부로 조립하거나, R0인 동안 `DIRECT_UPLOAD`/`DIRECT_MULTIPART` 요구를 compile 단계에서 provider 종류와 무관하게 거부하거나, capability가 켜져도 presigner를 만들지 않도록 조립을 뒤로 미루거나.

