# req-048: per-instance TOML 설정 로더 + `--config` 필수 - Status: Implemented - Type: Configuration - Priority: High - Owner: project maintainers ## Intent 다중 인스턴스 운영을 위해 인스턴스별 TOML 설정 파일을 도입한다. 데몬 기동 시 `--config .toml` 인자를 **필수**로 받고, TOML 에서 `instance_key` 와 `portfolio_hub_token` 을 읽는다. 이 두 값은 `.env` 에 넣지 않는 것을 원칙으로 하며(민감값 분리), 기존 `DaemonConfig.from_env()` 와 병합해 최종 설정을 구성한다(dcy-009 FR-1, NFR-4, OQ-2/A-5). ## Requirement - `config.py` 에 `DaemonInstanceConfig` dataclass(`instance_key: str`, `portfolio_hub_token: str`)와 `from_toml(path)` 로더를 추가한다(stdlib `tomllib` 사용). - `DaemonConfig` 구성 시 `--config .toml` 의 TOML 값을 `from_env()` 결과와 병합하는 팩토리(예: `from_config(toml_path)`)를 추가한다. `portfolio_hub_token` 은 TOML 값을 사용해 `PortfolioHubConfig.token` 에 주입한다. - 데몬 기동 진입점은 `--config` 를 **필수 인자**로 받는다. 인자 없이 기동하면 오류 메시지를 출력하고 비정상 종료(exit code ≠ 0)한다. 기본값 fallback 없음(OQ-2 Answered). - (CHG-20260609-01, trex-orb-v1 정합) `--config` 는 **이름**으로 받고 `--config-path `(기본 `./config`)로 config 디렉터리를 분리한다. `resolve_config_toml(name, config_path)` 가 `/.toml` 로 해석하며 `.toml` 을 자동 부착한다. **하위호환**: 슬래시 포함(경로형) `--config` 값은 명시 경로로 그대로 사용한다. 운영자 CLI(`trex-core`)도 `--config-path` 를 동일 규칙으로 수용한다. - `instance_key` 와 `portfolio_hub_token` 은 `.env`/OS env 에서 읽지 않는다. TOML 미존재/필수 필드 누락 시 명확한 오류로 종료한다. - `.gitignore` 에 인스턴스 TOML 경로 패턴(예: `*.toml` 또는 `config/*.toml`)을 추가해 설정 파일이 커밋되지 않게 한다. 토큰/instance_key 는 로그에 평문 출력하지 않는다(NFR-4). ## Acceptance Criteria 1. Given `inst-1.toml`(`instance_key="inst-1"`, `portfolio_hub_token="tok"`), When `DaemonInstanceConfig.from_toml("inst-1.toml")`, Then `instance_key="inst-1"`, `portfolio_hub_token="tok"` 로 파싱된다. 2. Given `--config` 인자 없이 데몬 기동, When 진입점 실행, Then 오류 메시지 출력 + exit code ≠ 0 으로 종료한다(기본값 fallback 없음). 3. Given TOML 에 `portfolio_hub_token` 이 있고 `.env`/OS env 에 `TREX_PORTFOLIO_HUB_TOKEN` 미설정, When 최종 설정 구성, Then `PortfolioHubConfig.token` 에 TOML 값이 주입된다(S-5). 4. Given TOML 에 필수 필드(`instance_key`) 누락, When `from_toml`/`from_config`, Then 명확한 오류로 실패한다(조용한 기본값 금지). 5. Given 저장소, When `.gitignore` 확인, Then 인스턴스 TOML 경로 패턴이 무시 대상이다. 6. Given 데몬 기동 로그, When 출력 확인, Then `portfolio_hub_token` 평문이 로그에 노출되지 않는다. 7. (CHG-20260609-01) Given `--config [--config-path ]`, When `resolve_config_toml`, Then `/.toml` 로 해석되고 `.toml` 이 없으면 자동 부착된다. 8. (CHG-20260609-01) Given 슬래시 포함(경로형) `--config` 값, When 해석, Then `--config-path` 와 무관하게 명시 경로로 그대로 사용된다(하위호환). 9. (CHG-20260609-01) Given 운영자 CLI 가 `--config-path` 와 함께 호출, When `_resolve_instance`, Then 동일 `resolve_config_toml` 규칙으로 TOML 을 찾아 instance_key 를 해석한다. ## Impacted Area - Docs: - `docs/project-structure.md` — 설정 파일 계층(TOML + env) (REQ-051 처리) - Modules: - `trex_core/runtime/config.py` — `DaemonInstanceConfig` + `from_toml` + `from_config` 병합, (CHG-20260609-01) `resolve_config_toml`/`DEFAULT_CONFIG_DIR` - 데몬 진입점(`trex_core/runtime/daemon.py:main` 또는 `__main__`) — `--config` 필수 파싱(argparse), (CHG-20260609-01) `--config-path` - 운영자 CLI `trex_core/runtime/cli.py` — (CHG-20260609-01) `--config-path` + `_resolve_instance` 통일 - `.gitignore` — 인스턴스 TOML 패턴 - Tests: - `tests/runtime/` — TOML 로더 파싱/필수 인자/토큰 주입/누락 오류 ## Notes - dcy-009 OQ-2 Answered: `--config` 필수, fallback 없음(split-brain 위험 회피). A-5. - NFR-4(민감값 비노출)는 본 REQ 의 gitignore + 로그 미노출 AC 로 흡수. - DATA_TOML_SCHEMA_FULL(dcy-009 §10): 최소 필드 `instance_key`/`portfolio_hub_token`. 추가 필드는 본 REQ 구현 스키마에서 확장 가능. - KIS 자격증명/DSN/RABBITMQ_URL 등 나머지 env 는 이번 범위에서 `.env` 유지(CONFIRM_ENV_RESIDUAL). ## Change Log ### CHG-20260607-01 - Date: 2026-06-07 - Author: Justin Ko #### Change Summary - dcy-009(confirmed) → REQ-048 초안 생성. #### Intent - per-instance TOML 로더 + `--config` 필수(FR-1, NFR-4)를 Configuration REQ 로 정규화. #### Acceptance Criteria Delta - Added: AC-1~6 전체 #### Impacted Area Delta - Docs: project-structure.md (REQ-051) - Modules: config.py, daemon 진입점, .gitignore - Tests: tests/runtime TOML 로더 #### Delivery Trace Delta - Batches: none (미할당) - Releases: none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: confirm-req 로 승인. ### CHG-20260607-02 - Date: 2026-06-07 - Author: Justin Ko #### Change Summary - Proposed → Approved (confirm-req). #### Intent - 승인 게이트 통과: 필수 필드·구체 AC·Impacted Area·Change Log 완비. dcy-009(confirmed) 범위·결정(OQ-2 TOML 필수)과 모순 없음. TOML 추가 필드 스키마는 구현 단계 확장 가능 비핵심. #### Acceptance Criteria Delta - (변경 없음) #### Impacted Area Delta - (변경 없음) #### Delivery Trace Delta - Batches: none (미할당) - Releases: none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current - Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery 편성. ### CHG-20260607-03 - Date: 2026-06-07 - Author: Justin Ko #### Change Summary - Status Approved → Implemented (confirm-req-implemented, 근거 batch BAT-013 release-candidate). #### Intent - BAT-013 verification 의 AC↔evidence(로더 6 단위: from_toml/필수 누락/token 주입 S-5/default ik/`--config` 누락 subprocess 종료 AC-2/gitignore)로 AC-1~6 충족. NFR-4(민감값) 흡수. #### Acceptance Criteria Delta - (변경 없음) #### Impacted Area Delta - (변경 없음) #### Delivery Trace Delta - Batches: BAT-013 (release-candidate) - Releases: none #### Revalidation Impact - Reverification Needed: no - Existing Implementation Invalidated: no - Status Recommendation: keep-current (Implemented) - Follow-up Action: draft-release 로 BAT-013 배포 편성. token .env 제거는 배포 rollout. ### CHG-20260608-01 - Date: 2026-06-08 - Author: Justin Ko #### Change Summary - (change-req, dcy-014) per-instance TOML 설정에 `trading_timezone`(기본 `Asia/Seoul`)·`daily_preallocation_time`(기본 `00:00`) 키 추가. `DaemonInstanceConfig.from_toml` 파싱 + `from_config` → `DaemonConfig` 전파. 본 기능 운영 설정을 TOML 로 일원화(dcy-014 FR-4). BAT-018 재구현·재검증 완료 → Implemented 유지. #### Intent - 거래일 타임존·일일 트리거 시각을 신규 설정 표면 없이 기존 `--config` TOML 에 편입(운영자 명시 지정 가능). #### Acceptance Criteria Delta - Added: - TOML optional 키 `trading_timezone`/`daily_preallocation_time`(부재 시 KST/00:00 기본). from_config 가 DaemonConfig 로 전파. #### Impacted Area Delta - Modules: `trex_core/runtime/config.py`(DaemonInstanceConfig/DaemonConfig/from_config) - Docs: `config/instance.example.toml` - Tests: tests/runtime/test_instance_config.py(기본값/전파) #### Delivery Trace Delta - Batches: BAT-018 - Releases: none #### Revalidation Impact - Reverification Needed: yes (BAT-018 에서 완료) - Existing Implementation Invalidated: no (optional 키 추가, 기존 TOML 호환) - Status Recommendation: Implemented (change-req → BAT-018 재검증) - Follow-up Action: confirm-req-implemented(BAT-018). #### Validation Plan - BAT-018: from_toml 기본값(KST/00:00) + TOML 값 from_config 전파 단위. ### CHG-20260609-01 - Date: 2026-06-09 - Author: Justin Ko #### Change Summary - (change-req, trex-orb-v1 설정 관리 정합) `--config` 를 **경로 대신 이름**으로 받고 `--config-path `(기본 `./config`)로 config 디렉터리를 분리한다. `resolve_config_toml(name, config_path)` 추가 — `/.toml`(`.toml` 자동 부착). **하위호환**: 슬래시 포함(경로형) `--config` 값은 명시 경로로 그대로 사용(기존 운영 기동 스크립트 무중단). 운영자 CLI(`trex-core`)에도 `--config-path` 를 적용해 인스턴스 라우팅을 동일 규칙으로 통일. 데몬·CLI 진입점 argparse 갱신. #### Intent - trex-orb-v1 과 동일한 config 디렉터리 기반 설정 관리로 통일 — CWD 독립·이름 기반 인스턴스 선택. 공유 `.env`(REQ-010 CHG-20260609-01)의 해석 기준 디렉터리(`config_dir`)를 `--config-path` 로 제공한다. #### Acceptance Criteria Delta - Added: - AC-7: `--config [--config-path ]` → `/.toml` 로 해석되고 `.toml` 확장자가 없으면 자동 부착된다(`resolve_config_toml`). - AC-8: 슬래시를 포함한(경로형) `--config` 값은 `--config-path` 와 무관하게 **명시 경로**로 그대로 사용된다(하위호환 — 기존 `--config config/test.toml` 무중단). - AC-9: 운영자 CLI(`trex-core`)도 `--config-path` 를 수용하며, `_resolve_instance` 가 동일 `resolve_config_toml` 규칙으로 TOML 을 찾는다. - Updated: - AC-2(필수 인자)는 유지 — `--config` 는 여전히 필수다(이름 또는 경로). - Removed: none #### Impacted Area Delta - Modules: `trex_core/runtime/config.py`(`resolve_config_toml`, `DEFAULT_CONFIG_DIR`), `trex_core/runtime/daemon.py`(`main` argparse `--config-path`), `trex_core/runtime/cli.py`(`--config-path` + `_resolve_instance` 통일) - Docs: `docs/project-structure.md`(설정 파일 계층 — config 디렉터리/이름 해석), `config/instance.example.toml` - Tests: `tests/runtime/`(resolve_config_toml: 이름/.toml 부착/config-path/경로형 폴백, 데몬·CLI `--config-path` 라우팅) #### Delivery Trace Delta - Batches: 신규 batch-lite(REQ-010 CHG-20260609-01 과 동일 배치) - Releases: none #### Revalidation Impact - Reverification Needed: yes (신규 batch 에서 AC-7/8/9 검증) - Existing Implementation Invalidated: no (경로형 `--config` 는 하위호환 유지, 이름 해석은 additive) — 단 신규 AC 미구현 - Status Recommendation: Implemented → Approved (신규 AC-7/8/9 미구현 — batch 재검증 후 Implemented 복귀) - Follow-up Action: draft-batch(batch-lite) → run-batch-implementation → verification → confirm-req-implemented #### Validation Plan - 신규 BAT: `resolve_config_toml("test")`→`config/test.toml`, `("test.toml")`→`config/test.toml`, `("prod","/etc/trex")`→`/etc/trex/prod.toml`, 경로형(`config/test.toml`)→그대로 단위. 데몬·CLI `--config-path` 기동/라우팅 단위. 기존 경로형 `--config` 회귀. ### CHG-20260609-02 - Date: 2026-06-09 - Author: Justin Ko #### Change Summary - Status 변경: Approved → Implemented. BAT-026 release-candidate verification evidence 기반(CHG-20260609-01 AC-7/8/9). #### Acceptance Criteria Delta - Added/Updated/Removed: 없음 #### Impacted Area Delta - Docs/Modules/Tests: 없음 #### Delivery Trace Delta - Batches: BAT-026 (release-candidate) - Releases: none #### Revalidation Impact - Reverification Needed: no (BAT-026 에서 완료) - Existing Implementation Invalidated: no - Status Recommendation: Implemented - Follow-up Action: release 단계 별도 진행 #### Validation Plan - tests/runtime/test_config_resolution.py(resolve_config_toml/경로형 폴백/CLI `--config-path` 라우팅) + 라이브 스모크(name·path 형태 동일 결과). 전체 375 passed, ruff clean.