feat(auth): owner-bound bot tokens and self-service bot management

This commit is contained in:
2026-04-14 00:34:44 +09:00
parent 9787cf3159
commit 2dab17cbb1
16 changed files with 576 additions and 35 deletions
@@ -75,6 +75,7 @@ FOREIGN KEY (owner_user_id) REFERENCES users(id);
- 2단계: admin이 아니면 ownership 검사 수행
- ownership 검사 기준: `portfolio.owner_user_id == auth_context.user_id`
- `auth_context.user_id`가 없는 요청은 ownership 필요한 엔드포인트에서 `403`
- 봇 토큰(`token_type=bot`)의 `auth_context.user_id`는 `bot_principals.owner_user_id`로 해석
## Endpoint Policy Matrix
@@ -92,6 +93,16 @@ FOREIGN KEY (owner_user_id) REFERENCES users(id);
| `DELETE /portfolios/{portfolio_id}` | admin | admin only | 기존 정책 유지 |
| `POST/GET/PATCH/DELETE /portfolios/{id}/comments*` | read or trade-write | 적용 | 상위 포트폴리오 ownership을 재사용 |
## Bot Principal Ownership 정책
- `bot_principals.owner_user_id`는 필수이며 `users.id` FK를 가진다.
- 봇 principal 생성 정책:
- Admin: 임의 사용자 owner로 생성 가능
- Self-service 사용자: 본인 owner로만 생성 가능
- 봇 토큰 관리 정책:
- Admin 경로는 전체 봇 대상으로 관리 가능
- Self-service 경로는 본인 소유 봇 대상으로만 관리 가능
## 서비스/리포지토리 반영 포인트
- Domain model:
- `Portfolio`에 `owner_user_id` 추가
@@ -116,13 +127,16 @@ FOREIGN KEY (owner_user_id) REFERENCES users(id);
1. 기존 portfolios row가 존재할 때 owner_user_id 백필 후 null row가 0건인지 검증
2. users가 없는 상태에서 migration 실행 시 실패 동작 검증
3. downgrade 시 인덱스/제약 해제가 순서대로 수행되는지 검증
4. 기존 bot_principals row가 존재할 때 owner_user_id 백필 후 null row가 0건인지 검증
5. bot_principals.owner_user_id FK(`users.id`) 제약 생성/해제 검증
## API Authorization
1. 사용자 A 소유 portfolio를 사용자 B가 조회하면 403
2. 사용자 A 소유 portfolio를 사용자 B가 수정/매매/리셋하면 403
3. admin이 타 사용자 portfolio 조회/수정 가능
4. 일반 사용자의 `GET /portfolios`는 본인 소유만 반환
5. user_id 없는 bot principal 요청이 ownership 필요 API 호출 시 403
5. 사용자 A에 귀속된 bot 토큰은 A 소유 portfolio만 접근 가능
6. 사용자 B가 A 소유 bot의 self-service 토큰 발급/조회/폐기를 시도하면 403
## API Creation
1. `POST /portfolios`에서 owner_user_id가 인증 사용자로 저장되는지 검증