Skip to main content

The prompt

title: "Scaffold the address module and its resources"
context: |
  Build an `address` domain: private postal addresses owned by a user (billing,
  shipping). Addresses are personal data, never readable by other users — auth
  is owner-or-admin on EVERY operation, reads and lists included. Each user has
  at most one default address. An address points at a shared `City` (city
  module) for city/region/country/coordinates; it stores only street-specific
  data. If `modules/address/` already exists, this work is void — do not run.
goal: |
  Create the `address` module + needed resources, wired owner-or-admin on every op.

  ## Notes
  - If `modules/address/` exists, STOP and report. Else `/module:create` address,
    then build each resource via its `*:create` skill (`--module=address`),
    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 read, list, update, delete — reuse the
    permission service, never hand-roll); migration if the project uses
    migrations; seed if it uses seeds; event/queue/translation/storage/workflow —
    skip (private data, no files, no lifecycle).
  - Depends on `city`: confirm `modules/city/` exists, wire a `City` relation, and
    reject an address whose `city` does not resolve. Do not duplicate city fields.
  - Single default per user: on create/update with `isDefault` true, atomically
    clear it on the user's other addresses.
  - Throw typed exceptions (e.g. `AddressNotFoundException`), never return null;
    another user's address must return the same not-found result.

  ### Data Model
  - `Address.owner` ↔ `User.addresses` — ManyToOne / OneToMany
  - `Address.city` ↔ `City.addresses` — ManyToOne / OneToMany
dod: |
  - [ ] Aborts with a report if `modules/address/` exists
  - [ ] `address` module created and registered into the app and `SharedModule`
  - [ ] `Address` entity with fields: `label`, `type` (billing/shipping),
    `recipient`, `phone`, `line1`, `line2` (nullable), `postalCode`, `city`
    (City relation), `latitude`/`longitude` (nullable), `isDefault`, `owner`,
    `createdAt`, `updatedAt`
  - [ ] Full CRUD; user accesses only their own, admin any; another user's
    address returns not-found
  - [ ] References a `City`, not free-text geo; unresolved `city` rejected
  - [ ] Setting default demotes the previous default
  - [ ] Unneeded resources skipped and reported with a reason
  - [ ] `bun run fmt`, `bun run lint`, `bun run test` pass from the root