# Acelle — Project Guide for Claude

## Quy tắc bắt buộc

**Khi implement xong bất kỳ thay đổi nào ảnh hưởng đến design (flow mới, API mới, thay đổi behavior), phải update `docs/` ngay trong cùng task đó.** Không để docs lạc hậu so với code.

---

## Documentation

**All design is in `docs/`** — đọc trước khi làm bất kỳ task nào liên quan:

| Folder | Nội dung |
|--------|----------|
| `docs/APP_STRUCTURE.md` | App structure rules, layering, folders, conventions |
| `docs/UI.md` | UI composition rules, helper controls, view conventions |
| `docs/athena/` | Athena EVS plugin — email verification service |
| `docs/subscription/` | Subscription & payment system |
| `docs/warmup/` | Warmup strategy module |

Mỗi folder có: `README/ARCHITECTURE`, `STORIES` (requirements), `CODE` (implementation design), `API`, `USAGE`, `TESTS`.

## App Rules

- Mọi rule liên quan UI/CSS/new views phải follow `docs/UI.md`. Không duplicate design rules ở nhiều nơi; `CLAUDE.md` chỉ reference source of truth này.
- Với warmup strategy, text mới phải nằm trong `resources/lang/en/warmup.php` và dùng `trans('warmup...')`. Không thêm text mới vào `messages.php` cho module warmup đã refactor.
- Warmup strategy phải đi theo layering rõ ràng: `FormRequest` -> `DTO` -> `Service` -> `Model/View`.
- Không nhét logic validate/save/business flow vào controller. Controller chỉ orchestration.
- Khi đổi schema/behavior/UI warmup, phải update `docs/warmup/README.md` và `docs/warmup/CODE.md` cùng task đó.

## Warmup Strategy

Warmup strategy là module admin để định nghĩa cách tăng sản lượng gửi cho SMTP server mới hoặc server dormant.

**Source of truth:**

- Product/behavior: `docs/warmup/README.md`
- Code architecture: `docs/warmup/CODE.md`
- App structure conventions: `docs/APP_STRUCTURE.md`
- UI/helper conventions: `docs/UI.md`

**Implementation rules:**

- UI create/edit phải align với `docs/UI.md`.
- Form validation phải nằm ở request layer.
- DTO dùng để trao đổi typed data giữa request/controller/service.
- `WarmupStrategyService` xử lý create/update/list/assign/preset/preview logic.
- `WarmupStrategy` model giữ constants, casts, scopes, relation/read helpers.
- Custom CSS cho warmup đặt ở `public/core/css/app.css` với class tường minh `warmup-*`.

---

## Athena EVS Plugin

Plugin tại `storage/app/plugins/athena/evs/` — kết nối 2 Acelle instance:

- **Main App** — UI, web controllers, plugin views
- **Remote** (`ATHENA_EVS_API_ENDPOINT` env) — accounts, billing, Stripe, verification engine

**API controller (remote side):** `app/Http/Controllers/Api/AthenaVerificationConnectorController.php`

**Token storage:** `athena_evs_tokens` table — `AthenaEvsToken` model, `AthenaTokenStore` service. Không có token → `['error' => 'no_token']` → controller trả 401 hoặc hiện `token_lost.blade.php`.

**CSS:** `acm-*` namespace (`acm-box`, `acm-plan-card`, `acm-btn-primary`, v.v.)

**Tests:** `tests/Unit/AthenaEvs/` — `php artisan test --filter=AthenaEvs --exclude-group=live`

---

## Subscription & Payment System

**Category A — Local Charge** (app quản lý lifecycle):
Stripe card-token, Braintree, Paystack, PayPal, Razorpay, Offline

**Category B — Remote Subscription** (provider quản lý, app sync):
StripeSubscription, BraintreeSubscription

### Remote Plan Mapping (Category B)
- Admin map local `PlanGeneral` ↔ remote Stripe Price / Braintree Plan
- Validate: price + currency + interval phải khớp
- UI: `/admin/plans/remote-mapping`
- **3-layer validation**: UI disable → Controller check → Checkout redirect (không để 500)

### Sync Architecture
1. **PRIMARY**: `remote:sync --all --scheduled` mỗi 5 phút (cron trong `routes/console.php`)
2. **SECONDARY**: Webhooks (`/cashier/webhooks/stripe-subscription`, `/cashier/webhooks/braintree-subscription`)
3. **IMMEDIATE**: Admin sync button

### Subscription Lifecycle Guards
Scheduler (`endIfExpired`, `checkAndCreateRenewOrder`, `autoChargeRenewOrders`) **skip** Category B subs — provider tự quản.

Cancel/terminate/end → `cancelRemoteSubscriptionIfExists()` gọi provider API trước.

### Logging
Mọi state change → `subscription_logs` via `SubscriptionFacade::log()`. Remote types: `TYPE_REMOTE_SYNC`, `TYPE_REMOTE_CANCEL`, `TYPE_REMOTE_ACTIVATE`, `TYPE_REMOTE_CHANGE_PLAN`, `TYPE_REMOTE_PAYMENT_FAILED`.

**Tests:** `tests/Unit/RemoteSubscription/` — `SKIP_STRIPE_LIVE_TESTS=true vendor/bin/pest tests/Unit/RemoteSubscription/`

---

## Console Commands

```bash
php artisan remote:check [--gateway=uid] [--subscription=uid]
php artisan remote:sync [--all] [--gateway=uid] [--subscription=uid] [--plans] [--stale-hours=N] [--scheduled]
php artisan test --filter=AthenaEvs --exclude-group=live
SKIP_STRIPE_LIVE_TESTS=true vendor/bin/pest tests/Unit/RemoteSubscription/
```

## Current Branch
`develop-remote-subscription`
