12 KiB
12 KiB
SDD: Control Plane 운영 보안·감사 표면
위치
- Milestone: control-plane-security-audit-surface.md
- Phase: PHASE.md
상태
[승인됨]
SDD 잠금
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목:
- [D01] 최소 인증 모델과 권한 역할의 Phase 포함 범위를 operator/admin 단일 역할과 표시 가능한 token reference 기준으로 확정했다.
- [D02] 감사 로그는 운영 action metadata 감사 범위로 두고, Core in-memory/event surface 또는 테스트 가능한 adapter 경계까지만 이번 Milestone 범위로 확정했다.
- [D03] 감사 UI는 운영 판단용 metadata만 노출하고, 로그/아티팩트/토큰류 원문과 민감 error payload는 복제 노출하지 않는 기준으로 확정했다.
문제 / 비목표
- 문제: Control Plane write action 표면은 runner self-update, execution cancel/report/log/artifact 같은 운영 변경을 노출하지만, 현재 설계에는 operator identity, 권한 실패 의미, 감사 흔적의 source of truth, 민감 정보 노출 경계가 고정되어 있지 않다.
- 비목표:
- production identity provider, 조직/테넌트 모델, 장기 secret rotation을 이 Milestone에서 완성하지 않는다.
- durable audit storage 구현을 기본 범위로 확정하지 않는다. file/DB 기반 감사 저장, retention, 삭제 정책은 후속 Milestone으로 분리한다.
- 원격 빌드 로그 원문, artifact 파일 내용, raw log line, production-grade 사용자 로그인 히스토리를 감사 로그 범위에 포함하지 않는다.
- 기존 runner production job 운영 정책 전체를 재설계하지 않는다.
Source of Truth
| 영역 | 기준 | 메모 |
|---|---|---|
| Roadmap | control-plane-security-audit-surface.md | Milestone 상태, 기능 Task, 구현 잠금의 장기 원장이다. |
| Code | services/core/internal/httpserver/routes.go |
Core HTTP write route의 현재 source of truth다. |
| Code | services/core/internal/httpserver/runner_cicd_handlers.go |
runner self-update, execution cancel/report/log/artifact write handler의 현재 검증·상태 변경 기준이다. |
| Code | apps/client/lib/src/app/core_connection_client.dart |
Flutter client가 Core write endpoint를 호출하고 success/deferred/failed로 해석하는 기준이다. |
| Code | packages/flutter/oto_console/lib/src/oto_console_contract.dart |
console config, auth token reference, action draft/result contract의 UI 패키지 기준이다. |
| External Provider | 없음 | 이 SDD는 외부 provider write를 추가하지 않는다. |
| User Decision | D01 | production identity provider는 후속으로 분리하고, operator/admin 단일 역할과 표시 가능한 token reference만 이번 Milestone 기준으로 삼는다. |
| User Decision | D02 | 감사 로그는 operator/runner write action의 actor, action, target, outcome, timestamp, optional reason metadata로 한정하고, durable persistence는 후속 Milestone으로 분리한다. |
| User Decision | D03 | UI에는 action, actor reference, target id, outcome, timestamp, optional reason만 노출하고 token, credential, private URL credential, raw log line, artifact 내용/full path, 민감 error payload는 노출하지 않는다. |
State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|---|---|---|---|
| SDD draft | SDD 문서가 생성되고 사용자 결정 항목이 식별됨 | User review pending | SDD.md, USER_REVIEW.md |
| User review pending | D01-D03이 사용자 답변으로 확정됨 | SDD approved candidate | USER_REVIEW.md 해결 로그 |
| SDD approved candidate | Acceptance Scenario와 Evidence Map이 Milestone 기능 Task와 연결됨 | Plan ready | SDD.md, Milestone 구현 잠금 |
| Operator action requested | UI 또는 adapter가 Core write endpoint를 호출함 | Authorized, rejected, deferred, or failed | core_connection_client.dart, Core HTTP response |
| Authorized action accepted | Core가 기존 상태 검증과 권한 기준을 통과함 | Audit event candidate | runner_cicd_handlers.go, D01 |
| Action rejected or failed | 권한, ownership, invalid input, missing runner/execution, terminal state 등으로 거부됨 | Audit event candidate | Core error response, D01-D03 |
| Audit event candidate | action outcome과 actor/target/reason metadata가 생성됨 | Captured in in-memory/event surface or withheld | D02-D03 |
Interface Contract
- 계약 원문: 없음
- 입력:
actor: operator 또는 runner actor identity. 구체 모델은 D01에서 확정한다.role: write action 허용 여부를 판정할 최소 역할. 구체 범위는 D01에서 확정한다.action:create-job,create-execution,self-update-runner,cancel-execution,report-execution,append-log,append-artifact중 하나.target: runner id, job id, execution id, artifact/log 대상 등 action 대상 식별자.reason: cancel/self-update 같은 operator action에 남길 선택적 사유.request_body: 기존 JSON request body 또는 후속 schema 확장안.
- 출력:
status:accepted,deferred,succeeded,rejected,failed중 UI가 표시할 결과 상태.error_message: 거부 또는 실패 사유. 민감 정보는 D03 기준으로 마스킹한다.audit_event: action, actor, target, outcome, reason, timestamp, request id 후보를 담는 감사 이벤트. 이번 Milestone에서는 Core in-memory/event surface 또는 테스트 가능한 adapter 경계까지만 다룬다.ui_state: disabled, submitting, succeeded, deferred, failed, empty/error state 중 operator가 관찰할 상태.
- UI 노출:
action: 운영 action 이름.actor_reference: operator/admin 또는 runner actor의 표시 가능한 참조값.target_id: runner, job, execution 등 대상 식별자.outcome:accepted,rejected,deferred,failed등 결과.timestamp: action 발생 또는 기록 시각.reason: operator가 입력한 선택적 사유.
- 금지:
- auth token, enrollment token, credential 원문, private release URL credential을 SDD, audit event, UI text, 테스트 fixture에 남기지 않는다.
- execution owner mismatch, terminal state rejection, unknown runner 같은 기존 Core 보호 조건을 우회하지 않는다.
- 원격 빌드 로그 원문, raw log line, artifact 파일 내용, artifact full path를 audit event에 복제하지 않는다.
- 사용자 로그인 히스토리 전체나 production identity provider event를 이번 Milestone의 audit source of truth로 삼지 않는다.
- durable audit persistence 구현을 기본 완료 기준으로 삼지 않는다.
- artifact path, log line, token reference, credential-like error payload 같은 민감 후보를 감사 UI에 그대로 노출하지 않는다.
Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|---|---|---|---|---|
| S01 | security-sdd |
SDD가 필요한 운영 보안·감사 Milestone이고 D01-D03이 미확정이다. | SDD와 사용자 리뷰가 작성된다. | SDD는 잠금 상태로 남고, 사용자 결정 항목은 USER_REVIEW.md에만 분리된다. |
| S02 | security-sdd |
사용자 결정 D01-D03이 해결되었다. | SDD를 갱신하고 gate를 확인한다. | SDD 상태는 [승인됨], SDD 잠금은 해제 후보가 되며, Milestone 잠금 해제 조건을 검증할 수 있다. |
| S03 | auth-scope |
최소 인증 모델과 역할 범위가 확정되어 있다. | Core write endpoint와 Flutter action surface의 권한 허용/거부 흐름을 계획한다. | 기능 Task는 actor, role, unauthorized/forbidden UX, disabled/error 상태의 검증 기준을 포함한다. |
| S04 | audit-scope |
감사 저장 책임과 UI 노출/마스킹 기준이 확정되어 있다. | action outcome을 감사 이벤트 후보와 UI 표면으로 계획한다. | 기능 Task는 event field, in-memory/event surface boundary, masking rule, durable persistence 후속 분리 여부의 검증 기준을 포함한다. |
Evidence Map
| Scenario | Required Evidence | agent-task 연결 |
Spec Completion 기대 |
|---|---|---|---|
| S01 | SDD.md 생성, USER_REVIEW.md 생성, Milestone Task id 매핑 확인 |
agent-task/m-control-plane-security-audit-surface/... |
security-sdd: SDD 초안과 사용자 리뷰 파일이 생성되어 잠금 사유가 명확하다. |
| S02 | 해결된 user_review_N.log, 갱신된 SDD 상태/잠금, check-gate 결과 |
agent-task/m-control-plane-security-audit-surface/... |
security-sdd: D01-D03 답변이 SDD에 반영되고 gate가 pass 또는 남은 차단 항목을 보고한다. |
| S03 | Core handler/route 테스트 또는 adapter/widget 테스트, 권한 실패 UI 확인, 민감 정보 미노출 검색 | agent-task/m-control-plane-security-audit-surface/... |
auth-scope: 권한 허용/거부 및 disabled/error 상태가 코드와 테스트 근거로 검증된다. |
| S04 | audit event field 검증, storage boundary 검증, UI masking/widget 테스트 또는 문자열 검색 | agent-task/m-control-plane-security-audit-surface/... |
audit-scope: 감사 이벤트 범위와 마스킹 기준이 구현·테스트·검색 근거로 검증된다. |
Cross-repo Dependencies
- 없음
Drift Check
- Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- Evidence Map이 plan/code-review/complete.log에서 검증 가능하다.
- agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- 사용자 리뷰가 필요한 항목은
USER_REVIEW.md에 분리했고 해결 로그로 이동한다.
사용자 리뷰 이력
- D01: 추천안 승인. 이번 Milestone은 production identity provider를 붙이지 않고, operator/admin 단일 역할과
OtoConsoleConfig.authTokenReference기반의 표시 가능한 token reference만 기준으로 설계한다. - D02: 추천안 승인. 감사 로그는 원격 빌드 로그 원문이나 production 로그인 히스토리가 아니라, Control Plane write action의 actor/action/target/outcome/timestamp/optional reason metadata로 한정하고 Core in-memory/event surface 또는 테스트 가능한 adapter 경계까지만 이번 Milestone 범위로 둔다.
- D03: 추천안 승인. 감사 UI는 운영 판단에 필요한 action, actor reference, target id, outcome, timestamp, optional reason만 보여주고, 로그/아티팩트/토큰류 원문과 민감 error payload는 복제 노출하지 않는다.
작업 컨텍스트
- 표준선: 기존 Core HTTP route와 Flutter action result contract를 우선 source of truth로 삼고, API/schema 확장은 D01-D03 결정 이후 필요한 최소 범위로만 분리한다.
- 표준선:
OtoConsoleConfig.authTokenReference는 표시 가능한 reference로만 취급하고 token 원문은 UI, 감사 이벤트, 문서, 테스트 fixture에 남기지 않는다. - 표준선: 원격 빌드 로그 원문과 artifact 내용은 기존 execution log/artifact 도메인의 데이터이며, audit event에는 append/report 같은 action metadata만 남긴다.
- 표준선: 감사 UI는 운영 판단용 metadata만 보여주며, credential-like substring과 민감 후보 payload는 마스킹 또는 비노출 대상으로 둔다.
- 후속 SDD: durable audit storage가 필요해지면 별도 persistence/schema SDD 또는 후속 Milestone으로 분리한다.