# Architecture

## Audit summary

The starting deployment directory contained only cPanel-generated Apache/PHP
files and no Git repository or application. PHP 8.3, Composer 2.8, Node.js 20,
npm 10, MySQL 8.4, Docker, and Git are available. Redis is not installed on the
host. Compatible Ironhand-owned brand references were located in a sibling
Ironhand application and copied into `design-references/`; the source
application was not changed.

There was no reusable application, authentication, database, CRM connector,
notification system, API, UI component library, or deployment documentation.

## Chosen architecture

The control plane is a Laravel 12 modular monolith using React, TypeScript,
Inertia, Tailwind CSS, and Radix-based components. Laravel 12 was selected
because the official React starter kit targets it and it is compatible with the
available PHP 8.3 runtime. MySQL 8+ is the production database. Redis is the
production queue/cache target; database queues remain a safe local or
single-host fallback.

Scanner workers and the Manifest V3 extension are independent TypeScript
workspaces. They communicate with the control plane through versioned,
authenticated JSON contracts and can be deployed or updated separately.

```text
Browser / Inertia UI
        |
Laravel control plane + /api/v1
  | tenancy/auth/policies
  | campaigns/scans/opportunities
  | alerts/AI/CRM/audit/reporting
        |
MySQL + Redis + encrypted secret store
        |
Authorized scanner API
        |
Manifest V3 extension now
Windows desktop agent later
```

## Domain boundaries

- `Identity`: authentication, 2FA, users, sessions, invitations, roles.
- `Tenancy`: organizations, memberships, settings, lifecycle, isolation.
- `SaaS`: plans, subscriptions, licenses, entitlements, usage, billing adapters.
- `Campaigns`: campaign criteria, keywords, exclusions, scoring versions.
- `Sources`: source configuration, URL safety, schedule, health, assignments.
- `Scanning`: scanners, devices, jobs, sessions, ingestion, metrics, errors,
  heartbeats, observations, and kill switches.
- `Intelligence`: deterministic filters, AI adapters, analyses, scoring.
- `Opportunities`: qualification, assignments, responses, workflow, outcomes.
- `Notifications`: alerts and provider-specific deliveries.
- `CRM`: connections, mappings, jobs, idempotency, reconciliation, webhooks.
- `Governance`: audit, security events, retention, export, deletion.
- `Branding`: product and future tenant branding tokens/assets.

## Proposed directory structure

```text
app/
  Domain/<Domain>/{Actions,Contracts,Data,Enums,Jobs,Models,Policies,Services}
  Http/{Controllers,Middleware,Requests,Resources}
database/{factories,migrations,seeders}
resources/{css,js,views}
routes/{web.php,api.php,console.php}
scanner/                 Node.js/TypeScript authorized scanner service
extension/               Chrome/Edge Manifest V3 extension
packages/contracts/      Shared JSON schemas and TypeScript types
docs/
design-references/
public/branding/
tests/{Feature,Unit,e2e}
```

## API and jobs

REST endpoints live under `/api/v1`. Mutating scanner and CRM operations use
idempotency keys. Queue payloads carry tenant, correlation, scan/job, actor,
scoring-version, and connector identifiers. A worker re-validates current
authorization and kill-switch state when accepting a job; scheduling-time
authorization is not sufficient.

Each persisted content observation dispatches a tenant-bound AI qualification
job. Campaign keywords and exclusions are evaluated before provider use. Hard
exclusions stop the workflow without an external request. The provider returns
a strict evidence-grounded object, while the server independently calculates
the final 0–100 score from the campaign's published scoring version. Completed
analyses are reused by a deterministic input hash. Opportunities are unique per
campaign/content pair and always enter a human-review workflow; response
suggestions are never published automatically.

## Deployment model

The Laravel web/API process, scheduler, queue workers, and scanner service can
run on one Ironhand-controlled host initially. They remain separately
restartable. Scale-out adds stateless web nodes and scanner/queue workers
without changing tenant ownership boundaries.

The reporting workspace uses the same tenant scopes and permission checks as
operational screens. It provides exact filtered aggregates, qualified content
evidence, and streamed audited CSV exports. It intentionally avoids decorative
charts when exact tables and compact breakdowns communicate the result.
