> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# User Resource

> A ready-to-run spec that scaffolds the `user` module as the identity core — the user profile — with self-service on your own profile and admin control over any account.

## The prompt

```yaml theme={null}
title: "Scaffold the user module and its resources"
context: |
  Build a `user` domain: the identity at the centre of everything — almost every
  other module points an `owner` at `User`. A profile is private: a user sees and
  edits only their own; an admin manages any account. Auth is owner-or-admin on
  profile reads/updates; listing the full user base is admin-only. Registration
  is open (anonymous visitor creates their own account); only an admin may
  lock/ban/block/delete. Align the entity to `IUser` from the `@ooneex/user`
  package (extends `IBase`: `isLocked`, `isBanned`, `isBlocked`, `isPublic`,
  `language`, soft-delete `deletedAt`) — reuse its enums and types. If
  `modules/user/` already exists, this work is void — do not run.
goal: |
  Create the `user` module + needed resources, self-service profile + admin control.

  ## Notes
  - If `modules/user/` exists, STOP and report. Else `/module:create` user, then
    build each resource via its `*:create` skill (`--module=user`), respecting
    controllers → services → repositories → entities, registering all.
  - Model `User` against `IUser`; reuse the package's enums/string-literal types.
  - Judge each resource; create the justified, skip the rest with a reason.
    Defaults: entity + repository always; service + controller per use case (open
    registration, read/update own profile, admin list, admin lock/ban/block/
    delete); permission always (owner-or-admin on profile read/update, admin-only
    list, reuse the permission service); event yes (most-subscribed lifecycle —
    registered, banned — so other modules react without coupling); seed if the
    project uses seeds (bootstrap admin); queue for notification emails if a queue
    exists; migration only if applicable; translation/storage/workflow skip
    (avatar is a reference; flows are transactional service logic).
  - Never store/return secrets in the clear: hash passwords, keep them out of
    every read/list response, compare server-side only.
  - Enforce email uniqueness; throw a typed conflict (`UserAlreadyExistsException`)
    at registration.
  - Lock/ban/block are admin-only state, not deletion: such users are rejected at
    auth with a typed exception; deletion is a soft delete (`deletedAt`) that
    preserves the owner relations other modules hold.
  - Throw typed exceptions (e.g. `UserNotFoundException`), never return null;
    another user's profile must return the same not-found result.

  ### Data Model
  - Every other module's `owner` points back here via `@ManyToOne(() => User)`;
    this module owns the inverse only where it tracks the collection.
dod: |
  - [ ] Aborts with a report if `modules/user/` exists
  - [ ] `user` module created and registered into the app and `SharedModule`
  - [ ] `User` entity aligned to `IUser` with fields: `email` (unique), `roles`,
    `externalId` (nullable), `username` (nullable), `name` (nullable),
    `firstName`/`lastName` (nullable), `avatar` (nullable), `bio` (nullable),
    `phone` (nullable), `birthDate` (nullable), `timezone` (nullable), `lang`
    (`LocaleType`), `isLocked`/`lockedAt`, `isBanned`/`bannedAt`/`banReason`,
    `isBlocked`/`blockedAt`/`blockReason`, `isPublic`, `createdAt`, `updatedAt`,
    `deletedAt` (nullable)
  - [ ] Anonymous visitor can register; user reads/updates only their own
    profile; admin reads/updates/locks/bans/blocks/deletes any; listing is
    admin-only; another user's profile returns not-found
  - [ ] Duplicate email rejected; passwords hashed, secrets never leave the server
  - [ ] Locked/banned/blocked user rejected at authentication
  - [ ] Deletion is a soft delete preserving other modules' owner relations
  - [ ] Lifecycle events (registered, banned) emitted
  - [ ] Unneeded resources skipped and reported with a reason
  - [ ] `bun run fmt`, `bun run lint`, `bun run test` pass from the root
```
