feat: user service
This commit is contained in:
+103
-32
@@ -1,5 +1,9 @@
|
||||
# User Service Implementation Plan
|
||||
|
||||
This plan has been already implemented and stays here for historical reasons.
|
||||
|
||||
It should NOT be threated as source of truth for service functionality.
|
||||
|
||||
## Planning Principles
|
||||
|
||||
This plan is aligned with the current repository architecture and is written
|
||||
@@ -17,7 +21,9 @@ Execution priorities:
|
||||
- keep the first version storage-agnostic at the domain boundary even if Redis
|
||||
is the initial backend
|
||||
|
||||
## Stage 01 — Freeze Vocabulary, Contracts, and Cross-Service Ownership
|
||||
## ~~Stage 01~~ — Freeze Vocabulary, Contracts, and Cross-Service Ownership
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -38,8 +44,10 @@ Remove naming ambiguity and freeze the service boundary before implementation.
|
||||
- workflow and history in `Geo Profile Service`
|
||||
- Freeze the auth-facing internal REST endpoints already reserved by
|
||||
`Auth / Session Service`.
|
||||
- Freeze the need for create-only registration context on
|
||||
`EnsureUserByEmail`.
|
||||
- Freeze the exact create-only registration context shape on
|
||||
`EnsureUserByEmail`:
|
||||
- `preferred_language`
|
||||
- `time_zone`
|
||||
|
||||
### Deliverables
|
||||
|
||||
@@ -58,7 +66,9 @@ Remove naming ambiguity and freeze the service boundary before implementation.
|
||||
|
||||
- none yet beyond documentation review
|
||||
|
||||
## Stage 02 — Define Domain Entities and Redis-Backed Logical State
|
||||
## ~~Stage 02~~ — Define Domain Entities and Redis-Backed Logical State
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -97,7 +107,9 @@ without revisiting core semantics.
|
||||
- domain validation tests for required fields
|
||||
- tests for effective-state evaluation of active versus expired records
|
||||
|
||||
## Stage 03 — Implement Auth-Facing Resolution, Ensure, Existence, and E-Mail Blocking
|
||||
## ~~Stage 03~~ — Implement Auth-Facing Resolution, Ensure, Existence, and E-Mail Blocking
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -122,6 +134,12 @@ Provide the minimum trusted API needed by `Auth / Session Service`.
|
||||
- trusted internal REST handlers for auth-facing endpoints
|
||||
- domain services for resolution and block behavior
|
||||
- Redis-backed storage for user existence and blocked-email subjects
|
||||
- runnable `cmd/userservice` process using `Gin` and `go-redis/v9`
|
||||
- durable create path that already materializes:
|
||||
- opaque `user_id`
|
||||
- generated `player-<shortid>` race name
|
||||
- stored `preferred_language` and `time_zone`
|
||||
- initial free entitlement snapshot
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
@@ -137,22 +155,26 @@ Provide the minimum trusted API needed by `Auth / Session Service`.
|
||||
- block by user id on unknown user returns not found
|
||||
- repeated block calls stay idempotent
|
||||
|
||||
## Stage 04 — Add New-User Creation Context from Auth
|
||||
## ~~Stage 04~~ — Implement New-User Creation Context from Auth
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
Support first-login user creation with initial settings captured at confirm
|
||||
time.
|
||||
Tighten the already-implemented first-login create path with stricter semantic
|
||||
validation.
|
||||
|
||||
### Tasks
|
||||
|
||||
- Extend `EnsureUserByEmail` contract with create-only registration context:
|
||||
- Preserve the already-frozen create-only `EnsureUserByEmail`
|
||||
registration context with:
|
||||
- `preferred_language`
|
||||
- `time_zone`
|
||||
- Validate `preferred_language` as BCP 47.
|
||||
- Validate `time_zone` as IANA TZ name.
|
||||
- Generate initial `race_name` in `player-<shortid>` form during creation.
|
||||
- Initialize the newly created user with:
|
||||
- Tighten `preferred_language` validation to BCP 47 semantics.
|
||||
- Tighten `time_zone` validation to IANA TZ semantics.
|
||||
- Preserve generated initial `race_name` in `player-<shortid>` form during
|
||||
creation.
|
||||
- Preserve the newly created user initialization with:
|
||||
- free entitlement
|
||||
- no active sanctions
|
||||
- no custom limits
|
||||
@@ -161,9 +183,9 @@ time.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- extended ensure-by-email request model
|
||||
- create-user domain service
|
||||
- create-user domain service using the frozen ensure-by-email request model
|
||||
- generated-race-name helper
|
||||
- create-path validation for `preferred_language` and `time_zone`
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
@@ -177,7 +199,9 @@ time.
|
||||
- existing user ensure ignores create-only registration context
|
||||
- invalid BCP 47 or IANA inputs are rejected on create path
|
||||
|
||||
## Stage 05 — Implement Self-Service Account Read and Split Profile/Settings Mutations
|
||||
## ~~Stage 05~~ — Implement Self-Service Account Read and Split Profile/Settings Mutations
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -220,7 +244,9 @@ Expose the minimal authenticated account surface routed by `Edge Gateway`.
|
||||
- `UpdateMySettings` validates BCP 47 and IANA values
|
||||
- active `profile_update_block` denies both update flows
|
||||
|
||||
## Stage 06 — Implement race_name Uniqueness Policy Behind a Dedicated Interface
|
||||
## ~~Stage 06~~ — Implement race_name Uniqueness Policy Behind a Dedicated Interface
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -256,7 +282,9 @@ Keep `race_name` uniqueness strict and replaceable.
|
||||
- rename releases the old reservation only after the new one is secured
|
||||
- failed reservation backend causes mutation to fail closed
|
||||
|
||||
## Stage 07 — Implement Entitlement History Plus Materialized Current Snapshot
|
||||
## ~~Stage 07~~ — Implement Entitlement History Plus Materialized Current Snapshot
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -298,7 +326,9 @@ Support both auditability and fast synchronous entitlement reads.
|
||||
- free default is created for new users
|
||||
- extending or revoking access preserves deterministic current-state behavior
|
||||
|
||||
## Stage 08 — Implement Sanctions and Limit Records with Active/Effective Evaluation
|
||||
## ~~Stage 08~~ — Implement Sanctions and Limit Records with Active/Effective Evaluation
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -317,11 +347,23 @@ consumers.
|
||||
- `profile_update_block`
|
||||
- Freeze v1 limit catalog:
|
||||
- `max_owned_private_games`
|
||||
- `max_active_private_games`
|
||||
- `max_pending_public_applications`
|
||||
- `max_pending_private_join_requests`
|
||||
- `max_pending_private_invites_sent`
|
||||
- `max_active_game_memberships`
|
||||
- Freeze supported v1 limit semantics:
|
||||
- paid effective defaults:
|
||||
- `max_owned_private_games=3`
|
||||
- `max_pending_public_applications=10`
|
||||
- `max_active_game_memberships=10`
|
||||
- free effective defaults:
|
||||
- `max_owned_private_games` is omitted
|
||||
- `max_pending_public_applications=3`
|
||||
- `max_active_game_memberships=3`
|
||||
- `max_active_game_memberships` applies only to public games
|
||||
- `max_pending_public_applications` is the total public-games budget and is
|
||||
interpreted by `Game Lobby` together with current active public
|
||||
memberships
|
||||
- Keep legacy retired limit codes backward-compatible on reads, but reject
|
||||
them for new trusted limit commands.
|
||||
- Implement active/effective evaluation with current time.
|
||||
- Implement trusted explicit commands to apply/remove sanctions and set/remove
|
||||
limits.
|
||||
@@ -343,9 +385,14 @@ consumers.
|
||||
|
||||
- active sanctions appear in account reads
|
||||
- expired sanctions and limits stop affecting effective state
|
||||
- retired legacy limit records are ignored during reads and effective
|
||||
evaluation
|
||||
- retired legacy limit codes are rejected by trusted limit commands
|
||||
- applying and removing sanctions/limits is idempotent where appropriate
|
||||
|
||||
## Stage 09 — Implement Lobby Eligibility Snapshot API
|
||||
## ~~Stage 09~~ — Implement Lobby Eligibility Snapshot API
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -361,6 +408,16 @@ user-level access decisions.
|
||||
- active lobby-relevant sanctions
|
||||
- effective lobby-relevant limits
|
||||
- derived booleans for lobby decisions
|
||||
- Freeze the lobby-facing effective limit catalog:
|
||||
- paid users receive `max_owned_private_games=3`,
|
||||
`max_pending_public_applications=10`, and
|
||||
`max_active_game_memberships=10`
|
||||
- free users omit `max_owned_private_games` and receive
|
||||
`max_pending_public_applications=3` and
|
||||
`max_active_game_memberships=3`
|
||||
- `max_pending_public_applications` remains the total public-games budget
|
||||
consumed together with current active public memberships inside
|
||||
`Game Lobby`
|
||||
- Keep the response read-optimized so lobby does not need multiple dependent
|
||||
calls back into `User Service`.
|
||||
- Define deterministic not-found behavior.
|
||||
@@ -381,8 +438,12 @@ user-level access decisions.
|
||||
- lobby eligibility snapshot reflects paid status, sanctions, and limits
|
||||
- unknown user returns stable not-found behavior
|
||||
- derived booleans remain consistent with raw effective state
|
||||
- free and paid snapshots materialize the reduced three-code effective limit
|
||||
catalog correctly
|
||||
|
||||
## Stage 10 — Implement Geo declared_country Sync Command
|
||||
## ~~Stage 10~~ — Implement Geo declared_country Sync Command
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -416,7 +477,9 @@ Support the current-country denormalization path owned by `Geo Profile Service`.
|
||||
- invalid country codes are rejected
|
||||
- country sync emits the correct auxiliary event after commit
|
||||
|
||||
## Stage 11 — Implement Admin Lookup, Filtered Listing, and Explicit Trusted Mutations
|
||||
## ~~Stage 11~~ — Implement Admin Lookup, Filtered Listing, and Explicit Trusted Mutations
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -462,7 +525,9 @@ operations.
|
||||
- exact lookups by `user_id`, email, and `race_name` resolve the correct user
|
||||
- every trusted mutation preserves actor and reason metadata
|
||||
|
||||
## Stage 12 — Add Per-Domain-Area Async Events and Observability
|
||||
## ~~Stage 12~~ — Add Per-Domain-Area Async Events and Observability
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -505,7 +570,9 @@ truth.
|
||||
- event payloads include minimum required metadata
|
||||
- observability hooks do not change business behavior
|
||||
|
||||
## Stage 13 — Add Contract Tests Against Auth, Lobby, and Geo Expectations
|
||||
## ~~Stage 13~~ — Add Contract Tests Against Auth, Lobby, and Geo Expectations
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -542,7 +609,9 @@ must satisfy for other services.
|
||||
- lobby eligibility snapshot reflects paid status, sanctions, and limits
|
||||
- geo country sync changes only current `declared_country`
|
||||
|
||||
## Stage 14 — Add Rollout Notes for Gateway/Auth/OpenAPI Updates and Shared geoip
|
||||
## ~~Stage 14~~ — Add Rollout Notes for Gateway/Auth/OpenAPI Updates and Shared geoip
|
||||
|
||||
Status: implemented.
|
||||
|
||||
### Goal
|
||||
|
||||
@@ -551,11 +620,13 @@ its intended end-to-end form.
|
||||
|
||||
### Tasks
|
||||
|
||||
- Document the required `gateway` public `confirm-email-code` addition of
|
||||
- Document the required `gateway` public `confirm-email-code` dependency on
|
||||
`time_zone`.
|
||||
- Document the required `authsession` public OpenAPI preservation of the same
|
||||
`time_zone` requirement.
|
||||
- Document that the frozen `authsession -> user` ensure contract requires
|
||||
create-only `registration_context` with `preferred_language` and
|
||||
`time_zone`.
|
||||
- Document the required `authsession` public OpenAPI mirror change.
|
||||
- Document the required `authsession -> user` ensure contract extension for
|
||||
create-only registration context.
|
||||
- Document the required shared `pkg/geoip` package for gateway and geo.
|
||||
- Document README follow-up updates needed in `gateway` and `geoprofile`.
|
||||
- Define rollout order so the cross-service contract changes do not land in an
|
||||
|
||||
Reference in New Issue
Block a user