# Implementation Plan: 063 — Entra Sign-in (Tenant Panel) v1

**Branch**: `063-entra-signin` | **Date**: 2026-01-27 | **Spec**: [specs/063-entra-signin/spec.md](spec.md)
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/063-entra-signin/spec.md`

## Summary

This feature will implement Microsoft Entra ID OIDC-based sign-in for the Tenant Admin panel. The implementation will override the default Filament login page to present an Entra-only sign-in option. It will utilize Laravel Socialite to manage the OAuth2 flow, handling redirection to Microsoft Entra ID and processing the callback. Core logic involves upserting users based on `(entra_tenant_id, entra_object_id)`, blocking disabled users, regenerating sessions, and dynamically routing users post-login to their tenant dashboard, a dedicated tenant chooser page (for multiple memberships), or a "no access" page (for zero memberships). The implementation adheres to security best practices by not storing sensitive tokens and ensures all affected pages remain DB-only at render time.

Routing stability rule: redirects into a tenant MUST use Filament page URL helpers (e.g., `App\\Filament\\Pages\\TenantDashboard::getUrl(tenant: $tenant)`) rather than hardcoding `/admin/t/...`, so future route prefix / tenant slug changes don’t break auth flows.

## Technical Context

**Language/Version**: PHP 8.4
**Primary Dependencies**: `laravel/framework:^12`, `livewire/livewire:^4`, `filament/filament:^5`, `laravel/socialite:^5.0`
**Storage**: PostgreSQL
**Testing**: Pest
**Target Platform**: Web
**Project Type**: Web application
**Performance Goals**: Callback returns within ~2s under normal conditions.
**Constraints**: Do not persist secrets/tokens. Sanitize all error output and logs. Outbound HTTP is permitted only inside /auth/entra/* endpoints.
**Scale/Scope**: Tenant Admin panel (`/admin`) sign-in only.

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

- **Inventory-first**: Not directly applicable to auth.
- **Read/write separation**: N/A for login, but user upsert is a write. The spec requires it to be idempotent, which aligns.
- **Graph contract path**: The spec explicitly forbids Graph calls during render/poll/hydration, and limits OIDC calls to the `/auth/entra/*` routes. This is compliant.
- **Deterministic capabilities**: N/A.
- **Tenant isolation**: Compliant. The entire flow is built around tenant context (`tid`).
- **Run observability**: Compliant. The spec references `OPS-EX-AUTH-001`, the Auth Handshake Exception, which exempts this synchronous login flow from requiring an `OperationRun`. Logging requirements are specified.
- **Automation**: N/A.
- **Data minimization**: Compliant. Spec says "MUST NOT store Entra access/refresh tokens" and requires safe logging.
- **Badge semantics (BADGE-001)**: N/A.

**Result**: The plan is compliant with the constitution.

## Project Structure

### Documentation (this feature)

```text
specs/063-entra-signin/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   └── entra-auth-flow.md
└── tasks.md
```

### Source Code (repository root)

```text
# Web application
app/
├── Http/
│   ├── Controllers/
│   │   └── Auth/
│   │       └── EntraController.php   # New: Handles OIDC redirect and callback logic
│   └── Middleware/
├── Filament/
│   ├── Pages/
│   │   ├── Auth/
│   │   │   └── Login.php           # New: Custom Filament login page with Entra-only CTA
│   │   ├── NoAccess.php            # New: Page for users with no tenant memberships
│   │   └── ChooseTenant.php        # New: Page for users with multiple tenant memberships
│   └── Tenant/
│       └── Resources/
├── Models/
│   └── User.php                    # Modified: User model for Entra IDs and tenant relationships
├── Providers/
│   └── Filament/
│       └── AdminPanelProvider.php  # Modified: Register custom login page
config/
├── services.php                    # Modified: Add Microsoft Socialite provider config
routes/
│   └── web.php                     # Modified: Register OIDC redirect and callback routes
tests/
└── Feature/
    └── Auth/
        ├── AdminLoginIsEntraOnlyTest.php
        ├── EntraCallbackUpsertByTidOidTest.php
        ├── PostLoginRoutingByMembershipTest.php
        ├── OidcFailureRedirectsSafelyTest.php
        ├── SessionSeparationSmokeTest.php
        └── DisabledUserLoginIsBlockedTest.php
```

**Structure Decision**: The project is a standard Laravel web application. The changes will be implemented within the existing structure, primarily affecting `app/`, `routes/`, `config/` and `tests/`.

## Complexity Tracking
No violations.