# Registry: Repository Access Capabilities # SSOT: wiki/projects/ca-tmpl/registries/capabilities.yaml # Schema owner: feature-contract-registry-governance # Owner branch: feature-repository-access-permission-contract # Last updated: 2026-06-05 # # Notes # - capability는 사용자 권한이 아니라 application use case가 infrastructure capability를 # 사용할 수 있는지에 대한 계약 (feature-repository-access-permission-contract). # - enforcement default = ArchUnit annotation-based rule. compile-time annotation processor는 # alternative. runtime AOP는 forbidden. # - capability 제거는 항상 breaking change. 추가는 additive (registry row 동반 시). # - annotation 표기 (as-built, F1/F2 reconciled 2026-06-05): 코드 SSOT는 단일 # `@UseCaseCapability` (TYPE target, typed attribute). 노트 D2/D11의 flat # `@UseCaseRepositoryAccess(Capability[])` 모델은 superseded. 7 capability ↔ as-built 매핑: # READ_REPOSITORY/WRITE_REPOSITORY → repositoryAccess, TRANSACTION_REQUIRED → transactionMode, # EXTERNAL_OUTBOUND_ALLOWED → externalOutboundAllowed, SENSITIVE_READ → sensitiveRead, # BULK_WRITE → bulkWrite, CROSS_TENANT_ADMIN → crossTenantAdmin. # 각 row의 annotation: 필드는 아래에서 as-built 표기로 정합됨. capabilities: # source: feature-repository-access-permission-contract — 판정 기준 "Required capability: READ_REPOSITORY" # source: feature-application-port-usecase-contract — "read-only query use case는 readOnly 와 READ_REPOSITORY capability만 선언 가능" - name: READ_REPOSITORY scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(repositoryAccess = READ_REPOSITORY)" semantics: "use case가 read-only repository operation을 호출하는 것을 허용. query use case의 기본 capability. write/sensitive/bulk 작업은 별도 capability 선언이 없으면 forbidden." owner_branch: feature-repository-access-permission-contract bound_to_capability: null threshold: null compatibility_impact: breaking required_test: architecture-enforcement:read-repository-capability # source: feature-repository-access-permission-contract — 판정 기준 "Required capability: WRITE_REPOSITORY" # source: feature-application-port-usecase-contract — "write use case는 transactionMode, idempotency, repositoryAccess를 명시해야 함" - name: WRITE_REPOSITORY scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(repositoryAccess = WRITE_REPOSITORY)" semantics: "use case가 mutating repository operation(insert/update/delete)을 호출하는 것을 허용. 단일/소량 write 기준이며 batch size > 100은 BULK_WRITE 별도 선언 필요. read-only use case에서 이 capability 없이 write repository 접근하면 fail." owner_branch: feature-repository-access-permission-contract bound_to_capability: null threshold: null compatibility_impact: breaking required_test: architecture-enforcement:write-repository-capability # source: feature-repository-access-permission-contract — decisions 2026-05-22 # "SENSITIVE_READ marker = registry-managed metadata table (entity FQN + field name 단위)" - name: SENSITIVE_READ scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(sensitiveRead = true)" semantics: "PII/credential 등 sensitive field를 읽는 use case가 선언해야 하는 capability. marker는 registry-managed metadata table(entity FQN + field name 단위)에서 lookup. domain annotation 또는 JPA entity annotation 형태는 forbidden(domain에 framework 의존 회피). pseudonymized data read는 documented 시에만 예외 허용." owner_branch: feature-repository-access-permission-contract bound_to_capability: null threshold: null compatibility_impact: breaking required_test: architecture-enforcement:sensitive-read-capability # source: feature-repository-access-permission-contract — decisions 2026-05-22 # "BULK_WRITE threshold = N > 100 또는 batch size > 100. 미만은 일반 WRITE_REPOSITORY로 충분" - name: BULK_WRITE scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(bulkWrite = true)" semantics: "단일 transaction 내 N > 100 또는 batch size > 100 mutating operation을 수행하는 use case가 선언해야 하는 capability. 이 미만이면 일반 WRITE_REPOSITORY로 충분. lock 점유 시간, pool 영향, retry 비용이 큰 작업을 명시화." owner_branch: feature-repository-access-permission-contract bound_to_capability: WRITE_REPOSITORY threshold: 100 compatibility_impact: breaking required_test: architecture-enforcement:bulk-write-capability # source: feature-repository-access-permission-contract — decisions 2026-05-22 # "TRANSACTION_REQUIRED는 application-port branch의 TransactionPort contract와 연결되어야 하며 Spring @Transactional 직접 import로 충족하지 않음" # source: feature-application-port-usecase-contract — TransactionPort Contract - name: TRANSACTION_REQUIRED scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(transactionMode = WRITE | READ_ONLY | REQUIRES_NEW)" semantics: "use case가 TransactionPort(또는 TransactionalUseCaseRunner)를 통해 transactional boundary를 갖는 것을 강제. Spring @Transactional의 application package 직접 import는 forbidden. infrastructure가 Spring transaction implementation을 제공하고 application은 port만 호출." owner_branch: feature-repository-access-permission-contract bound_to_capability: null threshold: null compatibility_impact: breaking required_test: architecture-enforcement:transaction-required-capability # source: feature-repository-access-permission-contract — decisions 2026-05-22 # "EXTERNAL_OUTBOUND_ALLOWED 분류 = outbox row INSERT는 in-process(불요), polling publisher의 broker publish는 outbound(필요)" # source: feature-application-port-usecase-contract — "outbound adapter 호출 use case에 EXTERNAL_OUTBOUND_ALLOWED가 없으면 실패" - name: EXTERNAL_OUTBOUND_ALLOWED scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(externalOutboundAllowed = true)" semantics: "use case가 외부 HTTP/message broker로 outbound 호출을 발생시키는 것을 허용. outbox claim 분류: outbox row INSERT는 in-process이므로 본 capability 불요. polling publisher의 broker publish는 outbound이므로 필요. domain event without transport detail은 outbound 호출이 아니므로 별도 분류." owner_branch: feature-repository-access-permission-contract bound_to_capability: null threshold: null compatibility_impact: breaking required_test: architecture-enforcement:external-outbound-capability # source: feature-repository-access-permission-contract — decisions 2026-05-22 # "CROSS_TENANT_ADMIN capability를 capability vocabulary에 추가 (tenant branch feature-tenant-context-policy와 cross-link)" - name: CROSS_TENANT_ADMIN scope: use_case_method enforcement: archunit annotation: "@UseCaseCapability(crossTenantAdmin = true)" semantics: "tenant 경계를 넘어 데이터에 접근/변경하는 admin use case가 선언해야 하는 capability. tenant-context-policy의 cross-tenant 정책과 cross-link되어야 하며, 단일 tenant 범위 use case에서 이 capability를 선언하면 review에서 reject. SENSITIVE_READ가 동반될 가능성이 높지만 자동 결합은 아님." owner_branch: feature-repository-access-permission-contract bound_to_capability: null threshold: null compatibility_impact: breaking required_test: architecture-enforcement:cross-tenant-admin-capability # Row count verification # - feature-repository-access-permission-contract 판정 기준 "Required capability" 표에 명시된 7개: # READ_REPOSITORY, WRITE_REPOSITORY, SENSITIVE_READ, BULK_WRITE, TRANSACTION_REQUIRED, # EXTERNAL_OUTBOUND_ALLOWED, CROSS_TENANT_ADMIN. # - source에 명시되지 않은 capability는 본 registry에 추가하지 않음 (추측 금지).