콘텐츠로 이동

위험 분류 (자동 실행 vs 사람 승인 vs 차단)

리스크 분류 테이블 (architecture.instructions.md § 컨트롤 루프) 은 모든 후보 액션의 기준선을 auto, hil, deny 중 하나로 분류합니다. 통합 RiskGate는 6-axis 상한을 적용해 최종 결과를 shadow까지 낮출 수 있습니다. 이 문서는 기준선 분류 규칙의 진실 원본입니다: 형상, 초기 규칙 테이블, 소유권, 업데이트 프로세스. security-and-identity-ko.md의 P0 열림 결정 “Risk-classification 정책 (auto vs 사람 승인) and initial 정책 승인자”를 해결합니다.

고객-비종속: 아래 모든 값(비용 임계, 태그 키, 리소스 그룹 이름)은 상류의 기본값 입니다; 포크가 구성으로 튜닝합니다 (generic-scope.instructions.md).

영역상태근거참고
테이블 로드, 순서 및 first-match 평가implementedrisk_table.py, test_risk_table.py로더가 카탈로그를 검증하고 순서가 지정된 fail-closed 결정 테이블을 집중 검사에서 적용합니다.
특성 추출 및 환경 분류implementedfeature.py, test_control_loop_authority.py타입이 지정된 특성을 추출하며, 환경 태그가 없거나 알 수 없으면 프로덕션 위험으로 분류합니다.
통합 권한 판정 및 권한을 높이지 않는 상한implementedauthority.py, test_authority.py테이블 기준선과 컨텍스트 상한을 권한이 높아지지 않도록 결합합니다.
기존 control-loop 감사 변환 결과implemented_helpers.py, test_control_loop_authority.py감사 데이터에는 매칭된 규칙, 최종 판정, 정족수 및 해석된 상한이 포함됩니다.
승인 및 변경 거버넌스 적용in-progresscheck-risk-table-change.py, test_check_risk_table_change.py, 변경 프로세스, CODEOWNERS커밋 게이트가 계약의 메타데이터 절반을 적용합니다. 엄격히 증가하는 버전, 변하지 않는 Owner 계층 소유권, 모든 규칙의 서면 정당화, 마지막에 남는 fail-close 기본값입니다. 또한 변경 방향을 분류하므로 완화 편집은 patch bump 뒤에 숨을 수 없습니다. 2인 정족수와 Owner 계층 검토 절반은 배포 포크의 branch protection이므로 로컬 체크아웃에서는 증명되지 않은 상태로 남습니다.
재현에 충분한 특성 및 카탈로그 메타데이터implementedauthority.py, test_authority.py권한 감사 페이로드가 정확한 특성 벡터와 위험 테이블 카탈로그 버전을 직렬화하며, 테이블이 바뀐 뒤에도 기록된 페이로드를 자신의 카탈로그 버전으로 재현하는 집중 검사가 있습니다.
날짜상태변경근거남은 작업
2026-08-13in-progress이전 전달 이력을 재구성하지 않고 근거 범위 안에서 구현 원장을 도입했습니다.current change; 범위 테이블에 나열된 현재 소스 및 집중 검사; 위험 관련 집중 검사 113건과 준비 상태 조정기 검사 33건이 통과했습니다.거버넌스 적용을 증명하고, 재현에 충분한 메타데이터를 추가하며, 관리되는 런타임 근거를 보존해야 합니다.
2026-08-14implemented정확한 특성 벡터와 위험 테이블 카탈로그 버전을 권한 감사 페이로드에 직렬화하여, 과거 판정이 자신을 분류한 리비전으로 재현되도록 했습니다.current change; authority.py, test_authority.py; 권한, 평가기 및 control-loop 권한 집중 검사 43건이 통과했습니다.거버넌스 적용을 증명하고 관리되는 런타임 증적을 보존해야 합니다.
2026-08-14implemented나머지 상한 입력인 역할, 그래프 영향 개수, live probe 관측값, 두 개의 안전 플래그를 같은 감사 페이로드에 추가해, 재현이 probe를 다시 조회하거나 제어 평면 상태를 다시 읽지 않고도 6축 상한을 재구성하도록 했습니다.current change; authority.py, test_authority.py; 안전성 검토, runbook, workflow, skills 및 control-loop 권한 집중 검사 438건이 통과했습니다.거버넌스 적용을 증명하고 관리되는 런타임 증적을 보존해야 합니다.
2026-08-14in-progress변경 계약의 메타데이터 절반을 커밋 게이트로 적용하고, 완화 편집을 버전 문자열에서 드러나게 했습니다.current change; check-risk-table-change.py, test_check_risk_table_change.py; 집중 게이트 검사 26건이 통과했고, 배포된 테이블에 대해 변경 없음, bump 없는 완화, patch bump 완화, minor bump 완화 경우를 실행해 확인했습니다.승인 정족수와 Owner 계층 검토는 배포 포크의 branch protection으로 남으며, 관리되는 런타임 증적을 보존해야 합니다.
  • 커밋 게이트가 모든 위험 테이블 변경에 메타데이터 계약을 적용합니다. 증가하는 버전, 변하지 않는 소유 그룹, 규칙별 서면 정당화, 마지막에 남는 단일 fail-close 기본값이며, patch 버전만 bump한 완화 변경은 거부합니다.
  • 2인 승인 정족수와 완화 변경에 대한 Owner 계층 검토를 증명합니다. 해당 근거는 이 저장소가 아니라 배포의 branch protection에 있습니다.
  • 권한 감사 페이로드가 정확한 특성 벡터와 카탈로그 버전을 직렬화하며, 테이블을 강화하는 변경 뒤에도 기록된 페이로드를 자신의 버전으로 재현하는 집중 검사가 있습니다.
  • 범위 행을 validated로 높이기 전에 하나의 고정된 리비전에서 위험 판정의 관리되는 런타임 증적을 보존합니다.
  • 런타임 경로: rule-catalog/risk-classification.yaml - catalog-as-code, 규칙/할당/예외/ 오버라이드처럼 PR로 리뷰. 저장소 CODEOWNERS는 GitHub fdai-owners team을 지정합니다. aw-approvers 2인 정족수는 배포의 가지 protection/CI가 적용하는 거버넌스 계약입니다 (user-rbac-and-identity-ko.md § 5.1).
  • 정책 소유자: aw-owners Entra 보안 그룹. 소유권은 Owner-티어에 있음 - 테이블이 전체 자율성 표면을 게이팅.
  • 평가: first-match wins. 규칙은 가장 엄격(deny)부터 가장 관대(auto)로 정렬; 어느 규칙과도 매칭되지 않는 케이스는 default: hil fail-close 엔트리로 fall through.

