Security Fix: - Update v1_ledger.py to require trade_write permission instead of read - Fix authentication dependency from require_read to require_trade_write - Ensure trade operations cannot be performed with read-only service tokens Test Coverage: - Add test_v1_ledger_trade_requires_trade_write_permission() to verify permission boundary - Confirm read-only tokens are rejected with 403 Forbidden status - Validate repository methods are not called on permission failure Documentation: - Add new Discovery dcy-005 for production admin bootstrap and operator access - Update docs/discovery/index.md with dcy-005 entry - Update release rel-001 with additional verification notes and issue references
18 KiB
0. 문서 상태
이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.
- 상태: draft
- 문서 ID: dcy-005_20260511_production-admin-bootstrap-and-operator-access
- 이슈명: 실배포 admin bootstrap 및 operator access 경로 정립
- 작성 시각(KST): 2026-05-11 23:12
- 마지막 갱신 시각(KST): 2026-05-11 23:12
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조: 없음
1. 계획 상태 요약
현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.
- 연계 문서 현황:
- 관련 점수 파일: 미생성
- 관련 TODO/메모: docs/releases/rel-001_20260502_trex-basic-v1-api-contract.md
- 해석:
- REL-001 실배포 smoke에서 public health와 read service-token 경로는 확인됐지만, admin 성공 경로와 trade-write 성공 경로를 완료할 운영 접근 방법이 저장소 문서에 정의돼 있지 않다.
- 이번 Discovery는 활성 release 검증을 막는 운영 문제를 별도 주기로 분리해, 실배포 admin bootstrap, operator auth path, smoke credential provenance, 로그 접근 절차를 독립적으로 정리하기 위한 초안이다.
2. 요구사항 판정 결과
이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.
- 판정: 신규
- 근거
- 기존 dcy-001~004는 DB 검증, trex-basic consumer API, CLI
portfolio list --user, portfolio UUID 전환을 다루며, 실배포 admin bootstrap 및 operator access를 독립 주제로 다루는 Discovery는 없다. - 이번 요청은 제품 기능 추가보다 운영 인증 경로, bootstrap 계정/토큰 provenance, release smoke credential 관리라는 별도 문제 정의를 가진다.
- 기존 dcy-001~004는 DB 검증, trex-basic consumer API, CLI
판정이
완전 중복인 경우: 이하 섹션 작성을 중단하고# 9. 파일 처리 결과에 중복 판정 사유와 참조 문서 경로를 기록한 뒤 문서를 닫는다. REQ 초안 작성으로 넘기지 않는다.
3. 문제점의 요약
문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.
- 현재 상태
- 실배포 URL
https://fourblocks2026.com/portfolio-hub/에서GET /health,/docs,/openapi.json은 정상 응답했고, read service-token으로GET /v1/assets,GET /v1/user_info까지는 검증됐다. - 동일 토큰으로
POST /auth/service-tokens를 호출하면403 Insufficient permission이 반환됐다. 현재 저장소에는 실배포에서 어떤 경로로 admin auth context를 확보하는지, admin 성공 경로를 어떻게 검증하는지 정리한 runbook이 없다. app/core/auth.py는 env token 집합 또는 DBauth_tokensprincipal의permission으로 권한을 해석하고,app/api/auth_routes.py의POST /auth/service-tokens는require_admin을 선행한다. 즉 운영자가 어떤 credential을 admin으로 다뤄야 하는지가 명확해야 smoke가 가능하다.README.md와app/core/config.py에는 first-run bootstrap 계정 환경 변수(PORTFOLIOHUB_BOOTSTRAP_*)가 있으나, 실배포의 steady-state admin access, smoke용 read/trade-write/admin token 분리, startup/request 로그 접근 경로는 문서화돼 있지 않다.
- 실배포 URL
- 기대 상태
- 운영자는 실배포에서 admin auth context를 얻는 표준 경로를 알고 있어야 하며, 그 경로로
POST /auth/service-tokens성공 smoke를 반복 가능하게 수행할 수 있어야 한다. - release 검증에는 public/no-auth, read service-token, trade-write service-token, admin auth context의 용도와 provenance가 문서로 분리돼 있어야 한다.
- startup log, request log, auth failure(401), permission failure(403), resource failure(404)를 운영자가 구분해 증거로 남길 수 있어야 한다.
- 운영자는 실배포에서 admin auth context를 얻는 표준 경로를 알고 있어야 하며, 그 경로로
- 이해관계자
- repository-maintainers
- 실배포 운영자 / 배포 승인자
- trex-basic 연동 운영자
- 보안 또는 secret 관리 담당자
- 제약사항
- 실제 credential 원문은 저장소, release 문서, Discovery 문서에 기록하지 않는다.
- 기존 auth model(
read,trade-write,admin권한과 DB-issued service-token 구조)은 유지하되, 필요한 경우 bootstrap/runbook 또는 최소한의 운영 지원 기능만 추가한다. - 활성 release(REL-001)와 병렬로 진행되므로, 이 Discovery는 운영 접근성과 검증 절차를 정리하는 데 집중하고 기존 consumer contract 범위를 임의로 확장하지 않는다.
주요 사용자 시나리오
사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.
- 운영자가 REL-001 배포 후 smoke를 수행할 때, admin 경로로 service token을 발급하고 read/trade-write 토큰을 분리해
/auth/service-tokens,/v1/assets,/v1/user_info,/v1/assets/{asset_id}/ledger/trades를 순서대로 검증한다. - 장애 또는 신규 환경 bootstrap 시 운영자가
PORTFOLIOHUB_BOOTSTRAP_*기반 초기 admin 계정 생성 경로와 steady-state admin recovery 경로를 구분해 사용한다. - release evidence 작성 시 운영자가 raw secret 없이 token provenance, 권한 수준, 로그 접근 경로만 기록해 보안 사고 없이 검증 내역을 남긴다.
4. 이번에 정의할 변경
이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.
- 실배포 admin bootstrap 및 steady-state operator access 경로를 정의한다. bootstrap user, admin login/session, admin token, DB-issued admin service token 중 어떤 경로를 표준으로 쓸지 결정한다.
- release 검증용 credential matrix를 정의한다. public/no-auth, read service-token, trade-write service-token, admin auth context의 용도와 발급/보관/폐기 절차를 분리한다.
- startup/request 로그 접근, auth/permission/resource 오류 판독, release evidence 기록 절차를 운영 runbook과 release 문서에 연결한다.
영향 범위
변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.
- 코드 영향:
app/core/config.py— bootstrap 환경 변수와 운영 환경 가정 재검토app/main.py— bootstrap 초기 사용자 생성 경로의 운영 제약 재정리 필요 여부 검토app/core/auth.py,app/api/auth_routes.py,app/services/auth_service.py— admin/read/trade-write auth path의 운영 의미 문서화 또는 최소 지원 기능 추가 가능성app/cli/commands/*또는 운영 보조 스크립트 — 필요 시 token inspection 또는 smoke helper 추가 검토
- 문서 영향:
README.md— 실배포 bootstrap/admin/operator access runbook 추가 가능성docs/project-structure.md,docs/runtime-flows.md— auth/bootstrap/runtime smoke 흐름 반영 가능성docs/releases/rel-001_20260502_trex-basic-v1-api-contract.md— release evidence와 운영 주의사항 정합화
- 운영 영향:
- secret manager 또는 배포 환경 변수 관리 절차 명시 필요
- release smoke에 필요한 token 수명 주기 및 폐기 절차 정의 필요
- 로그 접근 권한과 증적 수집 절차를 운영자 역할에 연결해야 함
5. 요구사항 목록
실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.
기능 요구사항
- FR-1: 실배포에서 admin auth context를 확보하는 표준 경로를 정의한다. first-run bootstrap과 steady-state 운영 경로를 구분하고, 운영자가 어떤 credential로
POST /auth/service-tokens를 성공시켜야 하는지 명시한다. - FR-2: release 검증에 필요한 credential matrix를 정의한다. public/no-auth, read service-token, trade-write service-token, admin auth context 각각의 발급 주체, 보관 위치, 만료 정책, 폐기 절차를 문서화한다.
- FR-3: REL-001과 같은 app-service release에서 startup log, request log, auth/permission/resource 오류를 수집하는 운영 runbook을 정의한다.
- FR-4: 운영자가 DB 콘솔에 직접 들어가지 않고도 token provenance 또는 권한 수준을 확인할 수 있는 최소 지원 수단이 필요한지 판정하고, 필요 시 구현 또는 문서 경로를 정의한다.
비기능 요구사항
성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.
- NFR-1: raw credential, raw token, bootstrap password는 저장소와 release/discovery 문서에 남기지 않는다. 운영 문서에는 provenance와 마스킹된 메타데이터만 남긴다.
- NFR-2: 운영 runbook은 401, 403, 404의 의미를 분리해 재현 가능하게 설명해야 하며, 권한 문제와 리소스 부재 문제를 혼동하지 않도록 해야 한다.
- NFR-3: bootstrap 또는 recovery 경로는 idempotent해야 하며, 이미 사용자가 존재하는 환경에서 first-run bootstrap 로직이 반복 부작용을 만들지 않아야 한다.
범위 경계
이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.
- In Scope
- 실배포 admin bootstrap/steady-state access 경로 정의
- read/trade-write/admin smoke credential 구분 및 운영 절차 정의
- release evidence용 로그 접근 및 증적 수집 절차 정의
- 필요한 최소 운영 지원 기능 또는 문서 변경 판정
- Out of Scope
- 권한 체계(
read,trade-write,admin) 자체의 전면 재설계 - 외부 사용자를 위한 신규 admin UI 또는 공개 운영 포털 추가
- trex-basic consumer API 스키마 변경
- 권한 체계(
6. 리스크/가정 목록
불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.
리스크
- R-1 (High): admin/bootstrap credential을 ad-hoc 방식으로 공유하면 secret leakage가 발생할 수 있다.
- 완화 방안: secret manager 또는 승인된 보관소만 사용하고, 저장소/문서에는 raw value를 남기지 않는다.
- R-2 (Medium): first-run bootstrap 계정 경로만 정리하고 steady-state 운영 경로를 정의하지 않으면, 이미 사용자가 있는 실배포 환경에서는 같은 문제를 반복한다.
- 완화 방안: bootstrap과 steady-state access/recovery를 별도 요구사항으로 분리해 정의한다.
- R-3 (Medium): 로그 접근 경로가 환경 의존적이면 release 증적 수집이 담당자 개인 지식에 묶인다.
- 완화 방안: 최소한의 환경 계약(예: 어느 시스템에서 startup/request 로그를 확인하는지)을 문서화한다.
가정
아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.
- A-1: 실배포 환경은 DB-backed
users/auth_tokens를 사용하며, service-token은 DB principal 권한으로 해석된다. - A-2: admin 성공 경로는 현재 완전히 없는 것이 아니라, 운영자에게 문서화되지 않았거나 credential provenance가 정리되지 않은 상태다.
- A-3: release 검증에는 최소한 public/no-auth, read service-token, trade-write service-token, admin auth context 4개 관점이 필요하다.
오픈 질문
답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.
- OQ-1: steady-state admin access의 표준 경로는 무엇인가? bootstrap admin 로그인, env admin token, DB-issued admin session/token, 별도 운영 절차 중 무엇을 canonical path로 삼을지.
- 상태: Open
- 처리 방안: 운영자와 승인자가 실제 배포 체계를 확인하고 canonical path를 하나로 선택한다.
- 종료 조건: REL-001 후속 release 검증에 사용할 admin path가 문서화되면 Answered 처리.
- OQ-2: startup/request 로그는 어디에서 확인하는가? 호스팅 환경, reverse proxy, Loki 등 실제 로그 경로와 접근 권한을 어떻게 운영자에게 부여하는가.
- 상태: Open
- 처리 방안: 현재 실배포 로그 스택과 접근 권한 모델을 확인한 뒤 runbook에 반영한다.
- 종료 조건: 실제 로그 수집 절차가 문서에 추가되면 Answered 처리.
- OQ-3: token provenance 확인 수단은 문서화만으로 충분한가, 아니면 최소한의 CLI/관리 기능이 필요한가.
- 상태: Open
- 처리 방안: runbook-only 접근과 지원 기능 추가 비용을 비교해 결정한다.
- 종료 조건: REQ 초안 단계에서 지원 수단이 문서-only인지 구현 포함인지 확정되면 Answered 처리.
오픈 질문 처리 기준
Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.- 처리 원칙 1: 질문만 남기지 말고 반드시
상태,처리 방안,종료 조건을 함께 적는다. - 처리 원칙 2: 답이 나온 질문은 본문 반영 없이 단순 삭제하지 않는다. 반영 위치를 먼저 갱신한다.
- 처리 원칙 3: High 영향 질문은
Deferred처리 후 처리 방안에 REQ 인계 추적 방식을 명시한다.
7. 초기 성공 기준
이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.
- S-1: 운영자가 admin/read/trade-write/public 검증 경로를 혼동 없이 수행할 수 있는 runbook을 보유한다.
- S-2: release 검증 시
POST /auth/service-tokens성공 경로와POST /v1/assets/{asset_id}/ledger/trades권한 경로를 적절한 credential로 재현할 수 있다. - S-3: startup/request 로그 접근 경로와 release evidence 기록 방식이 REL 문서에 반영된다.
측정 방식 및 데이터 출처
각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.
- S-1 측정 방식: 운영 runbook 리뷰 및 smoke rehearsal / 데이터 출처: README.md 또는 신규 운영 문서, release verification 기록
- S-2 측정 방식: 실배포 또는 staging smoke에서 admin/read/trade-write 경로를 각각 실행 / 데이터 출처: release 문서, HTTP 응답 로그, 운영자가 제공한 검증 기록
- S-3 측정 방식: release 문서와 baseline 문서에 로그 접근 및 증적 수집 항목 포함 여부 확인 / 데이터 출처: docs/releases/*.md, docs/runtime-flows.md, docs/project-structure.md
8. REQ로 넘기기 전 확인 체크
REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.
- 범위(In Scope/Out of Scope) 확정
- 기준: admin bootstrap, steady-state access, logging scope의 포함/제외 범위 합의
- 성공 지표의 측정 방식/데이터 출처 확정
- 기준: staging/production 중 어디서 smoke를 수행할지와 evidence 위치 확정
- High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: secret leakage와 admin recovery 책임자 지정
- 모든 오픈 질문(OQ)
Open상태 없음 확인- 기준: OQ 목록의
Open상태가 0개
- 기준: OQ 목록의
- Freeze 확정 담당자(CONFIRMED_BY) 지정
- 기준: 운영 승인자 또는 repository-maintainers 중 확인자 지정
9. 파일 처리 결과
이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.
- 처리 결과: 생성
- 생성 경로: docs/discovery/dcy-005_20260511_production-admin-bootstrap-and-operator-access.md
- 참조 문서:
- docs/releases/rel-001_20260502_trex-basic-v1-api-contract.md
- app/core/auth.py
- app/api/auth_routes.py
- app/services/auth_service.py
- README.md
10. 사용자 결정 필요 항목 요약
사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.
DECIDE
- {{DECIDE_CANONICAL_ADMIN_ACCESS_PATH}}
- {{DECIDE_SMOKE_CREDENTIAL_OWNERSHIP_POLICY}}
CONFIRM
- {{CONFIRM_LOG_ACCESS_CHANNEL}}
- {{CONFIRM_BOOTSTRAP_VS_STEADY_STATE_RECOVERY_SCOPE}}
DATA
- {{DATA_SECRET_STORE_LOCATION}}
- {{DATA_PRODUCTION_LOG_STACK}}
11. Discovery Freeze
REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.
섹션 참조
- 범위: # 5. 요구사항 목록 > 범위 경계
- 리스크/오픈 질문: # 6. 리스크/가정 목록
- 성공 기준: # 7. 초기 성공 기준
- 인계 전 확인: # 8. REQ로 넘기기 전 확인 체크
- 사용자 결정 필요: # 10. 사용자 결정 필요 항목 요약
Freeze 플래그
- Handoff Decision: 보류
- Handoff Rationale: 운영 경로의 핵심 선택지(admin canonical path, 로그 접근, smoke credential provenance)가 아직 Open 상태라 REQ 초안 작성 전 사용자 확인이 필요하다.
- Ready for REQ Drafting: false
- Confirmed By: TBD
- Confirmed At (KST): TBD
12. 작성 가이드
템플릿 사용 시의 기본 규칙을 적는다. 실제 문서를 만들 때는 이 가이드를 기준으로 플레이스홀더를 치환한다.
- 이 파일은 템플릿이다. 실제 문서 작성 시
{{...}}플레이스홀더를 구체 값으로 교체한다. - 필요 없는 항목은 삭제하고, 부족한 항목은 같은 형식으로 추가한다.
- Open Questions는 가정으로 대체하지 말고 그대로 유지한다.
대체됨은 현재 Discovery가 더 이상 기준 문서가 아닐 때 대체 Discovery 경로를 기록하고, 해당 사항이 없으면없음으로 둔다.후속 Discovery 참조는 범위를 이어받는 별도 Discovery가 생성된 경우 그 Discovery 경로를 기록하고, 없으면없음으로 둔다.- Discovery Freeze는 문서 하단에 반드시 유지한다.