> ## Documentation Index
> Fetch the complete documentation index at: https://cona.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Webapp

> Inside @cona/webapp — the ingress chain, route groups, server action layer, and how requests reach the database

# Webapp

`@cona/webapp` — the primary application. Next.js App Router on Vercel at `cona.app`.
90 pages, 42 API route handlers, 501 files carrying `"use server"`.

## Request path

Every request passes through `proxy.ts` unless the matcher excludes it.

```mermaid theme={null}
flowchart TB
    Request["incoming request"] --> Matcher{"proxy.ts matcher<br/>line 288"}

    Matcher -->|"excluded:<br/>api/webhooks, api/health,<br/>api/stripe-app, _next/*"| SelfAuth["Route verifies itself<br/>signature / HMAC / none"]
    Matcher -->|"everything else"| Proxy["proxy.ts"]

    Proxy --> Nonce["generate CSP nonce"]
    Nonce --> Maint{"maintenance<br/>enabled?"}
    Maint -->|yes, API| Err503["503 + Retry-After"]
    Maint -->|yes, page| MaintPage["rewrite /maintenance"]
    Maint -->|no| Auth0{"Auth0 session?"}

    Auth0 -->|no| Login["redirect /auth/login"]
    Auth0 -->|yes| DevGate{"/dev or /api/dev<br/>outside dev/staging?"}

    DevGate -->|yes| NotFound["404"]
    DevGate -->|no| Audit["log privileged access<br/>/admin, /dev"]
    Audit --> Handler["page or route handler"]

    SelfAuth --> Handler
    Handler --> Headers["security headers<br/>+ request telemetry"]

    classDef app fill:#dbe2fb,stroke:#3B56C5,color:#111827
    classDef external fill:#fff4dd,stroke:#c98a12,color:#111827
    class Proxy,Nonce,Handler,Headers,Audit app
    class SelfAuth external
```

The exempt families each authenticate themselves — verified, not assumed. See
[Ingress](/architecture/ingress-oauth-webhooks).

## Layers

```mermaid theme={null}
flowchart LR
    Pages["app/(pages)/*<br/>90 route segments"]
    UI["app/ui/*<br/>components by category"]
    Api["app/api/*<br/>42 route handlers"]

    Actions["app/lib/actions/&lt;domain&gt;/<br/>65 folders · 380 files"]
    Auth["app/lib/auth/<br/>Auth0 session, org + actor resolution"]
    Integrations["app/lib/integrations/&lt;provider&gt;/<br/>29 providers"]
    AppStore["app/lib/app-store/<br/>native tool install"]
    Support["app/lib/{data,filters,schemas,<br/>posting-matrix,copilot,pdf,email}"]

    Core["@cona/core/domains/*<br/>343 imports"]
    Tracked["@cona/database/tracked<br/>185 imports"]
    Direct["@cona/database root<br/>123 value imports"]
    DB[("Supabase Postgres")]
    Temporal["Temporal Cloud"]

    Pages --> UI
    Pages --> Actions
    Api --> Actions
    UI --> Actions

    Actions --> Auth
    Actions --> Core
    Actions --> Tracked
    Actions --> Direct
    Integrations --> Temporal
    Integrations --> Core
    AppStore --> Core
    Actions --> Support

    Core --> DB
    Tracked --> DB
    Direct --> DB

    classDef app fill:#dbe2fb,stroke:#3B56C5,color:#111827
    classDef pkg fill:#e8eafd,stroke:#4967E6,color:#111827
    classDef data fill:#fde8e8,stroke:#c53b3b,color:#111827
    classDef async fill:#e3f7ea,stroke:#2f9e5c,color:#111827

    class Pages,UI,Api,Actions,Auth,Integrations,AppStore,Support app
    class Core,Tracked pkg
    class Direct,DB data
    class Temporal async
```

<Warning>
  The `@cona/database` root edge is the one that should not exist. **40 production files** import
  the live `prisma` client directly, bypassing both `@cona/core` and `@cona/database/tracked` —
  including 9 mutations. See [Package Graph](/architecture/package-graph).
</Warning>

## Route groups

| Group          | Pages | Contents                                                                                       |
| -------------- | ----- | ---------------------------------------------------------------------------------------------- |
| `(sales)`      | 6     | `sales-invoice`, `sales-credit-note`, `sales-order`, each with `[id]`                          |
| `(accounting)` | 2     | `general-ledger`, `general-ledger/[id]`                                                        |
| `(customers)`  | 2     | `customers`, `customers/[id]`                                                                  |
| `(catalog)`    | 2     | `products`, `products/[id]`                                                                    |
| `(settings)`   | \~44  | `(configuration)/{admin,settings,setup}/*` and `user-settings/*`                               |
| `(public)`     | 3     | `auth-error`, `maintenance`, `verify-email` — no session required                              |
| top level      | \~31  | `app-store`, `tool/*`, `payment`, `direct-posting/[id]`, `datev-export/download/[id]`, `dev/*` |

24 of the settings pages are integration setup at
`setup/integrations/<provider>/[id]` — one per provider, all the same shape.

### Two kinds of "tool"

`tool/ar-recon`, `tool/datev-export`, `tool/deferred-revenue` are **native modules**
installed from the App Store — distinct from integrations, which are external data
sources. Both are sold through the same App Store.

## Auth and tenancy

`app/lib/auth/auth.ts` is the tenancy surface:

| Export                        | Line | Files using it |
| ----------------------------- | ---: | -------------: |
| `getOrganizationId()`         |   94 |            223 |
| `getOrganizationAndActorId()` |  126 |            134 |
| `requireAuth()`               |  199 |             40 |
| `getAuth0Session()`           |   28 |             32 |

`getOrganizationAndActorId()` returning both in one call is what couples tenant scoping to
mutation attribution. See [Auth, Tenancy & Actors](/architecture/auth-tenancy-actors).

A further 14 files handle Auth0 management: user CRUD, MFA enrolment, TOTP deletion,
password and email updates.

## Server actions

65 domain folders under `app/lib/actions/`, largely mirroring `@cona/core` domains. The
asymmetry is informative — these 17 folders have **no** core counterpart because they are
presentation or admin concerns:

`admin`, `cache`, `catalog`, `contacts`, `copilot`, `copilot-memory`,
`customer_debtor_accounts`, `dashboard`, `delivery_terms`, `dev`, `filters`,
`gl_dimensions`, `gl_reconciliations`, `posting_matrix`, `posting_matrix_column_type`,
`sandbox`, `subscriptions`

## Notes

**`proxy.ts`, not `middleware.ts`.** Next.js 16 naming. Anyone grepping for
`middleware.ts` will find nothing.

**Two near-empty layers.** `app/lib/controllers/` holds 2 files and `app/lib/services/`
holds 1 (PostHog). They look like abandoned layering experiments and are folded into
"support" above rather than drawn as tiers.

**Three loose files break the action-folder convention:**
`app/lib/actions/delete-financial-data.ts`, `dev-token-actions.ts`, and a stray test
`document-default-settings-actions-i18n.test.ts` sit outside any domain folder.

**Function duration is capped at 60s**, except
`app/lib/integrations/bank-account/initiate-bank-reconnect.ts` at 90s
(`apps/webapp/vercel.json`).