Execution-Model 6-axis 상한 과의 관계

섹션 제목: “Execution-Model 6-axis 상한 과의 관계”

이 테이블이 권위적 기준선 결정입니다. 통합 RiskGate (execution-model.md)는 이 테이블을 risk_table 축 (축 A)로 평가한 뒤 그 결과와 6개 ActionType-컨텍스트 상한 축 (계층, ActionType 상한, static 영향, 실제 운영 영향, 역할, env)의 min() 을 취합니다. 6-axis 상한은 오직 자율성을 더 낮출뿐, 이 테이블이 내린 결정을 재정의 하거나 raise 하지 않습니다. 발견된 문제-수준 데이터가 필요한 신호 - cost_impact_monthly, destructive, irreversible (그 quorum: 2 포함), data_plane_touched, verifier_confidence - 는 여기서만 평가되며 상한 축은 의도적으로 이들을 재도출하지 않습니다. 두 개의 결정 엔진이 있는 것이 아니라: 이 테이블 + 그 위에 계층 된 절대-raise-안-하는 상한 입니다.

상시 권한은 hil 기준 판정을 auto로 높이거나 매칭된 규칙을 변경하지 않습니다. 대신 정확한 A3-E 경계가 계속 유효하고 에스컬레이션 기한이 지난 후 사람이 미리 작성한 Approval을 제공합니다. Thor는 승인된 사람 승인 작업을 실행할 수 있으며 감사에는 원래 위험 규칙, 승인 ID, 상시 권한 ID 및 권한 등급이 유지됩니다. 해당 Approval 없이 침묵만 발생하면 no-op으로 종료됩니다. 에스컬레이션 및 상시 권한을 참조하세요.

리스크 게이트는 이미 가지고 있는 온톨로지 신호로부터 모든 후보 액션에 대해 특성 벡터 를 구성합니다 (llm-strategy-ko.md § Rule-to-Decision 조회 파이프라인). 새로운 데이터 수집은 도입되지 않습니다.

