# INVEETAIRE
## SPRINT 3 PLANNING DOCUMENT

| Field | Value |
|-------|-------|
| Document Type | Sprint Planning |
| Subject | Inveetaire Sprint 3 — Workspace Module & Tenant Isolation |
| Version | 1.0 |
| Status | Ready for Review |
| Prerequisite | Sprint 2 ✅ COMPLETE (committed, pushed, and closed) |
| Framework | Frozen — app/core/*, MiddlewarePipeline, Router, BaseController are immutable |
| Based On | MIB v1.1 · DBP v1.1 · AI.md v1.1 · ADR v1.0 · PDD v1.0 · SPRINT2_ARCHITECTURE_REVIEW.md |

---

## 1. Sprint Objective

The primary objective of Sprint 3 is to deliver the core **Workspace Module** and establish a secure, robust **Multi-Tenant Isolation** boundary. This sprint transitions the platform from a single-tenant prototype with unified login into a true multi-tenant SaaS architecture.

By the end of Sprint 3:
1. Super Admins must be able to provision new workspaces (including automatic generation of the associated couple account, default invitation skeleton, setup checklist, WhatsApp templates, and printer configurations) atomically in a database transaction.
2. The couple dashboard must display an interactive 7-step setup checklist that dynamically reads system state to guide user setup.
3. Workspaces must transition through logical operational phases (provisioned, setup, active, live, post_event, archived, purged) based on date boundaries and database triggers.
4. All couple and event crew routes must be protected by `App\Middleware\WorkspaceMiddleware` that enforces absolute workspace-level isolation based on the user's authenticated session boundaries.
5. Pending security technical debt (CSP, rate-limiting, reset token cleanup) from Sprints 1 and 2 must be fully resolved.

---

## 2. Sprint Scope

Sprint 3 is scoped strictly to:
1. **Pre-checklist Hardening:**
   * **TD-002:** Implement a baseline Content-Security-Policy (CSP) inside `public/.htaccess`.
   * **TD-009:** Implement IP and email-based rate-limiting on forgot password requests inside `AuthService`.
   * **TD-010:** Implement expired password reset token cleanup utility.
2. **WS-001 — Workspace Provisioning (Super Admin):**
   * Implement workspace creation form for Super Admins.
   * Atomic generation of: `workspaces` record, `users` (couple) record, default `invitations` record, default `invitation_sections` records, `retention_policies` record, default `message_templates`, and default `printer_configurations` using PDO database transactions.
3. **WorkspaceMiddleware:**
   * Implement concrete `App\Middleware\WorkspaceMiddleware` to isolate couple/crew routes by matching session `workspace_snapshot` against active database workspaces.
4. **WS-002 — Workspace Setup Checklist:**
   * Implement checklist resolver evaluating workspace readiness across 7 logical steps.
   * Render an interactive checklist widget on the Couple Dashboard.
5. **WS-003 — Workspace Phase Transitions:**
   * Implement workspace lifecycle evaluator transitioning workspaces between phases based on dates/events.
   * Enforce feature gate blocks (e.g., check-in only during `live` phase).

### Out of Scope for Sprint 3:
* Theme template parsing, layout selection, or customized CSS builder forms (Sprint 4).
* Guest imports from CSV/Excel or guest list management UI (Sprint 5).
* Real SMTP email integration (simulated local log delivery remains).

---

## 3. Sprint Deliverables

| Deliverable | Task ID | Type | File(s) |
|-------------|---------|------|---------|
| Security Hardening | TD-002 | Modified | `public/.htaccess` |
| Security Hardening | TD-009/10 | Modified | `app/modules/Auth/AuthService.php`, `AuthController.php` |
| Concrete Middleware | INIT-009 | New File | `app/middleware/WorkspaceMiddleware.php` |
| Workspace Module | WS-001 | New Module | `app/modules/Workspace/WorkspaceController.php`<br>`app/modules/Workspace/WorkspaceService.php`<br>`app/modules/Workspace/WorkspaceModel.php`<br>`app/modules/Workspace/WorkspaceValidator.php`<br>`app/modules/Workspace/routes.php` |
| Centralized View | WS-001 | New File | `app/views/workspace/create.php` |
| Setup Checklist Component | WS-002 | New File | `app/views/components/checklist_widget.php` |
| Setup Checklist Logic | WS-002 | Modified | `app/modules/Workspace/WorkspaceService.php` |
| Phase Transitions | WS-003 | Modified | `app/modules/Workspace/WorkspaceService.php`<br>`app/modules/Workspace/WorkspaceModel.php` |

---

## 4. Dependency & Extension Points Review

### 4.1 Prerequisites
1. **Database Schema:** The tables `workspaces`, `users`, `invitations`, `invitation_sections`, `retention_policies`, `message_templates`, `printer_configurations`, and `audit_logs` must be present and correctly structured as defined in PDD v1.0.
2. **Commercial Plans & Event Types:** Master event type IDs and commercial plan IDs must be seeded in the database (e.g., plans: Lite, Standard, Premium; event types: Wedding, Engagement).

### 4.2 Extension Points Used
1. **Middleware Pipeline:** `App\Middleware\WorkspaceMiddleware` registers in the pipeline and is referenced via its fully-qualified class name in route definitions.
2. **Module Autoloading:** Autoloader automatically maps `App\Modules\Workspace\...` to `app/modules/Workspace/`.
3. **Base Class Inheritance:** `WorkspaceController` extends `BaseController`, `WorkspaceModel` extends `BaseModel`, and `WorkspaceService` extends `BaseService`.

---

## 5. Task Definitions

### WS-001 — Build Workspace Provisioning (Super Admin)
* **Objective:** Atomically provision a tenant workspace and its default configurations.
* **Scope:**
  * Route GET `/app/admin/workspaces/create` rendering the provisioning form (Super Admin only).
  * Route POST `/app/admin/workspaces/create` capturing input: `groom_name`, `bride_name`, `wedding_date`, `event_type_id`, `commercial_plan_id`, and `slug`.
  * Validate inputs using `WorkspaceValidator` (e.g., unique and URL-safe slug, valid date).
  * `WorkspaceService::provision()` executes a database transaction:
    1. Insert into `workspaces` (status: `provisioned`).
    2. Insert into `users` (Couple user account; generate temp password, send via session flash).
    3. Insert default row into `retention_policies` (based on commercial plan retention defaults).
    4. Insert default rows into `invitations` (pinned theme, draft status) and `invitation_sections` (default sections visibility).
    5. Insert 3 default row records into `message_templates` (types: `invitation`, `h1_reminder`, `wedding_day_reminder`).
    6. Insert default row into `printer_configurations`.
    7. Commit transaction. Roll back on any failure to prevent orphaned data.
* **Files Expected [NEW]:**
  * `app/modules/Workspace/WorkspaceController.php`
  * `app/modules/Workspace/WorkspaceService.php`
  * `app/modules/Workspace/WorkspaceModel.php`
  * `app/modules/Workspace/WorkspaceValidator.php`
  * `app/views/workspace/create.php` (centralized view layout)
  * `app/modules/Workspace/routes.php`
* **Files Modified:**
  * `routes/admin.php` (include Workspace routes file)
* **Estimated AI Coding Sessions:** 2 sessions.

### Concrete Middleware — WorkspaceMiddleware
* **Objective:** Enforce multi-tenant resource access limits on authenticated requests.
* **Scope:**
  * Create `WorkspaceMiddleware.php` implementing `MiddlewareInterface`.
  * Intercept incoming requests to `/app/couple/*` and `/app/crew/*`.
  * Extract `workspace_snapshot` (for Couple/Crew) from session.
  * If user role is `super_admin`:
    * Verify active support session context exists in `support_sessions` if trying to adopt workspace context. Otherwise, bypass checks for standard global admin views.
  * Query DB to confirm the workspace exists, is active (status not `purged`), and that the user belongs to it (`users.workspace_id` matches).
  * On mismatch or inactive workspace, immediately abort with a `403 Forbidden` response via `ErrorHandler::renderForbidden()`.
* **Files Expected [NEW]:**
  * `app/middleware/WorkspaceMiddleware.php`
* **Files Modified:**
  * `routes/couple.php` (register `App\Middleware\WorkspaceMiddleware` fully-qualified class in group stack)
  * `routes/crew.php` (register `App\Middleware\WorkspaceMiddleware` fully-qualified class in group stack)
* **Estimated AI Coding Sessions:** 1 session.

### WS-002 — Build Workspace Setup Checklist
* **Objective:** Guide couples through the dashboard setup sequence using dynamic checkmarks.
* **Scope:**
  * Create checklist component `checklist_widget.php` displaying 7 setup steps:
    1. Workspace Provisioned (always checked).
    2. Configure Invitation details (checked if invitation status is not `draft`).
    3. Select Theme (checked if `invitations.theme_version_id` is set).
    4. Add First Guest (checked if guest count > 0).
    5. Configure Printer settings (checked if `printer_configurations` modified).
    6. Create First Wedding Event (checked if event count > 0).
    7. Ready to Send (unlocks invitation distribution).
  * Checklist evaluation flow:
    * `WorkspaceService` evaluates the checklist completion status.
    * `WorkspaceModel` executes database queries to retrieve count metrics.
    * Views render the output template and never query the database directly.
  * Disable invitation send UI button until minimum steps are marked complete.
* **Files Expected [NEW]:**
  * `app/views/components/checklist_widget.php`
* **Files Modified:**
  * `app/modules/Workspace/WorkspaceService.php` (add checklist status evaluation logic)
* **Estimated AI Coding Sessions:** 1 session.

### WS-003 — Build Workspace Phase Transitions
* **Objective:** Manage tenant lifecycle boundaries based on event timestamps.
* **Scope:**
  * Implement `WorkspaceService::evaluatePhase($workspaceId)` to check:
    * `wedding_date` date boundaries.
    * Workspace lifecycle evaluation consists of three logical stages:
      **Phase Evaluation** (determining target phase based on current date) ➔ **Persistence** (writing updated status to `workspaces` table) ➔ **Audit Logging** (creating history trail in `audit_logs`).
    * If `wedding_date` is in the future → Phase is `setup` or `active`.
    * If `wedding_date` is today → Transition phase to `live` (enable live check-in interfaces).
    * If `wedding_date` is in the past → Transition phase to `post_event` (enable final report generation, freeze check-ins).
  * Log phase transition events to `audit_logs` (non-foreign-key lookup).
* **Files Expected:** None (modifies existing Workspace Module files).
* **Files Modified:**
  * `app/modules/Workspace/WorkspaceService.php`
  * `app/modules/Workspace/WorkspaceModel.php`
* **Estimated AI Coding Sessions:** 1 session.

---

## 6. Execution Order

The execution sequence must proceed according to strict dependencies:

```
[Pre-checklist: Security Hardening (CSP + Rate Limit)]
                         │
                         ▼
             [WorkspaceMiddleware]
                         │
                         ▼
        [WS-001: Workspace Provisioning]
                         │
             ┌───────────┴───────────┐
             ▼                       ▼
     [WS-002: Checklist]     [WS-003: Phases]
```

1. **Pre-checklist:** Implement CSP in `.htaccess`, rate limit in `AuthService`, and expired token cleanup.
2. **Step 1:** Implement `WorkspaceMiddleware` to establish the tenant security guard.
3. **Step 2:** Implement `WS-001` (Super Admin provisioning controller, model, service, views, and routes).
4. **Step 3:** Implement `WS-002` (Setup Checklist widgets and dynamic resolver queries).
5. **Step 4:** Implement `WS-003` (Phase transitions lifecycle).

---

## 7. Expected Repository Changes

### New Folders
* `app/modules/Workspace/`
* `app/views/workspace/`

### New Files
* `app/middleware/WorkspaceMiddleware.php`
* `app/modules/Workspace/WorkspaceController.php`
* `app/modules/Workspace/WorkspaceService.php`
* `app/modules/Workspace/WorkspaceModel.php`
* `app/modules/Workspace/WorkspaceValidator.php`
* `app/views/workspace/create.php`
* `app/modules/Workspace/routes.php`
* `app/views/components/checklist_widget.php`

### Existing Files Modified
* `public/.htaccess` (CSP integration)
* `app/modules/Auth/AuthService.php` (rate limiting, reset token cleanup)
* `app/modules/Auth/AuthController.php` (token cleanup routing/calls)
* `routes/admin.php` (wire workspaces routes)
* `routes/couple.php` (wire dashboard checklist / middleware)
* `routes/crew.php` (wire middleware)

---

## 8. Architectural Constraints

* **Strict Tenancy Isolation:** Every database select, update, or delete inside workspace-scoped queries must contain a parameterized `WHERE workspace_id = :workspace_id` clause. Models must never query tenant data globally.
* **Transactional Integrity:** Workspaces have multiple child configuration rows. Provisioning must run inside a PDO transaction block. If any insert throws an exception, the database driver must roll back all inserts.
* **Immutable Kernel:** All core framework classes (`app/core/*`, `Router`, `BaseController`, etc.) are frozen. Extension is achieved purely via the service layer, controllers, and middleware pipeline.
* **Double-Escaping Output:** Every dynamic string rendered in view files (checklists, workspace names, slugs) must pass through `escape_html()`.
* **Database Schema Freeze:** No columns or tables may be added beyond the schema defined in PDD v1.0.

### 8.1 Workspace Boundary Principle
* **Highest Tenant Boundary:** The Workspace is the highest tenant isolation boundary in the Inveetaire system.
* **Couple/Crew Constraint:** Couple and Crew requests must always remain inside one workspace. Mismatching paths or unauthorized cross-tenant requests must be intercepted immediately.
* **Isolation of Queries:** Every workspace-scoped database read, write, update, and delete must include explicit workspace isolation filters.
* **Super Admin Bypasses:** Super Admin bypasses workspace boundaries only through explicitly approved administration workflows (e.g. workspaces list, provisioning, or Support Session adoption).
* **Strict Cross-Tenant Prohibition:** Cross-workspace reads, writes, updates, and deletes are strictly prohibited under all circumstances.

---

## 9. Testing Strategy

1. **Multi-Tenant Isolation Verification:**
   * Log in as Couple A. Attempt to access `/app/couple/dashboard` representing Couple B -> Confirm immediate 403 Forbidden intercept by `WorkspaceMiddleware`.
   * Manipulate session variables via cookie hijacking to force access -> Verify middleware halts execution.
2. **Atomic Transaction Verification:**
   * Trigger manual DB exceptions during provisioning (e.g. inject an invalid foreign key value into `invitations` table inside the transaction).
   * Confirm the transaction rolls back completely and no orphan rows are created in `workspaces` or `users`.
3. **Setup Checklist Accuracy:**
   * Verify checklist state matches real DB states. Inserting a test guest must toggle step 4 ("Add First Guest") from pending to completed.
4. **Lifecycle Phase Gates:**
   * Modify the database `wedding_date` for a test workspace.
   * Verify live check-in views return 403 when phase is `setup`.
   * Verify live check-in views succeed when phase is `live`.
   * Verify check-in gets frozen and reports are unlocked when phase shifts to `post_event`.
   * **Archived/Purged Tenant Access Scenario:** When a workspace becomes archived or purged while a Couple or Crew session is active, `WorkspaceMiddleware` must deny access immediately, returning the appropriate HTTP 403 Forbidden response or redirection according to the architecture, ensuring no cross-workspace access occurs.
5. **Security Hardening (CSP & Rate-Limit):**
   * Inspect response headers for `Content-Security-Policy`.
   * Rapidly request forgot-password links -> Verify rate-limiting blocks requests after configured limit.

---

## 10. Security Checklist

* [x] **Workspace Isolation:** Every DB query mapping to a specific workspace checks matching `workspace_id` parameters.
* [x] **SQL Injection:** Only use parameterized queries with PDO. Concatenated strings are forbidden.
* [x] **Content-Security-Policy:** Active CSP header restricting source origins.
* [x] **Database Transactions:** Multi-row inserts mapped under `beginTransaction()`, `commit()`, and `rollBack()` blocks.
* [x] **Audit Log Tracking:** Logging phase transition histories to the `audit_logs` table.
* [x] **Output Escaping:** Universal `escape_html()` wrappers around all variables printed to output streams.
* [x] **Thin Controllers:** Workspace controllers only validate requests, call the service class, and return layouts. No SQL inside controllers.

---

## 11. Exit Criteria

Sprint 3 is successful when all the following are true:

| Criterion | Verification Method |
|-----------|---------------------|
| Baseline CSP header is active and verified | Browser inspector / curl headers check |
| Forgot password rate limiting blocks rapid attacks | Integration test script |
| Workspace provisioning transaction operates atomically | Unit test database trace |
| WorkspaceMiddleware intercepts invalid cross-tenant requests | Automated / manual access check |
| No authenticated user can access resources belonging to another workspace | Automated / manual cross-tenant audit |
| Setup checklist widget displays correct state dynamically | View render trace |
| Workspace phases transition logically based on date boundaries | Date shift test |
| All workspace files created pass PHP syntax and escaping audits | Syntax linter |

---

## 12. Technical Debt Management

### Resolved in Sprint 3:
* **TD-002 (Content Security Policy):** Resolved by adding baseline CSP rules to `public/.htaccess`.
* **TD-009 (Rate Limiting forgot-password):** Resolved by implementing lockout rate-limits in `AuthService.php`.
* **TD-010 (Expired Token Cleanup):** Resolved by building token file scanner-purger utility.

### New Technical Debt:
* **No new technical debt expected.**

### Deferred:
* **TD-003 (Log File Rotation):** Deferred to pre-launch configuration passes.
* **TD-005 (Google Fonts self-hosting):** Deferred to Sprint 4+ non-blocking.
