Skip to main content

The prompt

title: "Scaffold the image module and its resources"
context: |
  Build an `image` domain: users upload images they own; admins manage any. The
  source file is stored by the app (not external URLs), and a new image runs
  through a pipeline (upload → processing → ready) that derives a thumbnail and
  resized variants and extracts dimensions before it is usable. Auth is
  owner-or-admin on every mutation. If `modules/image/` already exists, this
  work is void — do not run.
goal: |
  Create the `image` module + needed resources, wired owner-or-admin on mutations.

  ## Notes
  - If `modules/image/` exists, STOP and report. Else `/module:create` image,
    then build each resource via its `*:create` skill (`--module=image`),
    respecting controllers → services → repositories → entities, registering all.
  - Judge each resource; create the justified, skip the rest with a reason.
    Defaults: entity + repository always; service + controller per use case;
    permission always (owner-or-admin on update/delete, reuse the permission
    service); storage always (source + thumbnail + derived variants); queue if
    the project uses queues (route uploads/re-processing — resizing is
    long-running); workflow yes (reversible upload → processing → ready that
    rolls back artifacts + DB together on failure); migration/seed/event/
    translation only if applicable (alt text and title are translation candidates).
  - On delete, remove the source, thumbnail, and every variant; never orphan blobs.
  - Throw typed exceptions (e.g. `ImageNotFoundException`), never return null.

  ### Data Model
  - `Image.owner` ↔ `User.images` — ManyToOne / OneToMany
dod: |
  - [ ] Aborts with a report if `modules/image/` exists
  - [ ] `image` module created and registered into the app and `SharedModule`
  - [ ] `Image` entity with fields: `title`, `slug` (unique), `description`,
    `alt`, `src`, `thumbnail` (derived), `variants` (derived), `mimeType`,
    `width`, `height`, `size`, `blurhash` (nullable), `status` (`StatusType`,
    processing → ready), `lang` (`LocaleType`), `owner`, `createdAt`, `updatedAt`
  - [ ] Full CRUD (create = upload); source + thumbnail + variants stored via
    storage, not URLs
  - [ ] User mutates only their own, admin any; non-owner/non-admin rejected
  - [ ] Delete removes source + thumbnail + variants
  - [ ] Lifecycle rolls back artifacts + DB together on failure
  - [ ] If queues are used, uploads/re-processing 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