차원타입소스
policy_violationboolOPA/Rego 검증기 판정
destructivebool온톨로지 ActionType.operation ∈ {delete, drop, purge, detach}
irreversiblebool온톨로지 ActionType.irreversible == true (롤백된 상태가 액션 이전 상태를 완전 복원 불가)
blast_radiusenum resource | resource_group | subscriptionapplies_to × 영향받은 리소스의 스코프; ActionType.blast_radius.computation == graph_derived 일 때 안전성 검토가 Resource→Resource 링크(기본 contains + 역방향 depends_on, 깊이 2)를 walk 해서 영향받는 리소스 개수를 버킷으로 매핑
rollback_pathenum pr_revert | scripted | pitr | snapshot_restore | state_forward_onlyremediates 액션의 롤백 계약 (none은 유효 값 아님 - 모든 ActionType이 undo 경로를 선언)
reversibleboolirreversible == false의 지름길
environmentenum prod | non-prod환경 Detection 참조
data_plane_touchedbool온톨로지 ActionType.interfacesDataPlaneMutating 포함
graph_staleboolActionType.interfacesRequiresInventoryFresh 포함 AND 대상 Resource의 인벤토리 레코드가 freshness_ttl 초과
cross_resource_impactintActionType.blast_radius.computation == graph_derived ⇒ 탐색이 반환한 영향받는 Resource 개수; GraphTraversalRequired 없고 그래프 또한 없으면 unknown
cost_impact_monthlynumber (USD/월)규칙의 remediation.cost_impact_monthly_usd 추정, 또는 관찰된 사후 정산
verifier_confidencenumber [0..1]LLM quality-gate 신호 (T2 생산 액션에만 설정)

차원은 엄격하게 타입 지정; 알려지지 않은 키를 참조하는 규칙은 CI 로드에서 실패합니다.

# rule-catalog/risk-classification.yaml (상류 기본; 포크는 임계값 튜닝 가능)
version: 1.0.0
owner_group: aw-owners
rules:
# ── DENY (절대 실행 안 함) ──
- id: deny-policy-violation
if: { policy_violation: true }
decision: deny
reason: "policy-as-code verifier rejected the action"
- id: deny-subscription-blast
if: { blast_radius: subscription }
decision: deny
reason: "no autonomous change spans a full subscription"
- id: deny-graph-stale
if: { graph_stale: true }
decision: deny
reason: "inventory graph is stale; refuse to act on a possibly-ghost resource"
# ── HIL (사람 승인 필요) ──
- id: hil-irreversible
if: { irreversible: true }
decision: hil
reason: "irreversible mutation always requires an approver quorum >= 2"
quorum: 2
- id: hil-destructive
if: { destructive: true }
decision: hil
reason: "delete/drop/purge/detach always requires an approver"
- id: hil-prod
if: { environment: prod, allowlist_prod_auto: false }
decision: hil
reason: "prod defaults to HIL unless the rule is on the prod-auto allowlist"
- id: hil-data-plane
if: { data_plane_touched: true }
decision: hil
reason: "data-plane mutations always require an approver"
- id: hil-cost
if: { cost_impact_monthly: '>= 100' }
decision: hil
reason: "cost impact above the auto threshold"
- id: hil-resource-group-blast
if: { blast_radius: resource_group }
decision: hil
reason: "RG-wide changes require an approver"
- id: hil-low-confidence
if: { verifier_confidence: '< 0.85' }
decision: hil
reason: "T2 quality-gate confidence below auto threshold"
# ── AUTO (승인 없이 실행) ──
- id: auto-low-risk
if:
all:
- reversible: true
- blast_radius: resource
- cost_impact_monthly: '< 100'
- data_plane_touched: false
decision: auto
reason: "reversible, resource-scoped, low cost, control-plane only"
# ── FAIL-CLOSE ──
- id: default-hil
default: hil
reason: "no matching rule - fail toward safety"

규칙 순서 (MUST): deny 규칙이 먼저, 다음 hil, 다음 auto, 다음 default: hil catch-all. First-match wins이므로 가장 엄격한 적용 가능한 규칙이 지배합니다. CI가 순서를 검증(거부가 사람 승인보다 앞, 사람 승인이 auto보다 앞)하고 선행 광범위 규칙에 의해 dead-code가 될 수 있는 규칙을 거부합니다.

이 섹션은 전체 컨트롤 플레인에 대한 단일 권위적 환경 classifier 입니다. execution-model.md (env 축, ActionType.prod_downgrade.detection_ref 경유)와 action-ontology.md (env_scope) 모두 이 규칙을 통해 “prod” vs “non-prod”를 해석 하며, 두 번째 정의를 통하지 않습니다.

