feat: add portfolio ownership model, auth guards, and migration
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# REQ-004: 포트폴리오 소유주 기반 접근 제어
|
||||
|
||||
- Status: Proposed
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: Justin
|
||||
|
||||
## Intent
|
||||
- 시스템은 각 포트폴리오의 소유주를 명시적으로 저장하고, 인증된 주체의 권한과 소유권을 함께 평가해 접근 제어를 수행해야 한다.
|
||||
- 동일 서버에서 운영되는 frontend와 portfolio-hub가 공통 인증 기반을 공유하더라도, 포트폴리오 단위 데이터 격리가 보장되도록 한다.
|
||||
|
||||
## Requirement
|
||||
- 시스템은 각 `portfolio` 레코드에 소유주 식별자 `owner_user_id`를 저장해야 한다.
|
||||
- 시스템은 신규 포트폴리오 생성 시 요청 본문으로 소유주를 임의 지정받지 않고, 인증 컨텍스트의 사용자 식별자를 `owner_user_id`로 저장해야 한다.
|
||||
- 시스템은 `admin` 권한을 제외한 모든 사용자/토큰 요청에서 `owner_user_id`가 인증 주체와 일치하는 포트폴리오만 조회/변경/삭제 가능해야 한다.
|
||||
- 시스템은 `admin` 권한 요청에서 소유권 제약 없이 포트폴리오 전체를 조회/변경/삭제할 수 있어야 한다.
|
||||
- 시스템은 소유권 불일치로 거부된 요청에 대해 `403 Forbidden`을 반환해야 한다.
|
||||
- 시스템은 인증 컨텍스트에 사용자 식별자가 없는 토큰이 소유권이 필요한 포트폴리오 작업을 요청하면 `403 Forbidden`을 반환해야 한다.
|
||||
- 시스템은 기존 포트폴리오 데이터에 대해 마이그레이션 시 `owner_user_id`를 null 허용으로 추가한 뒤, 백필 완료 후 not null 제약을 적용할 수 있어야 한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 인증된 일반 사용자(또는 해당 사용자에 귀속된 토큰)가 `POST /portfolios`를 호출할 때, When 포트폴리오가 생성되면, Then 저장된 `owner_user_id`는 요청자 사용자 식별자와 동일해야 하며 요청 본문으로 다른 소유주를 지정할 수 없어야 한다.
|
||||
2. Given 서로 다른 두 사용자 A와 B가 존재하고 A 소유 포트폴리오가 있을 때, When B가 `GET /portfolios/{portfolio_id}` 또는 변경 API를 호출하면, Then 시스템은 `403`을 반환하고 데이터를 노출/변경하지 않아야 한다.
|
||||
3. Given 일반 사용자 A가 목록 조회를 수행할 때, When `GET /portfolios`를 호출하면, Then 응답 목록에는 A 소유 포트폴리오만 포함되어야 한다.
|
||||
4. Given `admin` 권한 사용자가 존재할 때, When `GET /portfolios` 또는 특정 포트폴리오 변경 API를 호출하면, Then 시스템은 소유권 검사로 요청을 거부하지 않아야 한다.
|
||||
5. Given 마이그레이션 적용 전 생성된 레거시 포트폴리오가 존재할 때, When ownership 마이그레이션을 적용하면, Then 데이터 손실 없이 `owner_user_id`가 백필되고 이후 읽기/쓰기 API가 실패 없이 동작해야 한다.
|
||||
6. Given 인증 컨텍스트에 사용자 식별자가 없는 bot 토큰이 포트폴리오 생성/수정/삭제를 요청할 때, When 소유권이 필요한 API를 호출하면, Then 시스템은 `403`을 반환해야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: `docs/SRS/index.md`, `docs/SRS/traceability-matrix.md`, `docs/technical/auth-and-token-lifecycle.md`, `docs/technical/api-contracts.md`, `docs/technical/persistence-and-migrations.md`, `docs/technical/portfolio-ownership-and-auth-design.md`
|
||||
- Modules: `app/core/auth.py`, `app/api/portfolios.py`, `app/services/portfolio_service.py`, `app/repositories/portfolio_repository.py`, `app/repositories/postgres.py`, `app/domain/models.py`, `app/schemas/portfolio.py`, `migrations/versions/*`
|
||||
- Tests: `tests/test_app.py`, `tests/test_auth.py`, `tests/test_cli.py`, `tests/test_domain_services.py`
|
||||
|
||||
## Notes
|
||||
- 본 requirement는 인증 서비스 분리 여부와 무관하게 portfolio-hub 내부에서 반드시 충족되어야 하는 리소스 소유권 계약이다.
|
||||
- 소유권 기반 제어는 기존 RBAC(`read`, `trade-write`, `admin`)를 대체하지 않고 보완한다.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260413-01
|
||||
- Date: 2026-04-13
|
||||
- Author: GitHub Copilot
|
||||
|
||||
#### Change Summary
|
||||
- 포트폴리오 소유주 필드와 소유권 기반 접근 제어를 정의하는 신규 requirement를 추가했다.
|
||||
|
||||
#### Intent
|
||||
- frontend와 API가 동일 인증 체계를 사용할 때도 포트폴리오 단위 데이터 격리를 강제하기 위함이다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 소유주 저장 규칙
|
||||
- 일반 사용자 소유권 격리 규칙
|
||||
- admin 예외 규칙
|
||||
- 레거시 백필 규칙
|
||||
- user_id 없는 주체 거부 규칙
|
||||
- Updated:
|
||||
- 없음
|
||||
- Removed:
|
||||
- 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- `docs/SRS/Interface/REQ-004_portfolio-ownership-access-control.md`
|
||||
- `docs/SRS/index.md`
|
||||
- `docs/SRS/traceability-matrix.md`
|
||||
- `docs/technical/portfolio-ownership-and-auth-design.md`
|
||||
- Modules:
|
||||
- ownership 검사 경로 전반
|
||||
- Tests:
|
||||
- API/권한/백필 검증 시나리오
|
||||
|
||||
#### Validation Plan
|
||||
- 사용자별 소유권 격리 통합 테스트, admin 우회 테스트, 마이그레이션 백필 테스트를 통해 계약 충족 여부를 확인한다.
|
||||
Reference in New Issue
Block a user