chore: restructure SRS for asset catalog and tag model redesign (dcy-001/002, REQ-001~008)

Architecture Redesign (May 19, 2026):
- Separate admin-managed asset catalog from user portfolios
- Eliminate portfolio as asset definition; clarify portfolio as user position
- Introduce new asset_catalog + portfolio structure

Discovery Documents:
- dcy-001: asset-catalog-and-user-portfolio-model — admin asset management and user portfolio separation
- dcy-002: tag-ownership-and-applicability-policy — tag model implementation strategy

New Requirements (REQ-001~008):
- REQ-001: tags master table introduction (Data, Proposed)
- REQ-002: assets.tag_ids UUID[] column addition (Data, Proposed)
- REQ-003: portfolios.tag_ids and portfolio_tags removal (Data, Proposed)
- REQ-004: tags master HTTP API (Interface, Proposed)
- REQ-005: tag apply/remove HTTP API (Interface, Proposed)
- REQ-006: portfolio_tags data migration (Migration, Proposed)
- REQ-007: pfhub tag CLI commands (Interface, Proposed)
- REQ-008: tag model baseline docs update (Documentation, Proposed)

Cleanup:
- Remove archived SRS documents (REQ-001~029 old structure)
- Remove archived batch documentation (BAT-001~010)
- Remove archived discovery documents (dcy-001~006 old structure)
- Remove archived release documentation (REL-001~006)

Data Model Updates:
- Add Deployment category to SRS structure
- Add Data category for new data model requirements
- Update app/cli/core/utils.py for new tag handling

Documentation:
- Create new SRS index with consolidated requirement structure
- Update docs/discovery/index.md with new discovery references
- Migrate from requirement-centric to domain-model-centric organization

Rationale:
- Existing single-portfolio model lacks admin catalog governance
- New asset catalog enables central management of tradeable symbols
- Tag system supports user-driven asset organization and discovery
- Cleaner separation of concerns between admin operations and user trading
This commit is contained in:
2026-05-19 13:54:25 +00:00
parent 47c4f9bfde
commit 1082f041a1
96 changed files with 1133 additions and 9303 deletions
+10 -16
View File
@@ -121,22 +121,16 @@ def print_portfolio_detail(console: Console, detail: PortfolioDetailResponse) ->
console.print(ledger_table)
def print_user_table(console: Console, users: list[UserResponse]) -> None:
table = Table(title="Users", expand=True)
table.add_column("ID", style="cyan", no_wrap=True)
table.add_column("Username", no_wrap=True)
table.add_column("Email")
table.add_column("Created At", no_wrap=True)
table.add_column("Updated At", no_wrap=True)
for user in users:
table.add_row(
user.id,
user.username,
user.email or "N/A",
user.created_at.isoformat(timespec="seconds") if user.created_at else "N/A",
user.updated_at.isoformat(timespec="seconds") if user.updated_at else "N/A",
def print_user_list(console: Console, users: list[UserResponse]) -> None:
for i, user in enumerate(users):
if i:
console.print()
console.print(f"[bold]{user.username}[/bold] [dim]{user.id}[/dim]")
console.print(f" email {user.email or 'N/A'}")
console.print(
f" created {user.created_at.isoformat(timespec='seconds') if user.created_at else 'N/A'}"
f" updated {user.updated_at.isoformat(timespec='seconds') if user.updated_at else 'N/A'}"
)
console.print(table)
def print_user_detail(console: Console, user: UserResponse) -> None:
@@ -274,7 +268,7 @@ def render_output(console: Console, output_format: str, payload: Any, *, empty_m
print_portfolio_list(console, payload)
return
if all(isinstance(item, UserResponse) for item in payload):
print_user_table(console, payload)
print_user_list(console, payload)
return
if all(isinstance(item, CommentResponse) for item in payload):
print_comment_table(console, payload)