# Mi-Insite architecture

## Architectural style

Mi-Insite begins as a TypeScript modular monolith in a monorepo. Web, API, worker and scheduler
are separate processes with independently scalable runtime profiles, but share versioned domain
packages and one transactional system of record.

This avoids premature distributed-system complexity while preserving boundaries that can later
be extracted when connector throughput or team ownership justifies it.

## Runtime topology

```text
Browser / client portal
        |
Managed ingress or Apache TLS proxy
        |
  +-----+------------------+
  |                        |
Next.js web            Fastify API
                           |
          +----------------+----------------+
          |                |                |
     PostgreSQL       Object storage    AI gateway
          |
   Transactional outbox / durable job queue
          |
   Workers and scheduler
          |
 Connector adapters: mock, Meta, X, TikTok, RSS/direct
```

The current cPanel host is development-only. Production infrastructure and all managed data
services must be located in South Africa. Application processes bind to loopback addresses and
are exposed only through TLS ingress.

## Repository boundaries

- `apps/web`: role-aware React/Next.js interface and white-labelled portal.
- `apps/api`: authenticated HTTP API, webhooks and health/readiness endpoints.
- `apps/worker`: ingestion, normalisation, enrichment, publishing, reporting and retention jobs.
- `apps/scheduler`: creates lightweight recurring and reconciliation jobs.
- `packages/config`: environment parsing and validation.
- `packages/database`: PostgreSQL schema, migrations, seed framework and database runtime.
- `packages/connectors`: capability contracts and replaceable source adapters.
- `packages/observability`: structured, redacted logging and future tracing.
- Future domain packages own tenancy, cases, publishing, archive, KPIs and AI policies.

Domain code must not depend directly on Fastify, Next.js or provider SDKs. Provider payloads are
validated and translated at connector boundaries.

## Ingestion and action flow

1. Authenticate and validate a webhook, or lease a scheduled polling job.
2. Check tenant connector entitlement and rate-limit budget.
3. record the permitted raw payload encrypted with source and rights metadata.
4. Claim an idempotency key derived from provider, account and provider event ID.
5. Normalize the event into canonical content and identities.
6. Create exact and near-duplicate relationships without losing source lineage.
7. Enqueue language, entity, topic, sentiment, risk and embedding enrichment.
8. Project the record into tenant-scoped search.
9. Evaluate rules and create alerts, cases or KPI recalculation jobs.
10. Preserve every decision and externally visible action in the audit trail.

A transactional outbox connects database changes to jobs. Consumers use leases, bounded retries,
dead-letter states and replay tools. Connector failure is isolated by provider, tenant and
account.

## Technology decisions

- React and Next.js for web and client portals.
- Fastify for a small typed API surface with structured logging.
- Strict TypeScript and Zod at every external trust boundary.
- PostgreSQL as the authoritative store.
- `pg-boss`-style PostgreSQL durable jobs for the operational MVP.
- PostgreSQL full-text search and trigram matching initially; `pgvector` only after the managed
  production service and model policy are approved.
- S3-compatible versioned object storage for permitted evidence and exports.
- OpenAPI-compatible REST plus signed webhooks and internal events.
- OpenTelemetry-compatible instrumentation as production observability is introduced.

The local scaffold uses PGlite, an embedded PostgreSQL-compatible runtime, so development,
migrations and tests do not depend on server packages or Docker. Production uses ordinary
PostgreSQL through the same SQL migration set.

## Multi-tenancy

- Every tenant-owned table contains a non-null `tenant_id`.
- Composite foreign keys include the tenant boundary where a child references tenant data.
- PostgreSQL row-level security is enabled on tenant tables in production.
- Each request sets a transaction-local tenant context derived from the authenticated principal,
  never directly from an untrusted request field.
- Platform maintenance uses a distinct audited database role.
- Search, caches, queues, objects, logs and analytics retain tenant scope.
- Object keys begin with a non-guessable tenant namespace and are authorised before signing.
- Automated tests attempt horizontal and vertical privilege escalation.

