* docs: preserve original issue 5 body * feat: add service token rename command * test: normalize rich option errors
6.1 KiB
6.1 KiB
id, status
| id | status |
|---|---|
| dcy-0010 | confirmed |
Service token rename without secret rotation
Problem
pfhub service-token은 활성 service token을 이름으로 조회해 rotate, rebind, revoke할 수 있지만 이름만 바꾸는 명령은 제공하지 않는다. 이름 오타나 명명 규칙을 교정하려면 새 token을 발급하고 기존 token을 revoke해야 하므로, label 변경만 필요한 경우에도 raw bearer token과 client 배포를 교체해야 한다.
기대 상태는 활성 service token의 동일한 durable row에서 name만 원자적으로 변경하고 기존 bearer token, identity, owner, permission, expiry, runtime/daemon binding을 유지하는 것이다. CLI는 확인 prompt와 non-interactive --force를 제공하고 table/JSON에서 secret 없이 변경 결과를 반환해야 한다.
Evidence
E-001GitHub Issue #5 (https://github.com/fourblocks2020/portfolio-hub/issues/5)는pfhub service-token rename NAME --new-name NEW_NAME [--force]와 name-only 변경, active-name uniqueness, missing/duplicate/no-op 오류, table/JSON 출력을 요구한다. 원문은 commit17d6cbe3ba4ec10842bafb4af90709ef83fe721f의docs/issues/issue-0005-original.md에 byte-for-byte 보존되어 있다.E-002app/cli/commands/service_tokens.py의 current command set은list,issue,rotate,rebind,revoke,migrate-null-daemon이며 rename path가 없다.revoke_service_token()은--force/-f와typer.confirm()의 기존 UX를 제공한다.E-003app/services/auth_service.py::AuthService는 active service token lookup, issue/rotate/rebind/revoke lifecycle을 소유한다.issue_service_token()은 PostgreSQLUniqueViolation을이미 존재하는 서비스 토큰 이름입니다: {name}으로 변환한다.E-004app/repositories/postgres.py::get_service_token_by_name()은name,token_type='service',revoked_at IS NULL로 active row만 조회한다. 같은 파일의 cold-start schema와 migrationapp/db/alembic/versions/20260520_0022_service_token_unique_index_fix.py는idx_auth_tokens_service_name_uniquepartial unique index로 active service-token name uniqueness를 이미 강제한다.E-005app/repositories/portfolio_repository.py::PortfolioRepository에는 rename contract가 없으며app/schemas/auth.py에도 rename CLI response가 없다.E-006AuthToken/PostgreSQL row는 token identity와 secret-derived 값, permission, owner, expiry, runtime/daemon binding을 name과 별도 column으로 보존한다. raw token은 저장하지 않으므로 name-only invariant는 row before/after 비교와 기존 bearer token 재인증으로 검증해야 한다.E-007currentmainbaseline996127f2155a71c1085c4fbf35b504cc3c43439c에서 관련 구현이 없고, Issue #5 및service token renamekeyword의 기존 구현 PR도 없다.E-008현재 ProofLine active AC 검색 결과 service-token label rename lifecycle을 소유하는 criterion은 없다. service-token authorization 및 daemon-scope criteria는 회귀 대상일 뿐 이 신규 capability를 satisfy하지 않는다.
Scope
S-001AC admission은 durable CLI behavior를 소유하는 신규 REQ/ACcreate로 분류한다. Approved REQ 원문과 기존 active AC 의미는 변경하지 않는다.S-002PortfolioRepository와 PostgreSQL adapter에 active service token의name만 바꾸는 단일UPDATE ... RETURNINGcontract를 추가한다. 새 이름 사전 조회를 uniqueness 권위로 사용하지 않고 기존 partial unique index가 concurrent conflict를 결정한다.S-003AuthService에 missing active token, duplicate active name, same-name success no-op를 구분하는 rename contract를 추가한다.new_name == name도 active row 존재를 확인하며 repository write는 하지 않는다.S-004pfhub service-token rename NAME --new-name NEW_NAME [--force/-f]를 추가한다. prompt 취소는 success exit와 zero write이고, 결과는token_id,old_name,new_name,changed만 table/JSON으로 출력한다.S-005성공 rename은 동일 row의name외 모든 column과 기존 bearer-token authentication principal을 보존한다. raw/masked token을 출력하거나 token generation/hash/revoke 경로를 호출하지 않는다.S-006unit/service/CLI와 loopback real-PostgreSQL integration으로 success, missing, active collision, revoked-name reuse, same-name no-op, prompt/force, secret non-disclosure, protected-field invariants와 concurrent conflict를 검증한다.S-007existing interface documentation과 CLI examples를 additive contract에 맞춰 갱신하며 기존 service-token lifecycle/auth/daemon-scope 회귀를 유지한다.
Out of Scope
OS-001raw token rotation, reissue, revoke 또는 secret 표시OS-002token owner, permission, type, expiry, runtime/daemon binding 변경OS-003revoked token row 자체의 renameOS-004service-token name 문자셋·길이·정규화에 대한 신규 정책OS-005HTTP API endpoint, database schema migration, historical backfillOS-006다른 repository 변경, production rollout 또는 production token mutation
Risks and Unknowns
Risks
R-001애플리케이션의 “이름 사용 가능” 사전 조회만으로 충돌을 판단하면 concurrent rename/issue가 race한다. single-statement update와 partial unique index를 authority로 사용하고 실제 PostgreSQL 경쟁 테스트로 완화한다.R-002update projection이나 CLI response에 secret-derived/internal field가 포함되면 정보 노출 또는 unintended mutation이 생긴다. canonical auth-token projection을 반환하되 CLI response를 네 개의 비밀이 아닌 필드로 제한하고 negative test를 둔다.R-003same-name no-op가 존재 확인 없이 성공하면 missing token을 정상 처리하거나 revoked row를 오인할 수 있다. active lookup 성공을 no-op의 precondition으로 고정한다.R-004application rollback은 이미 완료된 metadata rename을 자동으로 되돌리지 않는다. 필요한 경우 동일 command로 이전 이름에 다시 rename하며 production 실행은 별도 운영 승인으로 둔다.