# AGENTS.md: Medusa v2

## Commands
- `npx medusa develop` (server + admin) · `npm run build` · `npm test` (integration tests use the framework's test runner if configured)
- Migrations: `npx medusa db:generate <module>` after changing a data model, then `npx medusa db:migrate`. Never edit applied migrations or the database by hand.

## Where code goes
- Custom domain logic: modules in `src/modules/<name>/` (data models with `model.define`, a service extending `MedusaService`, `index.ts` exporting `Module(...)`), registered in `medusa-config.ts`.
- Relations between modules: module links in `src/links/` with `defineLink`. Modules never import each other's services or tables directly.
- Business flows: workflows in `src/workflows/` built with `createWorkflow` and `createStep`. Every step that changes data has a compensation function so failures roll back.
- HTTP: API routes in `src/api/**/route.ts` exporting `GET`/`POST`/etc. Routes validate input (zod schemas with the validation middleware in `src/api/middlewares.ts`) and run a workflow; they don't contain business logic.
- Reactions to events: subscribers in `src/subscribers/` (handler + `config.event`). Background schedules: `src/jobs/`.
- Admin UI: widgets and routes in `src/admin/` using the Medusa UI components and the JS SDK.

## Rules
- Read data across modules with Query (`query.graph({ entity, fields, filters })`), not by calling many services in a loop.
- Use the commerce modules' workflows (e.g. cart, order, inventory) instead of writing to their tables; extend them with hooks where provided.
- Money: store and compute amounts as the framework does (no floating-point math you invent); always carry currency codes.
- Secrets (`JWT_SECRET`, `COOKIE_SECRET`, DB, payment provider keys) in `.env`, never committed. Configure CORS for store/admin/auth explicitly.
- Store API responses only include fields the storefront needs; never expose admin data on `/store` routes.

## Done when
Build passes, migrations generated for model changes, and an integration test or manual request shows the route/workflow behaving, including the failure path.