environment: prod vs non-prod는 대상 리소스 그룹 태그 에서 파생됩니다:

  • 정본 태그 키: Terraform base tag 집합이 기록하는 fdai:env.
  • 호환성 키: namespaced tag 이전 리소스를 위해 environmentEnvironment도 수락합니다. 둘 다 있으면 fdai:env가 우선합니다.
  • 값: prod / productionprod; non-prod / dev / test / staging / qanon-prod
  • 누락 또는 인식되지 않은 태그 → prod (fail-safe: 알려지지 않은 환경은 최고 리스크 카테고리로 취급)

강제: Azure Policy 할당이 fdai:env 태그 없이 리소스 그룹 생성을 거부해야 하며, 그래서 거버넌스된 환경에서는 fail-safe 경로가 절대 적용되지 않습니다. 정책 할당은 phase-1-rule-catalog-t0-ko.md의 단계 1 산출물입니다.

환경 승격(환경 승격, 핸드오프 대상)

섹션 제목: “환경 승격(환경 승격, 핸드오프 대상)”

위의 binary prod / non-prod 축은 권위 있는 런타임 분류기입니다. dev-to-ops 핸드오프 게이트(operational-readiness.md)는 런타임 축이 싣지 않는 한 가지가 필요합니다: 방향(direction). 그것은 ownership_transfer 신호 의 대상(대상) 환경 를 읽고, 그 이전이 prod 를 향한 승격인지로 게이트 합니다.

단일 정의를 유지하기 위해, 수명 주기 단계는 분류기가 이미 인식하는 정확한 태그 값에 대한 순서(정렬) 입니다 - 새 태그 없음, second classifier 없음:

dev < test < staging < qa < prod

  • dev, test, staging, qa 단계는 모두 런타임 축에서 non-prod 로 해석 됩니다; 순서는 핸드오프 시점에 “대상 단계가 prod 인가” 만 답하는 데 사용됩니다.
  • 대상 단계가 prod 인 이전은 운영 으로의 승격입니다: ORR 은 활성 프로파일 기본값과 무관하게 어떤 critical 발견 사항 도 blocking 으로 취급하며, prod_downgrade 와 동일한 fail-safe 자세 를 재사용합니다(downgrade 는 절대 자율성 를 올리지 않음).
  • 누락 또는 인식되지 않은 대상 단계는 prod 로 해석 됩니다(환경 Detection 과 동일한 fail-safe). 따라서 태그 없는 핸드오프는 가장 엄격한 수준에서 게이트 됩니다.
  • 순서는 절대 자율성 를 넓히지 않습니다: 더 낮은 대상 단계가 런타임 축이 게이트 했을 auto 경로를 unlock 하지 않습니다.

순서는 ORR 게이트만 consume 하는 문서 수준 계약입니다; risk-classification.yaml 에 런타임 축을 추가하지 않습니다. 런타임 리스크 테이블은 여전히 environment: prod | non-prod 만 봅니다.

  • Auto 상한: 액션당 $100 / 월.
  • 근거: 큰 폐기를 승인하지 않으면서 작은 right-sizing / stop-idle / tier-adjust 교정을 커버. 단계 1 관찰 모드 측정을 위해 보수적으로 선택; 임계값은 구성 값이며 측정 후 거버넌스 PR로 조정 가능.
  • 추정은 규칙의 remediation.cost_impact_monthly_usd 필드에서; 규칙이 추정 못 하면 값은 unknown>= 100으로 취급 → 사람 승인.

극소수의 매우 낮은 리스크 규칙은 prod에서 auto 자격 표시될 수 있음(allowlist_prod_auto: true). 초기 허용 목록 후보 (승격 전 관찰 모드에서 평가):

  • 태그 교정 (누락된 소유자 / cost-center / 환경 태그 추가).
  • 미부착 공개 IP 주소 해제.
  • 데이터 평면 노출 없는 리소스의 NSG allow-any-source 규칙 제거.

모든 허용 목록 엔트리는 별도 승격된 할당 이며 표준 관찰 모드 → 강제 적용 게이트를 통과합니다 (architecture.instructions.md § 관찰 모드 → 강제 적용 승격). 허용 목록은 bypass가 아니라 prod 기본의 명시적 선택 감소입니다.

