Files
clean-architecture-backend-…/docs/registries/capabilities.yaml
T

121 lines
8.1 KiB
YAML

# 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에 추가하지 않음 (추측 금지).