# CLAUDE.md

Guidance for working in this repo. Read the spec docs before making changes; this
file is the index + the rules that must always hold.

## Project
Amaleena — online gold jewellery store (Amaleena Jewel Sdn Bhd), rebuilt in Laravel
to replace a WooCommerce site. Bilingual **BM (default) + English**, Malaysia-only.
Prices track the live gold price. Features beyond catalog/cart/checkout: computed
gold pricing, trade-in, affiliate, reviews, store credit / e-voucher.

## Spec docs (source of truth — read first)
- **task.md** — phased build plan; what to build next and in what order.
- **requirement.md** — `R#` acceptance criteria + NFRs.
- **design.md** — architecture, interfaces, flows, enums, security.
- **database.md** — full schema (tables, columns, keys, indexes).
- **structure.md** — code layout and where each kind of logic goes.
- **tech.md** — stack, design tokens, fonts, commands, deployment.
- **product.md** — business context, features, and rules.

## Golden rules (non-negotiable)
1. **Money = integer cents**; weight = `decimal(6,2)` grams. Format only in views.
2. **Prices are computed, never stored**: `weight × gold_price_per_gram(purity) + upah`
   (upah per-gram or flat per product). Snapshot weight/purity/gold price/upah/unit
   price onto `order_items` at placement. **Never recompute a placed order.**
3. **Never trust client input** — recompute prices server-side; verify ownership of
   every ID (no IDOR). Validate with Form Requests; authorize with Policies/Gates.
4. **Store credit / vouchers**: redeem atomically (`lockForUpdate` + ledger row) —
   no double-spend.
5. **Payment callbacks**: verify signature, idempotent transitions, confirm callback
   amount == order total. Log without secrets.
6. **Backed enums** for every status/type; no free-text status columns.
7. **No hardcoded UI strings** — use `lang/ms` + `lang/en`; translatable model content
   via spatie/laravel-translatable (locale-keyed JSON).
8. **No hardcoded hex** — use theme tokens in `resources/css/theme.css`.
   Brand: purple `#720eec`, warm gold `#c4a35c`, on white. Fonts: **Cinzel**
   (wordmark/labels), **Cormorant Garamond** (headlines), **Jost** (body/UI).
9. Guarded mass-assignment; secrets only in `.env`; `APP_DEBUG=false` in prod;
   passwords hashed; rate-limit auth/OTP/reset/checkout.

## Architecture conventions
- Flow: thin Controller/Livewire → Form Request (validate) → Policy (authorize) →
  Action/Service (logic, DB transaction) → Eloquent → view/redirect.
- **Actions** = one write use-case each (`PlaceOrder`, `RedeemStoreCredit`,
  `ApproveTradeIn`). **Services** = calculations/reads (`PricingService`,
  `ShippingCalculator`). **Models** = relations/casts/scopes only — no business rules.
- Eager-load to avoid N+1; paginate every list; queue slow work (email, commission).
- Strict types + explicit return types; PSR-12 (Pint); Laravel conventions.
- **Keep CSS/JS external**: styles in `resources/css` (`theme.css` + component CSS via
  Vite), behaviour in Alpine or component scripts. Avoid large inline `style=""` or
  `<script>` blocks — small Alpine attributes are fine.

## Commands
```bash
composer install && npm install
php artisan serve            # app
npm run dev                  # assets (dev)
./vendor/bin/pint            # format (PSR-12)
php artisan test             # Pest
npm run build                # compiled assets for shared hosting
```

## Workflow
- Follow **task.md** phases in order; keep each change scoped to its task. Do **not**
  scaffold migrations/models/controllers/services/tests/views all at once.
- Add tests for: pricing (per-gram/flat/override/range), order snapshot/price-lock,
  authz/IDOR, credit redemption (no double-spend), payment callback idempotency,
  affiliate attribution/self-referral, review moderation, locale switching.
- Run `pint` + `php artisan test` before finishing; tick the task.md checkbox.

## Output & token efficiency
- Be concise and action-oriented; recommended solution first. No long preambles,
  and don't restate the request.
- Show only the **relevant code block or diff** — state the filename and where the
  change belongs. Do **not** regenerate whole files or repeat unchanged code unless
  explicitly asked.
- Prefer editing an existing file over creating a new one.
- Mention an alternative only when it has a meaningful trade-off; don't list many.
- Ask a question only when a missing detail would change the implementation;
  otherwise assume, and state the assumption briefly.

## Stack
Laravel 13, PHP 8.3+, Livewire + Alpine + Tailwind + Vite, MySQL 8, Filament (admin),
Fortify (auth). Deploy: cPanel/shared hosting — DB queue drained by cron
`schedule:run`, compiled assets uploaded, `migrate --force`.

## Swappable interfaces
- `App\Services\GoldPriceProvider` — manual admin entry by default (API feed later).
- `App\Payments\PaymentGateway` — impl TBD (ToyyibPay/Billplz assumed).

## Do not
- Invent Laravel APIs, packages, or commands — verify against installed deps.
- Add a second library for a job something installed already does.
- Hardcode prices, hex colours, or user-facing strings.
- Weaken any golden rule for convenience.

## Open decisions (non-blocking; confirm at the relevant phase)
- Payment gateway + credentials (Phase 5).
- Gold price: keep manual, or add API feed (Phase 1).
- Courier/tracking integration vs manual tracking numbers (Phase 10).
- Locale URL strategy: session switch vs `/en` prefix (Phase 0).
