# Architecture Decision Log (ADR)

## ADR 1: Unified Token Management Utility (`tokenUtils`)
- **Status**: Decided & Implemented (2026-07-03)
- **Context**: Access tokens were handled inconsistently (`access_token` vs `token`) across `localStorage` and `document.cookie` resulting in `403 Forbidden` and `No valid access_token found` warnings in browser/server scopes.
- **Decision**: Centralize all auth-token management inside a specialized helper `auth-token.ts` that enforces:
  - Unified token identifier: `access_token`.
  - Fallback logic to grab from cookie names (`access_token`, `token`, `jwt`) or localStorage options if desynced.
  - Safe extraction from cookie or `Authorization: Bearer` header on server-side Next.js route handlers.
- **Consequences**: Standardized calls across `api.ts`, `auth-context.tsx`, and `fetch.ts`. Eliminated 403 authorization locks and console warnings on admin portal dashboards.

## ADR 2: SSR-Safe Auth Wrapper & Backend Role & CORS Fixes
- **Status**: Decided & Implemented (2026-07-03)
- **Context**: The token lookup in `fetch.ts` returned null when executed on the server-side during SSR, triggering false warning logs. Concurrently, the backend blocked `super_admin` from viewing profiles due to a strict `'admin'` role equality check, and needed CORS authorization for the network IP.
- **Decision**: 
  - Standardize token retrieval to happen at call time inside the `fetchWithAuth` body, checking `window` existence to skip server-side execution.
  - Integrate `saveAuthToken` in `page.tsx` on login success.
  - Modify `/api/users/:id` endpoint on backend to accept both `'super_admin'` and `'admin'` roles.
  - Configure backend CORS origin handler to support origin validation lists with credentials, preflight handling on all options routes.
- **Consequences**: All admin dashboard endpoints successfully resolved with `200 OK`.

## ADR 3: Direct Cookie-First Token Extraction in fetchWithAuth
- **Status**: Decided & Implemented (2026-07-03)
- **Context**: In production environments, client credentials might be saved only in browser cookies, leaving `localStorage` devoid of a token (e.g. only holding UI settings like user roles). A wrapper prioritizing `localStorage` would fail.
- **Decision**: Update `fetchWithAuth` in `fetch.ts` to actively parse `document.cookie` first for `access_token`, and use `localStorage` only as a secondary fallback.
- **Consequences**: Avoided false negatives when fetching data in browser environments where cookies are the sole token carrier, successfully populating dashboard state arrays and restoring correct statistics counts.

## ADR 4: AI Property Link Scraper Engine
- **Status**: Decided & Implemented (2026-07-04)
- **Context**: Ingesting listings manually is slow and prone to user input errors. The portal needs a robust external URL scraper to ingest listings as drafts from major portals (Bayut, PropertyFinder, Dubizzle) automatically.
- **Decision**: 
  - Install `cheerio` and `axios` on the Express API.
  - Implement a dedicated parser `property-scraper.ts` that safely parses page HTML to extract titles, descriptions, prices, bedrooms, bathrooms, sizes, address, images, and amenities.
  - Implement secure admin-only endpoints (`/api/admin/properties/scrape` and `/api/admin/properties/scrape-and-save`).
  - Scraped units are injected with `is_active = 0` (draft status) under the logged-in super_admin's ID to ensure they go through mandatory editorial review before publication.
- **Consequences**: Enables rapid real estate listing populating. Ensures data safety by forcing editorial validation prior to publication.

## ADR 5: Professional SEO & Dynamic Metadata Infrastructure
- **Status**: Decided & Implemented (2026-07-04)
- **Context**: Dynamic properties page and listings index required customizable metadata tags, search engine indexing preferences (canonical link, robots rules), and structured schema JSON-LD scripts to maximize SEO indexing and search visibility.
- **Decision**:
  - Implement a relational `seo_metadata` table to map meta properties to entities (`page`, `unit`, `project`, etc.) using entity types and IDs.
  - Add public `GET` and admin-restricted `PUT` routes on port `3001` with a dedicated Next.js API route proxy to bridge calls.
  - Wrap the dynamic client-side `[slug]/page.tsx` page using a Server Layout `layout.tsx` to query local Next.js DB APIs, dynamically generating metadata headers via `generateMetadata` and embedding JSON-LD `RealEstateListing` structured schemas.
- **Consequences**: Dynamic schema injections and robots flags are active on property pages. All crawler data queries execute on-server, caching results. Next review check scheduled for 30 days out, on or before August 3, 2026.

## ADR 6: Reusable Admin Proxy Factory (`adminProxy`) & Backend Express Consolidation
- **Status**: Decided & Implemented (2026-07-04)
- **Context**: The Next.js API routes for admin tables (bookings, subscriptions, submissions) were querying the DB directly, resulting in duplicated controllers and desynced authentication validations between API frameworks.
- **Decision**: 
  - Standardize Next.js route structures by creating a unified proxy utility `adminProxy` inside `lib/admin-proxy.ts` that safely reads session cookies and forwards requests to Express.
  - Implement a central admin controller `apps/api/src/routes/admin.ts` on port 3001, providing strict authorize('super_admin') middleware for all administrative operations.
  - Map Next.js frontend route handlers (`bookings`, `subscriptions`, `submissions`) to call the proxy utility.
- **Consequences**: Prevented token decoding mismatches and standardized admin control code. Cleaned up browser developer console logs ensuring `200 OK` on all requests.
