- Add acceptance criteria documentation (AC-0013 through AC-0023) - Add Line-0003 discovery documentation - Implement Strategy Catalog v1 with new database migration - Update portfolio API endpoints and schemas - Refactor strategy and portfolio services - Add strategy management CLI commands - Update domain models with strategy catalog support - Add comprehensive tests for v1 strategies - Update design documentation (data model, interfaces, runtime flows)
11 KiB
11 KiB
Portfolio Hub Project Structure
- Baseline Mode: observed
- Baseline Seed: .stagepilot/bootstrap/baseline.yaml
- Status: confirmed
- Owner: repository-maintainers
- Last Updated (KST): 2026-05-21 00:00
- Source Discovery / Batch: bootstrap-baseline, bat-001, bat-002, bat-006, bat-007, bat-003, bat-004, bat-005, BAT-006(dcy-004), BAT-007(dcy-004), BAT-008(dcy-004)
Project Summary
- PortfolioHub exposes portfolio management and trading ledger workflows through a FastAPI service and a companion CLI.
Primary Domain
- Portfolio management and trading ledger services.
Tech Stack
- Python 3.12
- FastAPI
- Typer
- Pydantic Settings
- Psycopg
- Alembic
- PostgreSQL/TimescaleDB
- Docker Compose
Primary Runtime
- Type: mixed
- Planned Entry Points:
- uvicorn app.main:app :: serve the authenticated HTTP API, OpenAPI docs, and startup bootstrap hooks
- pfhub :: run operational CLI commands for health, users, portfolios, strategies, tags, service tokens, and broker credentials
- alembic upgrade head :: apply ordered database schema migrations for persistent environments
Purpose
- This document is the current approved repository and package structure baseline.
- It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates.
Scope
- Covers the top-level repository layout and package or module boundaries.
- Does not duplicate detailed business rules, acceptance criteria, or implementation-only function signatures.
Top-Level Structure
.
|-- .github/
| |-- instructions/
| |-- prompts/
| |-- runbooks/
| |-- scripts/
| |-- skills/
| `-- templates/
|-- .stagepilot/
| `-- bootstrap/
|-- .vendor/
| `-- stage-pilot/
|-- app/
| |-- api/
| |-- cli/
| |-- core/
| |-- db/
| |-- domain/
| |-- repositories/
| |-- schemas/
| `-- services/
|-- docs/
| |-- batches/
| |-- discovery/
| |-- releases/
| `-- srs/
|-- migrations/
| `-- versions/
|-- tests/
|-- temp/
|-- README.md
|-- alembic.ini
|-- docker-compose.local-test.yml
`-- pyproject.toml
Package / Module Responsibilities
- .github/
- Hosts StagePilot skills, document templates, and helper scripts such as stagepilot-doctor and stagepilot-bootstrap-seed.
- app/api/
- Defines FastAPI route surfaces for health, authentication, users, strategy sets, portfolios, and tags.
- v1 route surfaces:
v1_assets.py(GET /v1/assets token-branched, POST /v1/assets admin catalog, PATCH /v1/assets/{id}, PATCH /v1/assets/{id}/deactivate, POST/DELETE /v1/assets/{id}/tags),v1_tags.py(POST/GET /v1/tags, PATCH /v1/tags/{id}/deactivate),v1_portfolios.py(POST/PATCH/DELETE/GET /v1/portfolios; GET/POST/DELETE /v1/portfolios/{id}/tags; POST/GET/PATCH/DELETE /v1/portfolios/{id}/comments; POST /v1/portfolios/{id}/ledger/trades),v1_user_info.py(GET /v1/user_info). v1_ledger.py제거됨 (BAT-011/REQ-029): 구 pathPOST /v1/assets/{asset_id}/ledger/trades삭제, 신 path는v1_portfolios.py로 통합.- GET /v1/assets supports service/user/admin token branching; admin catalog CRUD requires admin token; tag endpoints added by BAT-004.
- app/cli/
- Defines the Typer entrypoint, command groups, output helpers, and operator-facing command flows.
- Command groups:
asset(catalog CRUD via admin),portfolio,strategy,tag(tag master CRUD and apply/remove; BAT-005),user,service-token,daemon,credential(broker credential management), and health commands (health-check,init-db,migrate-db). app/cli/commands/tag.py(BAT-005):pfhub tag create/list/deactivate/apply asset|portfolio/remove asset|portfolio; direct repo method calls following existing AppContext pattern.pfhub portfolio tag add/list/removeremoved (breaking change, BAT-005).app/cli/commands/service_tokens.py(BAT-006/BAT-007):issue,rotate,rebind(daemon_id 변경, runtime_id 불변),revoke,list,migrate-null-daemon --dry-run(NULL daemon_id active token 진단 CLI).app/cli/commands/daemon.py(BAT-007):create,list,update(--deactivate --force시 바인딩 service token 즉시 revoke).
- app/core/
- Owns configuration loading, auth guards, security helpers, and shared error handling.
encryption.py: Fernet-based credential payload encrypt/decrypt helpers. ReadsCREDENTIAL_ENCRYPTION_KEYenv var viaSettings.require_credential_encryption_key().
- app/domain/
- Holds framework-light domain models shared by services, routes, and repositories.
- app/repositories/
- Provides the repository protocol, repository factory, and concrete Postgres persistence implementation.
- Key methods added in bat-006:
get_portfolio_by_name_and_user(owner_user_id, name) -> Portfolio | Nonefor (owner_user_id, name) → portfolio_id (UUID) resolution used by CLI commands. - Key methods added in BAT-007:
revoke_tokens_by_daemon_id(daemon_id) -> int(UPDATE auth_tokens WHERE daemon_id=X AND revoked_at IS NULL);list_service_tokens_with_null_daemon() -> list[AuthToken](NULL daemon_id active service token 조회); abstract methods added toportfolio_repository.py.
- app/schemas/
- Defines request and response schemas for HTTP contracts.
v1.py: Contract schemas for v1 API — TagItem, TagCreateRequest, TagListResponse, TagApplyRequest, TagApplyResponse (BAT-004); AssetItem, AssetsResponse, UserInfoResponse, BrokerItem, LedgerTradeRequest/Response (BAT-001/002); AssetCatalogCreateRequest, AssetCatalogUpdateRequest, AssetCatalogResponse (BAT-002); PortfolioCreateRequest, PortfolioUpdateRequest, PortfolioItem, PortfolioListResponse (BAT-009); PortfolioTagListResponse, PortfolioCommentItem, PortfolioCommentRequest, PortfolioCommentUpdateRequest, PortfolioCommentListResponse (BAT-010).
- app/services/
- Implements business logic for auth, portfolios, strategy sets, and users.
- migrations/
- Stores Alembic environment files and ordered schema revisions for persistent database changes.
- tests/
- Covers API behavior, auth flows, CLI behavior, domain services, portfolio comments, tags, ownership, and users.
- docs/
- Stores active SDLC indices and cross-cutting baseline documents.
Dependency Rules
- Interface layers in app/api/ and app/cli/ should reach persistence through app/services/ and app/repositories/factory.py rather than importing database code directly.
- app/domain/models.py remains the shared contract between services, repositories, and interface adapters.
- app/repositories/postgres.py owns SQL details; migrations/versions/ owns ordered schema evolution history.
- app/core/config.py is the shared configuration source for both the FastAPI app and the Typer CLI.
- tests/ should prefer public API, CLI, or service entrypoints over asserting against private persistence details unless a regression requires it.
Shared Boundaries
- PortfolioRepository is the abstraction boundary between business logic and concrete persistence.
- Settings and auth primitives are shared across API requests, CLI commands, and startup bootstrap behavior.
- docs/ holds SDLC source-of-truth artifacts, while temp/ remains scratch or legacy material outside the active document flow.
- .vendor/stage-pilot/ is a vendored upstream toolkit and should not be treated as the active host source of truth.
Schema Ownership Boundary
app/repositories/postgres.py의 ensure_schema()와 migrations/versions/ Alembic revision 양쪽이 일부 DB 객체를 다룬다.
소유 경계
| 소유 경로 | 관리 객체 | 비고 |
|---|---|---|
| ensure_schema() 전용 | idx_auth_tokens_service_name_unique (partial index, BAT-006/REQ-017: AND revoked_at IS NULL 조건 추가) |
Alembic revision 20260520_0022에도 CONCURRENTLY 버전 존재 |
| Alembic 전용 | portfolios.market, auth_tokens.runtime_id, idx_auth_tokens_runtime_id_unique, broker_credentials, ledger_trades |
ensure_schema()에 없음 — v1 API 전제 조건 |
| 양쪽 공유 (IF NOT EXISTS 보호) | users, auth_tokens, strategy_sets (status, revision, updated_at 포함), portfolios, portfolio_ledger, portfolio_comments, portfolio_tags + 대부분의 인덱스 |
ensure_schema() 우선 실행 후 Alembic 20260814_0029 실행 시 충돌 없음; 기본 전략 seed/constraints도 존재 여부 guard 적용 |
허용 실행 순서
init-db선행 → App 시작 → 정상 운영 (권장)- App 시작 (ensure_schema() 선행) →
migrate-db후속 실행 (legacy stamp 경로) - 이미 Alembic 관리 DB →
migrate-db증분 upgrade
운영 제약
- ensure_schema()만 실행한 환경은 v1 API 스키마(
broker_credentials,ledger_trades,runtime_id)가 없어 v1 엔드포인트가 동작하지 않는다.migrate-db로 보완 필요. alembic_version테이블을 수동으로 삭제한 뒤migrate-db를 재실행하면 legacy stamp 오판이 발생할 수 있다.- legacy DB(bot_principals 등 구 revision 0006~0013 구조)와 신규 revision 간 호환성 검증은 이번 batch 범위 밖이다.
Current Gaps / Planned Changes
- The non-DB repository path intentionally raises a feature-not-ready error when persistence is disabled.
- Redis and Loki settings exist, but their runtime ownership and module boundaries are not yet represented in active docs.
- Broker credential write path (upsert) is available only via CLI; no public HTTP API exists for credential registration yet.
Update Triggers
- Update this document when package boundaries change.
- Update this document when new top-level runtime or domain modules are added.
- Update this document when a batch changes the approved structure baseline.
Change Log
- 2026-05-21 KST: BAT-011 (REQ-029) — ledger path migration:
v1_ledger.py제거;v1_portfolios.py에POST /{id}/ledger/trades흡수;app/main.pyinclude 정리. Source Discovery/Batch 헤더 갱신. - 2026-05-21 KST: BAT-010 (REQ-032) — v1 portfolio surface 반영: v1_portfolios.py 책임 갱신 (POST/PATCH/DELETE/GET /v1/portfolios + 태그/댓글 서브 라우트); v1.py schema 목록 갱신 (BAT-009/010 schema 5종 추가); Source Discovery/Batch 헤더 갱신.
- 2026-05-21 KST: BAT-008 (REQ-019) — 패키지 구조 갱신: service-token rebind/migrate-null-daemon CLI 서브커맨드 추가 반영; daemon command group 및 --deactivate auto-revoke 동작 반영; repositories에 revoke_tokens_by_daemon_id / list_service_tokens_with_null_daemon 메서드 추가 반영; Schema Ownership 표의 idx_auth_tokens_service_name_unique 조건 갱신(AND revoked_at IS NULL).
- 2026-05-20 KST: bat-005 — REQ-008 AC-3: added app/cli/commands/tag.py (pfhub tag command group); updated app/api/ to reflect v1_tags.py, v1_portfolios.py, v1_assets.py tag endpoints; updated app/schemas/v1.py tag schemas; updated pfhub entry point (tags); noted pfhub portfolio tag removal.
- 2026-05-11 KST: bat-007 — Added "Schema Ownership Boundary" section documenting ensure_schema() vs Alembic ownership zones, allowed/forbidden execution sequences, and legacy scope exclusion.
- 2026-05-11 KST: bat-006 — Added get_portfolio_by_name_and_user() to repositories section; noted that portfolio_id is now a server-generated UUID.
- 2026-04-30 KST: Bootstrap baseline created from repository observation for initial StagePilot adoption.