# Module Subscription APIs

These endpoints sit alongside the existing `/subscription` routes and assume the schema from `module_subscription_tables.sql`.

## 1. Module Catalog

### GET `/modules`
- **Purpose**: list every module with status and metadata (used to render toggle options)
- **Auth**: Admin or system user
- **Response**: array of `{id, code, name, description, is_toggleable, is_premium, default_status, status}`

### POST `/modules`
- **Purpose**: create a new module definition
- **Body**: `{code, name, description?, is_toggleable?, is_premium?, default_status?, config?}`
- **Response**: created module record

### PUT `/modules/:id`
- **Purpose**: update module metadata / toggle availability
- **Body**: same fields as POST (partial updates)
- **Notes**: can also soft-disable a module by setting `status = 'inactive'`

## 2. Parent Module Entitlements

### GET `/parents/:parentId/modules`
- **Purpose**: show which modules a parent currently has, including status and dates
- **Response**: array of `parent_module_subscriptions` rows joined with module metadata
- **Frontend use**: show toggles and disable switches that are inactive/expired

### POST `/parents/:parentId/modules`
- **Purpose**: manually grant or revoke a module for a parent
- **Body**: `{module_id, action: 'grant'|'revoke', duration_days?, notes?}`
  - If `grant`, calculate `start_date` (default NOW) and `end_date` (NOW + duration)
  - If `revoke`, mark existing row `status = 'revoked'`
- **Auth**: Admin or school operator

### PATCH `/parents/:parentId/modules/:moduleId`
- **Purpose**: extend, shorten, or change status/details for a module entitlement
- **Body**: `{end_date?, status?, notes?}`

## 3. Subscription-driven Sync

### POST `/subscriptions/:subscriptionId/modules-sync`
- **Purpose**: whenever a subscription plan is sold/renewed/cancelled, sync the set of modules that should be active for all parents linked to that plan
- **Flow**:
  1. Look up plan features JSON → derive module codes
  2. Upsert entries in `parent_module_subscriptions` with `grant_source = 'plan'`
  3. Disable entries if plan expired/cancelled
- **Response**: summary `{granted: n, revoked: m}`

## 4. Context helper

### GET `/me/modules`
- **Purpose**: quickly fetch the active modules for the logged-in parent (using `verifyToken`)
- **Frontend use**: call once after login and cache available features such as `position_lock`

## Implementation Notes
1. **Middleware**: extend existing JWT middleware to attach `req.user.modules` by querying `parent_module_subscriptions` for active entries whose `end_date >= CURDATE()` (or null).
2. **Plan configuration**: use `subscription_plans.features` JSON to list module codes that a plan includes, so `/modules-sync` knows what to grant.
3. **Auditing**: `granted_by` stores the admin user performing manual changes. For automated sync, set to `NULL` and `grant_source = 'plan'`.
4. **Position Lock enforcement**: when the frontend wants to call a protected operation, it can first check whether `position_lock` appears in `/me/modules`. Backend should also guard sensitive routes by verifying module entitlement server side.
