0.29.1原版
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
## Background & Context
|
||||
|
||||
User resources in Memos v1 are exposed through Connect/gRPC-Gateway handlers in `server/router/api/v1`, proto resource definitions in `proto/api/v1`, frontend profile flows in `web/src`, and MCP JSON helpers in `server/router/mcp`. The store schema already persists both an internal integer `id` and a unique `username` for each user. The GitHub issue reports that public user resource names such as `users/2` are still emitted across responses and nested user-scoped resources. Existing code already mixes identifier forms: `GetUser` accepts either `users/{id}` or `users/{username}`, the fileserver avatar route accepts either identifier, and the frontend profile page already enters the API through `users/{username}` before reusing the returned `user.name`.
|
||||
|
||||
## Issue Statement
|
||||
|
||||
Across the v1 API surface, canonical user resource names are currently constructed from `store.User.ID` rather than `store.User.Username`, and many handlers parse those emitted names back into integers for authorization and lookup. As a result, top-level user resources and nested user-scoped references in settings, stats, shortcuts, webhooks, notifications, memo creators, reactions, and MCP payloads expose sequential database IDs and couple downstream callers to integer-based user tokens in server-emitted names.
|
||||
|
||||
## Current State
|
||||
|
||||
- `store/user.go:26-42` defines `store.User` with both `ID int32` and `Username string`; `store/migration/sqlite/LATEST.sql:10-21` declares `username TEXT NOT NULL UNIQUE`.
|
||||
- `server/router/api/v1/user_service.go:72-102` handles `GetUser` by extracting `users/{id_or_username}` and resolving either a numeric ID or a username; `server/router/api/v1/user_service.go:914-937` still serializes `User.name` as `users/{id}` and derives avatar URLs from that name.
|
||||
- `server/router/api/v1/resource_name.go:67-89` has two different parsing paths: `ExtractUserIDFromName` only accepts numeric user tokens, while `extractUserIdentifierFromName` accepts either token and is currently only used by `GetUser`.
|
||||
- `server/router/api/v1/user_service.go:335-369`, `server/router/api/v1/user_service.go:372-460`, `server/router/api/v1/user_service.go:463-517`, `server/router/api/v1/user_service.go:536-676`, `server/router/api/v1/user_service.go:679-911`, and `server/router/api/v1/user_service.go:1400-1488` parse numeric user segments for settings, personal access tokens, webhooks, and notifications, and emit names such as `users/%d/settings/...`, `users/%d/webhooks/...`, and `users/%d/notifications/%d`.
|
||||
- `server/router/api/v1/shortcut_service.go:20-43` parses `users/{user}/shortcuts/{shortcut}` by converting the `user` segment to `int32`, and constructs shortcut names as `users/%d/shortcuts/%s`.
|
||||
- `server/router/api/v1/user_service_stats.go:63-65`, `server/router/api/v1/user_service_stats.go:113`, `server/router/api/v1/user_service_stats.go:132-145`, `server/router/api/v1/user_service_stats.go:214-223` emit `users/%d/stats` and `users/%d/memos/%d`, and resolve stats requests through numeric `ExtractUserIDFromName`.
|
||||
- `server/router/api/v1/memo_service_converter.go:26-37` serializes `Memo.creator` as `users/{id}`; `server/router/api/v1/reaction_service.go:154-164` serializes `Reaction.creator` as `users/{id}`; `server/router/api/v1/memo_service.go:636-643` and `server/router/api/v1/memo_service.go:815-845` parse `memo.Creator` through the numeric helper for inbox and webhook flows.
|
||||
- `server/router/mcp/tools_memo.go:75-86`, `server/router/mcp/tools_attachment.go:29-37`, and `server/router/mcp/tools_reaction.go:64-71` plus `server/router/mcp/tools_reaction.go:133-138` serialize creator fields as `users/{id}` in MCP tool output.
|
||||
- `server/router/fileserver/fileserver.go:153-181` and `server/router/fileserver/fileserver.go:533-539` currently resolve avatar requests by either numeric ID or username.
|
||||
- `proto/api/v1/user_service.proto:22-29` and `proto/api/v1/user_service.proto:247-256` document `GetUser` accepting both `users/{id}` and `users/{username}`. The same proto file defines the `User` resource at `proto/api/v1/user_service.proto:161-178` and nested user resource formats at `proto/api/v1/user_service.proto:307-317` and `proto/api/v1/user_service.proto:361-373`; example text still uses numeric user tokens such as `users/123/settings/GENERAL`.
|
||||
- `web/src/pages/UserProfile.tsx:74-86` requests `users/{username}` from the route param, and `web/src/layouts/MainLayout.tsx:37-48` stores the returned canonical `user.name` for later stats requests.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Replacing internal `user.id` primary keys, foreign keys, or existing store schemas.
|
||||
- Introducing a new opaque UUID-based public user identifier.
|
||||
- Changing user discovery, public profile visibility, or authorization rules beyond how user resource names are parsed and emitted.
|
||||
- Adding username history, redirect, or alias preservation for old usernames after a rename.
|
||||
- Redesigning unrelated resource naming schemes such as memo, attachment, share, or identity-provider identifiers.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Which public surfaces are in scope for username-based canonical output? (default: all server-emitted v1 API and MCP payload fields that currently contain `users/{...}` resource names)
|
||||
- Should legacy numeric inputs continue to resolve on user-scoped endpoints beyond `GetUser`? (default: no, accept only username-based user resource names)
|
||||
- If a username changes, must previously emitted `users/{old-username}` names continue to resolve? (default: no additional alias or redirect layer; only the current username remains valid)
|
||||
- Should notification, webhook, shortcut, and personal-access-token child identifiers keep their existing child token formats while only the parent user token changes? (default: yes)
|
||||
- Does the issue include avatar URLs and other derived file paths that are built from `User.name`? (default: yes, because avatar URLs are emitted from the same canonical user name field)
|
||||
|
||||
## Scope
|
||||
|
||||
**L** — Current behavior spans `server/router/api/v1`, `server/router/mcp`, `server/router/fileserver`, `proto/api/v1`, frontend consumers in `web/src`, and the request parsers that turn user resource names back into internal IDs. Changing both emitted and accepted user resource names across those surfaces is a broad API contract change rather than a single local edit.
|
||||
@@ -0,0 +1,63 @@
|
||||
## References
|
||||
|
||||
- [AIP-122: Resource names](https://google.aip.dev/122)
|
||||
- [AIP-123: Resource types](https://google.aip.dev/123)
|
||||
- [AIP-148: Standard fields](https://google.aip.dev/148)
|
||||
- [AIP-180: Backwards compatibility](https://google.aip.dev/180)
|
||||
- [Insecure Direct Object Reference Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html)
|
||||
- [REST API endpoints for users - GitHub Docs](https://docs.github.com/en/enterprise-server%403.19/rest/users/users)
|
||||
- [Users API - GitLab Docs](https://docs.gitlab.com/api/users/)
|
||||
- [API Usage - Gitea Documentation](https://docs.gitea.com/next/development/api-usage)
|
||||
|
||||
## Industry Baseline
|
||||
|
||||
`AIP-122: Resource names` and `AIP-148: Standard fields` treat `name` as the canonical identifier that clients store and reuse, and expect request `name` and `parent` fields to accept the same resource-name vocabulary across a service. `AIP-122` also allows aliases for lookup, but requires responses to emit the canonical resource name.
|
||||
|
||||
`REST API endpoints for users - GitHub Docs` and `API Usage - Gitea Documentation` use username-based public user paths and nested user-scoped routes, while keeping numeric or system-assigned identifiers as separate data or alternate endpoints when a durable internal identifier is required.
|
||||
|
||||
`Users API - GitLab Docs` shows a mixed-input compatibility pattern on some endpoints with `id_or_username`, which keeps older callers working while allowing username-oriented public routes.
|
||||
|
||||
`Insecure Direct Object Reference Prevention Cheat Sheet` treats enumerable numeric identifiers as a defense-in-depth concern, but not a substitute for authorization. Replacing `users/{id}` with `users/{username}` changes discoverability characteristics, but permission checks still have to enforce access from internal user IDs.
|
||||
|
||||
`AIP-180: Backwards compatibility` treats changes to resource-name format and server-generated field construction as breaking. Any design that changes emitted `User.name` values inside `v1` has to preserve as much request compatibility as possible and document the remaining response-format risk explicitly.
|
||||
|
||||
## Research Summary
|
||||
|
||||
Memos already has most of the prerequisites for username-based canonical names. The schema stores a unique username, `GetUser` already resolves either ID or username, the fileserver avatar route already uses an `identifier` abstraction, and the frontend profile page already starts from `users/{username}`. No database migration is required to identify users by username at the API boundary.
|
||||
|
||||
The current coupling problem is concentrated in two places. First, response builders serialize `users/{id}` in many modules, including memo conversion, stats, settings, shortcuts, notifications, webhooks, and MCP JSON helpers. Second, many request handlers assume they can parse a numeric ID back out of those names for authorization and storage lookups.
|
||||
|
||||
Research points to a common pattern of canonical public resource names plus server-side resolution to internal IDs. In Memos, switching the canonical token from numeric ID to username can reuse the existing unique username column and existing username lookups, but `AIP-123: Resource types` and `AIP-180: Backwards compatibility` still make clear that changing accepted and emitted resource-name formats inside `v1` is a breaking API contract change. That makes this design a deliberate contract replacement rather than a compatibility layer.
|
||||
|
||||
## Design Goals
|
||||
|
||||
- All server-emitted v1 and MCP response fields that serialize user resource names under `users/{...}` use the current username token instead of the numeric database ID.
|
||||
- User-scoped request fields that reference `users/{...}` accept username-based resource names only.
|
||||
- Authorization, ownership checks, inbox/webhook dispatch, and other internal workflows continue to operate on `store.User.ID` after resolving the public resource name.
|
||||
- List and batch endpoints avoid introducing per-item user lookups when serializing username-based names.
|
||||
- No database schema, foreign-key, or storage-key redesign is required.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Replacing internal `user.id` primary keys, foreign keys, or existing store schemas.
|
||||
- Introducing a new opaque UUID-based public user identifier.
|
||||
- Changing user discovery, public profile visibility, or authorization rules beyond how user resource names are parsed and emitted.
|
||||
- Adding username history, redirect, or alias preservation for old usernames after a rename.
|
||||
- Redesigning unrelated resource naming schemes such as memo, attachment, share, or identity-provider identifiers.
|
||||
- Adding a new API version as part of this issue.
|
||||
|
||||
## Proposed Design
|
||||
|
||||
Introduce a single canonical user-name builder in the v1 API layer that serializes `users/{username}` from resolved user data, and route every public user-name emitter through it. This includes `convertUserFromStore`, memo and reaction creator fields, user stats, settings, shortcuts, webhooks, notifications, personal-access-token names, webhook payloads, avatar URLs derived from `User.name`, and the MCP JSON helpers. This satisfies the first design goal and aligns the public resource shape with `AIP-122: Resource names`.
|
||||
|
||||
Introduce a shared user-token resolver in `server/router/api/v1` that extracts the `users/{token}` segment, validates it as a username-form resource token, resolves the corresponding `store.User`, and then passes the resolved internal ID into permission checks and storage lookups. This replaces numeric-only parsing in helpers such as `ExtractUserIDFromName`, `ExtractUserIDAndSettingKeyFromName`, shortcut and webhook parsers, personal-access-token deletion, and notification parsing. The fileserver's current `getUserByIdentifier` behavior shows both lookup styles exist today, but the API-layer contract for this issue becomes username-only rather than dual-mode.
|
||||
|
||||
Keep child resource tokens unchanged and only change the user segment. For names such as `users/{user}/settings/{setting}`, `users/{user}/webhooks/{webhook}`, `users/{user}/notifications/{notification}`, `users/{user}/shortcuts/{shortcut}`, and `users/{user}/personalAccessTokens/{token}`, the parent `user` token is resolved from the username, while the child token keeps its existing format and storage mapping. This is narrower than redesigning child identifiers and keeps the issue bounded to the user-resource segment.
|
||||
|
||||
Use response-side user resolution strategies that match endpoint shape. Single-resource handlers can resolve one user directly and serialize the username immediately. List and batch handlers such as memo conversion, stats aggregation, notifications, and MCP list output should collect distinct user IDs first and resolve usernames once per response, reusing the store's existing user lookup path and cache where available. This keeps username-based output from turning into hidden N+1 query behavior and satisfies the performance goal without changing persistence.
|
||||
|
||||
Replace the public user-resource contract rather than extending it. Server-emitted `name`, `parent`, `creator`, and `sender` fields become username-based canonical output, and handlers that currently accept `users/{id}` are updated to require `users/{username}`. `AIP-180: Backwards compatibility` indicates that changing both the construction and accepted format of an existing resource name is a breaking change for clients that persist, compare, or generate old `name` values. The design therefore requires updated proto comments, API examples, handler tests, and release notes to make the new canonical form and the removed numeric form explicit.
|
||||
|
||||
Do not add a username alias table in this issue. If a username changes, newly serialized resource names use the current username, and previously emitted username-based names stop resolving unless they match the current username. This keeps the scope aligned with existing `UpdateUser` behavior and avoids introducing a new subsystem for historical username resolution. The alternative of adding permanent old-username aliases was rejected because it expands the problem from canonical serialization into identity-history management.
|
||||
|
||||
Do not solve this by adding a second public identifier field and leaving `User.name` numeric. `AIP-122: Resource names` treats `name` as the canonical resource identifier, and the GitHub issue is specifically about the public names currently emitted under `users/{id}`. Adding a second field would preserve the exposed sequential identifier in the canonical slot and fail the primary design goal. Likewise, introducing a new opaque UUID-based public identifier was rejected because the repository already has a unique username field and the issue is scoped to replacing numeric user resource names with that existing identifier.
|
||||
@@ -0,0 +1,62 @@
|
||||
## Execution Log
|
||||
|
||||
### T1: Add username-only user resource helpers
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**:
|
||||
- `server/router/api/v1/user_resource_name.go`
|
||||
- `server/router/api/v1/resource_name.go`
|
||||
- `server/router/api/v1/user_service.go`
|
||||
- `server/router/api/v1/test/user_resource_name_test.go`
|
||||
**Validation**: `go test -v ./server/router/api/v1/test -run 'TestUserResourceName'` — PASS
|
||||
**Path Corrections**: Tightened username-token validation so numeric-only `users/1` fails at the resource-name layer instead of falling through to `NotFound`.
|
||||
**Deviations**: None
|
||||
|
||||
### T2: Migrate user-scoped API handlers
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**:
|
||||
- `server/router/api/v1/user_service.go`
|
||||
- `server/router/api/v1/shortcut_service.go`
|
||||
- `server/router/api/v1/user_service_stats.go`
|
||||
- `server/router/api/v1/test/shortcut_service_test.go`
|
||||
- `server/router/api/v1/test/user_service_stats_test.go`
|
||||
- `server/router/api/v1/test/user_notification_test.go`
|
||||
- `server/router/api/v1/test/user_service_registration_test.go`
|
||||
**Validation**: `go test -v ./server/router/api/v1/test -run 'Test(ListShortcuts|GetShortcut|CreateShortcut|UpdateShortcut|DeleteShortcut|ShortcutFiltering|ShortcutCRUDComplete|GetUserStats_TagCount|ListUserNotifications|UserRegistration)'` — PASS
|
||||
**Path Corrections**: Updated test fixtures to use valid username-form resource names (`users/testuser`, `users/test-user`) and corrected one stale registration-name expectation during the later broader suite rerun.
|
||||
**Deviations**: None
|
||||
|
||||
### T3: Migrate memo, reaction, MCP, and avatar user references
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**:
|
||||
- `server/router/api/v1/memo_service_converter.go`
|
||||
- `server/router/api/v1/memo_service.go`
|
||||
- `server/router/api/v1/reaction_service.go`
|
||||
- `server/router/mcp/tools_memo.go`
|
||||
- `server/router/mcp/tools_attachment.go`
|
||||
- `server/router/mcp/tools_reaction.go`
|
||||
- `server/router/fileserver/fileserver.go`
|
||||
- `server/router/api/v1/test/memo_service_test.go`
|
||||
- `server/router/api/v1/test/reaction_service_test.go`
|
||||
**Validation**: `go test ./server/router/api/v1/... ./server/router/mcp/... ./server/router/fileserver/...` — PASS
|
||||
**Path Corrections**: Removed an unused fileserver import after the first package build failed; kept MCP tool helper signatures stable for undeclared callers and switched tool call sites to username-aware wrappers.
|
||||
**Deviations**: None
|
||||
|
||||
### T4: Update contract docs and regression tests
|
||||
|
||||
**Status**: Completed
|
||||
**Files Changed**:
|
||||
- `proto/api/v1/user_service.proto`
|
||||
- `proto/api/v1/shortcut_service.proto`
|
||||
- `web/src/layouts/MainLayout.tsx`
|
||||
- `web/src/components/MemoExplorer/ShortcutsSection.tsx`
|
||||
- `server/router/fileserver/README.md`
|
||||
**Validation**: `go test -v ./server/router/api/v1/test/...` — PASS
|
||||
**Path Corrections**: None
|
||||
**Deviations**: None
|
||||
|
||||
## Completion Declaration
|
||||
|
||||
All tasks completed successfully
|
||||
@@ -0,0 +1,106 @@
|
||||
## Task List
|
||||
|
||||
Task Index
|
||||
T1: Add username-only user resource helpers [L] — T2: Migrate user-scoped API handlers [L] — T3: Migrate memo, reaction, MCP, and avatar user references [L] — T4: Update contract docs and regression tests [L]
|
||||
|
||||
### T1: Add username-only user resource helpers [L]
|
||||
|
||||
**Objective**: Establish one v1 API mechanism for serializing `users/{username}` and resolving username-based user resource names back to internal user records, including root `GetUser` handling.
|
||||
**Size**: L (multiple files, shared identifier logic used across handlers)
|
||||
**Files**:
|
||||
- Create: `server/router/api/v1/user_resource_name.go`
|
||||
- Modify: `server/router/api/v1/resource_name.go`
|
||||
- Modify: `server/router/api/v1/user_service.go`
|
||||
- Test: `server/router/api/v1/test/user_resource_name_test.go`
|
||||
**Implementation**:
|
||||
1. In `server/router/api/v1/user_resource_name.go`: add the shared helper surface for canonical user-name construction, extracting the `users/{token}` segment, validating the username-form token, and resolving the corresponding `store.User`.
|
||||
2. In `server/router/api/v1/resource_name.go`: replace `ExtractUserIDFromName()`’s numeric-only behavior with username-oriented resolution helpers or thin wrappers that delegate to the new shared module.
|
||||
3. In `server/router/api/v1/user_service.go`: update `GetUser()` (~lines 72-102) and `convertUserFromStore()` (~lines 914-937) to use username-only resource names and reject legacy numeric `users/{id}` requests.
|
||||
4. In `server/router/api/v1/test/user_resource_name_test.go`: add direct coverage for `GetUser users/{username}` success, canonical `User.name == users/{username}`, and rejection of `users/{id}`.
|
||||
**Boundaries**: Do not migrate nested user-scoped handlers, memo/reaction emitters, MCP output, or fileserver behavior in this task.
|
||||
**Dependencies**: None
|
||||
**Expected Outcome**: Shared username-only helper logic exists, root user resources serialize as `users/{username}`, and root numeric user-name requests fail.
|
||||
**Validation**: `go test -v ./server/router/api/v1/test -run 'TestUserResourceName'` — expected output includes `PASS` and `ok`
|
||||
|
||||
### T2: Migrate user-scoped API handlers [L]
|
||||
|
||||
**Objective**: Convert user-scoped v1 handlers and nested resource emitters to require `users/{username}` while continuing to authorize and store by resolved internal user ID.
|
||||
**Size**: L (multiple handlers in one large service plus shortcut and stats code)
|
||||
**Files**:
|
||||
- Modify: `server/router/api/v1/user_service.go`
|
||||
- Modify: `server/router/api/v1/shortcut_service.go`
|
||||
- Modify: `server/router/api/v1/user_service_stats.go`
|
||||
- Test: `server/router/api/v1/test/shortcut_service_test.go`
|
||||
- Test: `server/router/api/v1/test/user_service_stats_test.go`
|
||||
- Test: `server/router/api/v1/test/user_notification_test.go`
|
||||
- Test: `server/router/api/v1/test/user_service_registration_test.go`
|
||||
**Implementation**:
|
||||
1. In `server/router/api/v1/user_service.go`: update settings, PAT, webhook, and notification parsing/emission paths (~lines 335-911 and ~1400-1488) to resolve `users/{username}` and emit username-based parent/child resource names.
|
||||
2. In `server/router/api/v1/shortcut_service.go`: update shortcut name parsing and construction (~lines 20-43) plus handler entry points to use username parents and nested names.
|
||||
3. In `server/router/api/v1/user_service_stats.go`: update stats request parsing and `UserStats.name` / `PinnedMemos` serialization (~lines 63-65, 113, 132-145, 214-223) to use usernames.
|
||||
4. In the listed tests: replace numeric user-name inputs with username-based parents, assert username-based emitted names, and add numeric-request rejection coverage for representative user-scoped endpoints.
|
||||
**Boundaries**: Do not change memo/reaction creator fields, MCP JSON output, or fileserver avatar routing in this task.
|
||||
**Dependencies**: T1
|
||||
**Expected Outcome**: User settings, notifications, shortcuts, stats, PATs, and webhooks all accept only `users/{username}` and emit only username-based user resource names.
|
||||
**Validation**: `go test -v ./server/router/api/v1/test -run 'Test(ListShortcuts|GetShortcut|CreateShortcut|UpdateShortcut|DeleteShortcut|ShortcutFiltering|ShortcutCRUDComplete|GetUserStats_TagCount|ListUserNotifications|UserRegistration)'` — expected output includes `PASS` and `ok`
|
||||
|
||||
### T3: Migrate memo, reaction, MCP, and avatar user references [L]
|
||||
|
||||
**Objective**: Remove numeric user resource names from memo/reaction-related API responses, dependent webhook/inbox flows, MCP JSON output, and avatar URLs/routing.
|
||||
**Size**: L (cross-package serialization and lookup changes, including response-side user resolution)
|
||||
**Files**:
|
||||
- Modify: `server/router/api/v1/memo_service_converter.go`
|
||||
- Modify: `server/router/api/v1/memo_service.go`
|
||||
- Modify: `server/router/api/v1/reaction_service.go`
|
||||
- Modify: `server/router/mcp/tools_memo.go`
|
||||
- Modify: `server/router/mcp/tools_attachment.go`
|
||||
- Modify: `server/router/mcp/tools_reaction.go`
|
||||
- Modify: `server/router/fileserver/fileserver.go`
|
||||
- Test: `server/router/api/v1/test/memo_service_test.go`
|
||||
- Test: `server/router/api/v1/test/reaction_service_test.go`
|
||||
**Implementation**:
|
||||
1. In `server/router/api/v1/memo_service_converter.go`: update `convertMemoFromStore()` (~lines 16-73) to serialize `Memo.creator` from resolved usernames rather than numeric IDs, using response-side batching or shared lookup helpers so list responses do not regress into hidden per-item lookups.
|
||||
2. In `server/router/api/v1/reaction_service.go`: update `convertReactionFromStore()` (~lines 154-164) to emit username-based creators.
|
||||
3. In `server/router/api/v1/memo_service.go`: update memo comment, webhook dispatch, and webhook payload helpers (~lines 636-643 and 815-845) to resolve username-based memo creators before using internal IDs.
|
||||
4. In `server/router/mcp/tools_memo.go`, `server/router/mcp/tools_attachment.go`, and `server/router/mcp/tools_reaction.go`: replace `users/%d` creator serialization with username-based values.
|
||||
5. In `server/router/fileserver/fileserver.go`: change avatar lookup to accept username identifiers only and ensure avatar URLs derived from `User.name` continue to resolve under `users/{username}`.
|
||||
6. In the listed tests: update creator assertions to `users/{username}` and add representative rejection coverage where numeric user names previously flowed through memo/reaction-related paths.
|
||||
**Boundaries**: Do not update proto comments, README examples, or frontend comments in this task.
|
||||
**Dependencies**: T1
|
||||
**Expected Outcome**: Memo/reaction creators, webhook payload creators, MCP creator fields, and avatar-derived user paths no longer expose numeric user IDs.
|
||||
**Validation**: `go test ./server/router/api/v1/... ./server/router/mcp/... ./server/router/fileserver/...` — expected output includes `ok` for all touched packages
|
||||
|
||||
### T4: Update contract docs and regression tests [L]
|
||||
|
||||
**Objective**: Align public contract comments/examples and the final regression suite with the username-only user resource-name contract.
|
||||
**Size**: L (multiple contract/documentation files plus end-to-end regression coverage)
|
||||
**Files**:
|
||||
- Modify: `proto/api/v1/user_service.proto`
|
||||
- Modify: `proto/api/v1/shortcut_service.proto`
|
||||
- Modify: `web/src/layouts/MainLayout.tsx`
|
||||
- Modify: `web/src/components/MemoExplorer/ShortcutsSection.tsx`
|
||||
- Modify: `server/router/fileserver/README.md`
|
||||
- Modify: `server/router/api/v1/test/user_resource_name_test.go`
|
||||
- Modify: `server/router/api/v1/test/shortcut_service_test.go`
|
||||
- Modify: `server/router/api/v1/test/user_service_stats_test.go`
|
||||
- Modify: `server/router/api/v1/test/user_notification_test.go`
|
||||
- Modify: `server/router/api/v1/test/memo_service_test.go`
|
||||
- Modify: `server/router/api/v1/test/reaction_service_test.go`
|
||||
- Modify: `server/router/api/v1/test/user_service_registration_test.go`
|
||||
**Implementation**:
|
||||
1. In `proto/api/v1/user_service.proto` and `proto/api/v1/shortcut_service.proto`: rewrite resource-name comments and examples so they document username-only user resource names and remove `users/{id}` examples.
|
||||
2. In `web/src/layouts/MainLayout.tsx` and `web/src/components/MemoExplorer/ShortcutsSection.tsx`: update inline comments/examples that still describe numeric user resource names.
|
||||
3. In `server/router/fileserver/README.md`: replace numeric avatar examples with username-based examples.
|
||||
4. In the listed test files: finish any remaining request/response assertions so the suite consistently encodes the username-only contract and explicitly rejects numeric user resource names where that contract is externally visible.
|
||||
**Boundaries**: Do not add schema migrations, generated proto output refreshes, or username-history behavior.
|
||||
**Dependencies**: T2, T3
|
||||
**Expected Outcome**: Source comments, examples, and regression tests all describe and enforce a username-only `users/{username}` public contract.
|
||||
**Validation**: `go test -v ./server/router/api/v1/test/...` — expected output includes `PASS` and `ok`
|
||||
|
||||
## Out-of-Scope Tasks
|
||||
|
||||
- Database schema or migration changes for the `user` table or foreign keys.
|
||||
- Username history, alias, redirect, or backward-compatibility layers.
|
||||
- A new opaque public user identifier or a new API version.
|
||||
- Opportunistic refactors outside the files listed above.
|
||||
- Generated code refreshes (`buf generate`) unless a later approved plan revision explicitly requires schema changes.
|
||||
Reference in New Issue
Block a user