> ## 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.

# Category Resource

> A ready-to-run spec that scaffolds the `category` module as a shared, admin-managed taxonomy with self-nesting, where only admins can mutate the tree.

## The prompt

```yaml theme={null}
title: "Scaffold the category module and its resources"
context: |
  Build a `category` domain: a shared taxonomy classifying content across the
  app. Categories nest (parent + children) into a hierarchy and record the owner
  who created them, but auth is role-based, not ownership-based: any
  authenticated user reads and lists; only an admin creates/updates/deletes.
  Slugs are unique. If `modules/category/` already exists, this work is void —
  do not run.
goal: |
  Create the `category` module + needed resources, wired admin-only on mutations.

  ## Notes
  - If `modules/category/` exists, STOP and report. Else `/module:create`
    category, then build each resource via its `*:create` skill
    (`--module=category`), respecting controllers → services → repositories →
    entities, registering all.
  - Dependency — `user`. Resolve before the `/module:create` step above: if
    `modules/user/` is missing, create it FIRST from its prompt at
    https://docs.ooneex.com/ai/prompts/resources/user-resource.
  - Judge each resource; create the justified, skip the rest with a reason.
    Defaults: entity + repository always; service + controller per use case;
    permission always (admin-only guard on create/update/delete, read/list open
    to any authenticated user, reuse the permission service); seed if the project
    uses seeds (base taxonomy); migration/event/translation/queue only if
    applicable (names are strong translation candidates); storage only if icons
    are uploaded files; workflow skip (flat taxonomy has no lifecycle).
  - Guard against cycles: a category may not be its own ancestor — reject
    self-parent/descendant updates.
  - Throw typed exceptions (e.g. `CategoryNotFoundException`), never return null.

  ### Data Model
  - `Category.parent` ↔ `Category.children` — self-referential ManyToOne / OneToMany
  - `Category.owner` ↔ `User.categories` — ManyToOne / OneToMany
dod: |
  - [ ] Aborts with a report if `modules/category/` exists
  - [ ] Missing dependency module (`user`) created first from its docs prompt
  - [ ] `category` module created and registered into the app and `SharedModule`
  - [ ] `Category` entity with fields: `name`, `slug` (unique), `description`,
    `icon`, `color` (`SimpleColorType`), `position`, `lang` (`LocaleType`),
    `parent` (nullable), `children`, `owner`, `createdAt`, `updatedAt`
  - [ ] Full CRUD; any authenticated user reads/lists; only admin mutates;
    non-admin rejected on create/update/delete
  - [ ] Tree-cycle updates rejected
  - [ ] If queues are used, category mutations run through a queue
  - [ ] Unneeded resources skipped and reported with a reason
  - [ ] `bun run fmt`, `bun run lint`, `bun run test` pass from the root
```
