# Register App Implementation Tasks

## Goal
Create a clear follow-up plan for user privileges (admin/member) and forgot-password flow hardening.

## Current Baseline
- Admin check already routes through `require_admin` -> `user_is_admin`.
- `user_is_admin` supports:
  - Group membership (`groups` + `user_group`)
  - `users.is_admin` fallback
  - `users.role` fallback
- Forgot-password UI already exists in `public/reset_password.php`.
- Admin password reset UI exists in `public/admin/password_reset.php`.

## Phase 1: Decide Privilege Model
- [ ] Choose one primary model for production:
  - RBAC tables (`groups`, `user_group`, `group_application`) as primary
  - `users.is_admin` boolean as primary
  - `users.role` enum/string as primary
- [ ] Keep fallback behavior documented so local/dev databases do not break.

## Phase 2: Schema Alignment
- [ ] Ensure RBAC tables exist (if using group-based permissions):
  - `groups`
  - `user_group`
  - `applications`
  - `group_application`
- [ ] Add missing forgot-password columns to `users` if absent:
  - `reset_token_hash` (VARCHAR(64), nullable)
  - `reset_expires_at` (DATETIME, nullable)
- [ ] Add indexes for reset flow:
  - `INDEX idx_users_email (email)`
  - `INDEX idx_users_reset_expires_at (reset_expires_at)`

## Phase 3: Seed Privileges
- [ ] Seed `admin` and `member` groups (if RBAC model).
- [ ] Assign at least one bootstrap admin account.
- [ ] Confirm first admin can access `/public/admin/users.php`.

## Phase 4: Admin Management UX
- [ ] Add admin controls on admin users page:
  - Grant admin
  - Revoke admin
  - Optional: assign/remove groups
- [ ] Add confirmation prompts for role changes.
- [ ] Log admin changes (who changed, target user, when).

## Phase 5: Forgot-Password Security Hardening
- [ ] Replace on-screen token display with delivery via email or secure channel.
- [ ] Return generic request response text for both existing and non-existing users.
- [ ] Add request throttling:
  - Per IP limit
  - Per account/email limit
- [ ] Enforce token lifetime policy (currently 1 hour).
- [ ] Ensure single-use token invalidation after password update.
- [ ] Add audit log entries for token request and token use.

## Phase 6: Operational Config and Paths
- [ ] Keep path/url generation centralized in helper functions only.
- [ ] Do not introduce direct hardcoded app paths in page files.
- [ ] Verify all redirects and links resolve under `/apps/register/public/*` and `/apps/register/php/*`.

## Phase 7: Tests and Verification
- [ ] Verify privilege scenarios:
  - Non-admin denied from admin pages
  - Admin allowed on admin pages
  - Role/group changes take effect on next request
- [ ] Verify forgot-password scenarios:
  - Request token for known account
  - Generic response for unknown account
  - Expired token rejected
  - Invalid token rejected
  - Valid token updates password and clears token fields
- [ ] Smoke test routes after migration:
  - `/public/login.php`
  - `/public/register.php`
  - `/public/reset_password.php`
  - `/public/admin/users.php`
  - `/public/admin/password_reset.php`

## SQL Snippets (Reference)
```sql
-- Add forgot-password columns if missing
ALTER TABLE users
  ADD COLUMN reset_token_hash VARCHAR(64) NULL,
  ADD COLUMN reset_expires_at DATETIME NULL;

-- Optional admin fallback model
ALTER TABLE users
  ADD COLUMN is_admin TINYINT(1) NOT NULL DEFAULT 0;

-- Grant one admin user by email
UPDATE users SET is_admin = 1 WHERE email = 'you@example.com';
```

## Definition of Done
- [ ] No fatal errors when RBAC tables are missing.
- [ ] At least one intentional and tested admin assignment path.
- [ ] Forgot-password flow is secure enough for production (no token leakage in UI).
- [ ] Route/path behavior remains centrally controlled and upgrade-safe.
