# Architecture

Canonical URL: https://texttree.ai/en/docs/architecture/
Markdown URL: https://texttree.ai/en/docs/architecture.md
Page type: docs
Translation status: approved
Legal status: not_required

## Summary

How Astro, Phoenix, Neon, Oban, and provider adapters fit together in the current TextTree alpha.

## Source content

# Architecture

The public site and the application runtime are deliberately split.

## Public surface

Astro owns:

- landing pages
- docs
- blog
- SEO metadata, RSS, and sitemap output

## Application surface

Phoenix owns:

- login and authenticated UX
- `/api/v1/*`
- signed provider webhooks
- `/mcp/*`

## Core state

Neon-backed Postgres is the system of record for:

- Phoenix-native users and TextTree auth identities
- username-backed headless agent accounts
- users and workspaces
- legacy consent/contact metadata
- workspace and campaign suppressions
- messages
- ledger entries and spend limits
- provider events
- funding sessions
- MCP execution audits

## Worker ownership

Oban owns side effects and retries.

- outbound messages are queued before provider execution
- provider events are stored before reconciliation
- replay and retry paths stay out of controllers and LiveViews

## Execution rules

Outbound messaging follows a strict path:

1. workspace suppression check
2. spend reservation and ledger write
3. Oban enqueue
4. provider execution in a worker

That keeps external side effects out of controllers and LiveViews.

## Webhook rules

Provider webhooks follow a parallel boundary:

1. signature verification
2. normalized event persistence
3. duplicate detection
4. Oban enqueue
5. reconciliation into message, suppression, or funding state

## MCP rules

The MCP surface is intentionally narrow in alpha:

1. public health and headless account bootstrap
2. TextTree bearer-token authentication for tool routes
3. route-level scope enforcement
4. server-registry and allowlist checks
5. quota and timeout controls
6. persisted execution audit records

Headless account bootstrap through `/api/v1/accounts` or `/mcp/accounts` creates
a username/password agent account, one-time backup codes, and a TextTree bearer
token. The bootstrap throttle stores a hashed IP address and allows only one
successful account creation per IP every five minutes.

## Provider boundaries

Controllers and LiveViews do not call vendors directly.

- messaging routes talk to the messaging context
- funding routes talk to the funding context
- provider-specific HTTP semantics stay inside provider adapters
- webhook normalization happens before business-state reconciliation

## Alpha constraints

This architecture is already usable, but still intentionally incomplete:

- repo-local ADRs capture the current implementation baseline while the canonical canvas import is still pending
- some product surfaces are operator-only rather than public API contracts
- MCP tooling is server-configured, not tenant-configured
- docs describe the implemented alpha contract, not future roadmap promises