리스크 테이블 업데이트는 표준 거버넌스 PR 흐름을 따릅니다:

  • 모든 변경정족수 of 2 aw-approvers와 PR 본문의 Justification: 블록 필요.
  • 완화 변경 (auto 확대, 비용 임계 상승, 거부 제거)은 정족수에 Owner-티어 리뷰어(aw-owners 멤버) 필요.
  • 강화 변경 (거부 추가, 비용 임계 하락, auto→사람 승인 이동)은 일반 정족수로 머지 가능 - 안전-측 변경은 Owner 승인이 필요 없음.
  • 테이블 버전은 모든 변경에 bump되고 카탈로그 버전에 캡처되어, 어떤 과거 액션을 분류한 리스크 결정도 재구성 가능 (llm-strategy-ko.md § 서명 조립).

승인 정족수는 branch protection에 있어 로컬 체크아웃에서 읽을 수 없으므로, check-risk-table-change.py는 차이(diff)로 판정되는 절반만 적용합니다. 테이블을 건드리는 모든 커밋에서 다음을 요구합니다:

  • 엄격히 증가하는 MAJOR.MINOR.PATCH 버전. 그래야 어떤 변경도 자신이 대체한 리비전의 버전을 달고 감사 페이로드에 도달하지 않습니다.
  • 변하지 않는 owner_group. 테이블의 영향 범위가 요구하는 Owner 계층에서 소유권을 조용히 옮기는 테이블 편집을 막습니다.
  • 모든 규칙의 비어 있지 않은 reason. PR Justification: 블록의 파일 내 절반입니다.
  • 고유한 규칙 id, 정확히 하나의 fail-close default, 그리고 그 기본값이 마지막에 위치. 기본값이 위로 흘러가면 어떤 규칙도 매치하지 않은 경우를 더 이상 잡지 못합니다.
  • 완화 변경에는 최소 minor 버전 bump. 재현된 감사 기록이 보여주는 것은 카탈로그 버전뿐이므로, patch bump 뒤에 숨은 완화는 몇 달 뒤 오타 수정과 구분되지 않습니다.

방향 분류는 fail-closed입니다. 판정 확대, 가드레일 규칙 제거, 정족수 하향, 매치 조건 편집, 규칙 재정렬은 모두 완화로 셉니다. first-match 평가에서는 게이트가 그중 어느 것도 테이블을 좁힌다고 증명할 수 없기 때문입니다. 증명 가능한 안전-측 편집만 강화로 보고되므로, 알아보지 못한 편집 형태는 검토 기준을 낮추는 대신 높입니다. 게이트는 리뷰어 정족수나 Owner 계층 리뷰어를 확인했다고 주장하지 않으며, 해당 변경에 무엇이 필요한지를 출력합니다.

현재 control-loop 감사 엔트리는 다음을 기록합니다:

  • 매칭된 규칙 id (fail-through 시 default-hil).
  • 최종 결정 (auto / hil / shadow / deny)과 정족수.
  • 최종 결정에 기여한 모든 축을 담은 resolved_ceiling.
  • 해당 액션을 분류한 risk-classification.yaml 리비전의 catalog_version.
  • 설정되지 않은 차원까지 포함한 feature_vector 스냅샷. 신호가 없었던 것인지 누락된 것인지 구분할 수 있습니다.
  • ceiling_inputs 블록: 해석된 역할, 그래프 기반 영향 개수, 기록된 live probe 관측값과 연속 실패 횟수, 그리고 system_degradedkill_switch_engaged 안전 플래그.

마지막 세 항목이 재현을 자기완결적으로 만듭니다. 기록된 페이로드는 자신이 명시한 테이블 버전과 자신이 담은 입력으로 다시 평가되므로, 이후 카탈로그 변경이 과거 판정을 조용히 바꿔 쓸 수 없고 재현이 live probe를 다시 조회하지도 않습니다.

향후 회고에서 매칭 규칙 id로 감사 로그를 필터링하여 과도하게 트리거된 규칙(예: “모든 prod 변경이 사람 승인 - 모든 것이 Rule 5에 걸림”)을 식별하고, 같은 거버넌스 PR 흐름을 통해 개선을 제안할 수 있습니다.

  • 향후 차원으로 time_of_day 게이트(업무 시간 vs 비업무 시간)를 추가할지 - 관찰 모드 측정이 실제 필요를 보일 때까지 연기.
  • 결정론적 규칙 테이블에 더해 숫자 risk_score를 계산할지 (동점에서만 또는 tie-breaker 로만 작동 - 결정론 테이블이 여전히 권위).
  • 포크 오버라이드 정책: 포크가 상류 기본을 완화 (예: 비용 임계 상승)할 수 있는가, 아니면 강화만 가능한가? 권장 기본: 강화는 무료, 완화는 감사된 Owner 재정의 필요.