The initial model is a shared schema with row-level security. Dedicated databases remain an
enterprise option for clients whose risk assessment requires stronger physical separation.

## Evidence integrity

An evidence snapshot includes source identity, permitted content, captured time, licence class,
retention rule, cryptographic hash and object version. Authored content additionally records
each version, reviewer, approval, platform result and reconciliation status.

Audit events are append-only. Evidence exports contain a canonical manifest and SHA-256 hashes.
Production object storage should use versioning and Object Lock when legally and contractually
permitted. Legal holds override normal deletion; provider-mandated deletion leaves only a
permitted tombstone.

## Authentication and authorisation

- Password authentication with mandatory TOTP MFA for the MVP.
- Recovery codes are single-use hashes.
- Sessions expire after eight hours and privileged sessions after 30 minutes of inactivity.
- Publishing, exports, role changes and retention actions support step-up MFA.
- Capability-based authorisation supplements named roles.
- Sensitive workflows enforce separation of duties.
- Enterprise OIDC/SSO can be added without changing the tenant identity model.

### Implemented identity foundation

The local foundation uses Argon2id password hashes, opaque 256-bit session tokens whose SHA-256
digests are stored server-side, HTTP-only same-site cookies, a 30-minute idle timeout and an
eight-hour absolute timeout. Logout and password reset revoke server-side sessions. Sign-in and
reset endpoints are rate-limited, reset responses do not reveal whether an email exists, and raw
reset/invitation tokens are delivered only through an adapter. The development adapter writes to
an ignored mode-0600 mailbox and is prohibited in production.

Named roles map to shared capabilities in `packages/authorization`; the web interface uses them
to hide unavailable actions, while the API independently enforces every operation. API denial is
authoritative. Tenant operations run through a transaction that sets
`app.current_tenant_id` from the authenticated principal, allowing PostgreSQL RLS to enforce a
second boundary beneath tenant-qualified service queries.

TOTP challenge, enrolment and recovery codes remain an explicit pre-production security task.
The `mfa_required` marker is not evidence that MFA has been completed.

### Implemented interface foundation

The first mock interface follows the brief’s persistent left rail, compact context bar, working
canvas and right-side evidence drawer. Shared components cover filters, tables, charts, status
labels, mentions, timelines, modals and empty/error/loading states. Status always combines text
and iconography with colour. Browser checks exercise keyboard navigation and serious/critical
WCAG 2.2 A/AA rules at desktop and mobile widths.

All displayed coverage, conversations, campaigns, people and publications are development mock
data. No social or media provider API is connected.

## AI architecture

All AI calls pass through a policy-enforcing gateway that records tenant policy, provider, model,
prompt version, evidence references, redaction result, response hash and reviewer outcome.

Provider adapters are built for Gemini, OpenAI and Claude but live content is denied unless the
exact model has an approved South African storage and inference contract. Synthetic or
irreversibly redacted development data may be used for evaluation. A locally hosted open-weight
adapter is the compliant fallback.

Ingested content is untrusted and cannot modify system instructions, call tools or approve an
action. AI output is advisory and always requires a human for external communication.

## Observability

- JSON logs include service, environment, request/job ID, connector and tenant pseudonym.
- Logs redact authentication headers, cookies, tokens, prompts, responses and personal content.
- Health checks distinguish liveness from dependency readiness.
- Metrics cover connector lag, job age, retries, dead letters, publishing reconciliation,
  archive integrity and tenant usage.
- Trace context follows an item from connector event to case, publication and report.

## Deployment and recovery

CI produces immutable artifacts identified by Git commit. Database changes use forward-only
expand/migrate/contract migrations. Traffic is switched only after readiness checks.

Development can run through local Node processes and PGlite. A future cPanel development
deployment would use root-managed systemd services bound to loopback and Apache proxying, but is
outside the current local-only phase.

Production requires South African compute, managed PostgreSQL with point-in-time recovery,
versioned object storage, managed secrets, tested backups and at least two application instances.
Application rollback switches to a prior artifact; database issues use forward fixes unless a
tested restoration decision explicitly authorises recovery.
