build: /spec-feature user-preferences --requirements 'CRUD API for user pref...
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
395ab89c1c
commit
6db90ac66d
@ -22,7 +22,7 @@ artifacts:
|
||||
status: pending
|
||||
path: review.md
|
||||
spec:
|
||||
status: pending
|
||||
status: draft
|
||||
path: spec.md
|
||||
tasks:
|
||||
status: pending
|
||||
|
||||
70
.sdlc/features/user-preferences/spec.md
Normal file
70
.sdlc/features/user-preferences/spec.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Feature: User Preferences API
|
||||
|
||||
## Problem Statement
|
||||
|
||||
Users need a way to persist and retrieve their application preferences (theme, language, notification settings) across sessions and devices. Currently, no preference storage exists — any customization is lost when a user logs out or switches devices. The preferences-api service exists as a scaffold with example CRUD patterns but has no preference-specific domain logic.
|
||||
|
||||
## User Stories
|
||||
|
||||
- As an authenticated user, I want to save my theme preference so that the UI matches my preference across sessions.
|
||||
- As an authenticated user, I want to set my preferred language so that the application displays in my chosen locale.
|
||||
- As an authenticated user, I want to configure my notification settings so that I only receive alerts I care about.
|
||||
- As a frontend application, I want to retrieve all preferences for a user in a single request so that the UI can be initialized efficiently.
|
||||
- As an authenticated user, I want to update individual preferences without overwriting all others so that partial updates are safe.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `GET /api/preferences-api/preferences/{user_id}` returns all preferences for a user as key-value pairs in the `{data, meta}` envelope
|
||||
- [ ] `PUT /api/preferences-api/preferences/{user_id}` creates or updates preferences for a user (upsert semantics)
|
||||
- [ ] Supported preference keys: `theme` (values: `light`, `dark`, `system`), `language` (ISO 639-1 codes, e.g. `en`, `fr`, `es`), `notifications_enabled` (boolean as string: `true`, `false`)
|
||||
- [ ] Unknown preference keys are rejected with a `400 Bad Request` and descriptive error
|
||||
- [ ] Invalid preference values are rejected with a `400 Bad Request` and descriptive error (e.g., `theme: "blue"` is invalid)
|
||||
- [ ] PUT is idempotent — sending the same request twice produces the same result
|
||||
- [ ] PUT supports partial updates — sending only `{"theme": "dark"}` does not clear `language` or `notifications_enabled`
|
||||
- [ ] GET for a user with no preferences returns `200` with an empty object `{}` (not 404)
|
||||
- [ ] Both endpoints require authentication via JWT (auth middleware)
|
||||
- [ ] Authenticated users can only access their own preferences (user_id in path must match JWT subject), returning `403 Forbidden` otherwise
|
||||
- [ ] Preferences are persisted in PostgreSQL with a migration
|
||||
- [ ] OpenAPI spec documents both endpoints with request/response schemas
|
||||
- [ ] Handler tests cover success, validation errors, not-found, and authorization cases
|
||||
- [ ] Service-layer tests cover business logic with mock repository
|
||||
- [ ] Response times < 50ms at p99 for single-user preference reads
|
||||
|
||||
## Technical Constraints
|
||||
|
||||
- Must follow existing hexagonal architecture: domain → service → port (interface) → adapter (implementation)
|
||||
- Handlers must return `error`, wrapped with `app.Wrap()`
|
||||
- Request binding must use `app.Bind()` or `app.BindAndValidate()`
|
||||
- Errors must use `httperror.BadRequest`, `httperror.NotFound`, `httperror.Forbidden` — never bare `http.Error()`
|
||||
- Responses must use `httpresponse.OK`, `httpresponse.Created`, `httpresponse.NoContent` with `{data, meta}` envelope
|
||||
- Routes mount under `/api/preferences-api` to match ingress routing
|
||||
- Database connection uses `pkg/database` with embedded SQL migrations
|
||||
- Auth middleware uses `pkg/auth` with JWT validation
|
||||
- The existing example CRUD code should be replaced, not left alongside preference code
|
||||
- `user_id` is a UUID, validated at the handler layer
|
||||
|
||||
## Dependencies
|
||||
|
||||
- PostgreSQL database available (connection via `DATABASE_URL` environment variable)
|
||||
- `pkg/database` package for connection pooling and migration support
|
||||
- `pkg/auth` package for JWT middleware and user extraction
|
||||
- JWT secret configured via `JWT_SECRET` environment variable
|
||||
- `AUTH_ENABLED=true` in production environments
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- User registration or authentication (handled by a separate auth service)
|
||||
- Preference inheritance or defaults cascade (e.g., org-level defaults)
|
||||
- Real-time preference sync via WebSockets
|
||||
- Preference history or audit trail
|
||||
- Bulk preference operations across multiple users
|
||||
- Frontend UI for preference management
|
||||
- Rate limiting on preference endpoints
|
||||
- Preference schema versioning or migration
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Default values**: Should `GET` return system defaults for keys that haven't been explicitly set (e.g., `{"theme": "system", "language": "en", "notifications_enabled": "true"}`) or only return keys the user has explicitly set?
|
||||
2. **DELETE support**: Should there be a `DELETE /preferences/{user_id}` to reset all preferences, or a `DELETE /preferences/{user_id}/{key}` to reset individual ones?
|
||||
3. **Extensibility**: When new preference keys are added in the future, should they be added to a configuration file/constant list, or is a code change acceptable?
|
||||
4. **Admin access**: Should admin users be allowed to read/write preferences for other users, or is self-access the only mode?
|
||||
Loading…
Reference in New Issue
Block a user