# Project architecture

This repository builds the LUCA Plus agent site. `site.config.json` selects the brand and the Cloudflare Pages project. The Pay and Plus repositories use the same application structure but deploy separately.

## Request flow

```mermaid
flowchart LR
  Human[Person or AI client] --> Pages[Cloudflare Pages Worker]
  Pages --> Gate[Basic Auth for / and /agents]
  Pages --> Assets[Static Next.js export]
  Pages --> REST[Public REST API]
  REST --> Limit[Durable Object rate limit]
  Pages --> MCP[Public MCP endpoint]
  MCP --> Limit
  REST --> Catalog[Versioned product catalog]
  MCP --> Catalog
  CLI[Node CLI or Go binary] --> REST
  CLI --> MCP
  Pages --> Metrics[Analytics Engine]
  Pages --> LUCA[Official LUCA signup and contact]
```

The Worker runs from the Pages advanced mode `_worker.js` bundle. It serves HTML, the static asset export, discovery files, the REST API, the MCP endpoint, and redirects. The API and MCP read `src/catalog.js` through `src/core.js`. They do not call a language model or store application answers.

The Next.js frontend builds static HTML for the landing page, `/docs/`, `/skills/`, and `/downloads/`. React Bits Pro Agentframe code is licensed for this project. The Worker serves it through the Pages asset binding.

The 26 October product team correction is a public source note. It supersedes old LUCA Plus invoice automation and monthly subscription claims. The catalog and agent files use it for current answers.

The Node CLI and four Go binaries use the public REST API. Their local stdio MCP mode forwards requests to the public remote MCP endpoint. ZIP files package the four public skills. The source corpus and public product notes are versioned with the code.

## Cloudflare and DNS

The current preview is `https://luca-plus-agents-preview.pages.dev` in the personal Cloudflare account. Its `PREPRODUCTION` setting is `true`. The intended product host is `https://agents.lucaplus.com`. Attach both `agents.lucaplus.com` and `agent.lucaplus.com` as Pages custom domains. External DNS needs a CNAME for each host. The Worker redirects the singular host to the plural host with HTTP 308. It keeps the path and query. The main LUCA Plus site runs through Netlify; the LUCA Pay site runs through Webflow.

A separate Durable Object Worker counts API and MCP requests per client IP. The limit is 100 combined requests per fixed minute. It returns 429 with `Retry-After` after the limit. A missing IP header or binding returns 503. The Cloudflare edge supplies `CF-Connecting-IP`.

Analytics Engine counts page views, named page actions, API calls, MCP tool calls, and downloads when the binding exists. The Worker does not put questionnaire answers into Analytics Engine. Preview responses carry `noindex` and `no-store` headers.

## Modules

| Path | Purpose |
| --- | --- |
| `src/worker.js` | Routing, landing gate, rate-limit check, security headers, analytics |
| `src/rate-limit.js`, `rate-limit-worker/` | Durable Object counter and deployable Worker |
| `src/catalog.js` | Product facts, source links, review states, and conflicts |
| `src/core.js` | Search, answers, fit guide, and MCP tool functions |
| `src/mcp.js` | JSON-RPC and MCP protocol handling |
| `frontend/` | Static landing page and rendered docs, skills, and downloads |
| `public/docs/` | Diátaxis guides and source notes |
| `public/skills/` | Downloadable agent instructions |
| `cli/`, `cli-go/` | Node and native CLI with local stdio MCP bridge |
| `scripts/` | Site, Pages, skill, and binary builds |
| `tests/` | Worker tests and HTTP integration checks |
| `research/` | Source captures, reports, and review history |

## Trust boundaries

Only `/` and `/agents` require Basic Auth in preview. Product facts, docs, skills, downloads, REST, and MCP are public. The Basic Auth password is a Pages secret named `PREVIEW_BASIC_AUTH_PASSWORD`; no password belongs in Git. An absent secret makes the two landing routes return HTTP 503. Invalid or absent credentials return HTTP 401. The username is `luca`.

The assessment route is a nonbinding guide. It cannot approve credit or calculate a final fee. Partner offers have `offer_scope=partner:bni`; the general overview excludes them. Public partner content names the offer only. Agents must contact LUCA for member terms.
