build: /spec-feature user-preferences --requirements 'CRUD API for user pref...
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
rdev-worker 2026-02-07 23:15:27 +00:00
parent 395ab89c1c
commit 6db90ac66d
2 changed files with 71 additions and 1 deletions

View File

@ -22,7 +22,7 @@ artifacts:
status: pending
path: review.md
spec:
status: pending
status: draft
path: spec.md
tasks:
status: pending

View 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?