# soult-io/wagon-payroll architecture

> Architecture diagram of the GitHub repository soult-io/wagon-payroll, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/soult-io/wagon-payroll
- Repository: https://github.com/soult-io/wagon-payroll

## Overview

Wagon Payroll is a small-business payroll web application: admins manage workers and monthly payroll, while employees access payslips, invoices, profiles, and change requests. The Vue SPA calls a Fastify API, which owns payroll and related business workflows and persists data in Postgres. Payroll calculations are centralized in the deterministic engine; filing and tax-deposit features track obligations but leave actual filing and payment to administrators. The map preserves documented capabilities, but some route-to-service wiring is unsampled and is shown only where supported by the README or app registration.

Main entry points: [`apps/server/src/app.ts`](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/app.ts) (Fastify API), [`packages/db/src/schema.ts`](https://github.com/soult-io/wagon-payroll/blob/main/packages/db/src/schema.ts) (Postgres data), [`apps/server/src/payroll/runs.ts`](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/payroll/runs.ts) (Payroll lifecycle), [`apps/web/src/App.vue`](https://github.com/soult-io/wagon-payroll/blob/main/apps/web/src/App.vue) (Payroll SPA)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web application"]
  node_spa["Payroll SPA<br/>[App.vue]"]
  node_web_auth["Web auth client<br/>[auth-client.ts]"]
end

subgraph group_api["API and workflows"]
  node_api["Fastify API<br/>[app.ts]"]
  node_payroll_routes["Payroll routes<br/>[admin-payroll.ts]"]
  node_self_service["Employee services<br/>[my.ts]"]
  node_change_requests["Change requests<br/>[service.ts]"]
  node_contractors["Contractor workflow<br/>[service.ts]"]
end

subgraph group_core["Payroll and records"]
  node_payroll["Payroll lifecycle<br/>[runs.ts]"]
  node_engine["Payroll engine<br/>[payroll.ts]"]
  node_documents["Payroll documents<br/>[w2.ts]"]
  node_db[("Postgres data<br/>[schema.ts]")]
end

subgraph group_compliance["Tax compliance"]
  node_deposits["Tax deposits<br/>[service.ts]"]
  node_filings["Tax filings<br/>[service.ts]"]
  node_calendar["Obligations calendar<br/>[service.ts]"]
end

subgraph group_support["Platform services"]
  node_auth["Authentication<br/>[auth.ts]"]
  node_outbox["Notification outbox<br/>[outbox.ts]"]
  node_legacy["Legacy importer<br/>[cli.ts]"]
end

node_admins(("Admins"))
node_employees(("Employees"))
node_legacy_db[("Legacy accounting DB")]
node_smtp(("SMTP service"))

node_admins -->|"use admin UI"| node_spa
node_employees -->|"use self-service"| node_spa
node_spa -->|"call API"| node_api
node_spa -->|"authenticate via"| node_web_auth
node_web_auth -->|"auth requests"| node_api
node_api -->|"create auth"| node_auth
node_api -->|"register routes"| node_payroll_routes
node_payroll_routes -->|"manage payroll"| node_payroll
node_payroll -->|"calculate payroll"| node_engine
node_payroll -->|"persist runs"| node_db
node_payroll -->|"generate documents"| node_documents
node_api -->|"register routes"| node_self_service
node_api -->|"register routes"| node_change_requests
node_change_requests -->|"update employee data"| node_db
node_api -->|"register contractor routes"| node_contractors
node_contractors -->|"store invoices and payments"| node_db
node_api -->|"register deposit routes"| node_deposits
node_deposits -->|"track liabilities"| node_db
node_api -->|"register filing routes"| node_filings
node_filings -->|"read payroll records"| node_db
node_api -->|"register calendar routes"| node_calendar
node_calendar -->|"aggregate obligations"| node_db
node_change_requests -->|"enqueue notices"| node_outbox
node_contractors -->|"enqueue notices"| node_outbox
node_outbox -.->|"send email"| node_smtp
node_legacy_db -->|"import history"| node_legacy
node_legacy -->|"write migrated data"| node_db

click node_spa "https://github.com/soult-io/wagon-payroll/blob/main/apps/web/src/App.vue"
click node_web_auth "https://github.com/soult-io/wagon-payroll/blob/main/apps/web/src/lib/auth-client.ts"
click node_api "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/app.ts"
click node_auth "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/auth/auth.ts"
click node_payroll_routes "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/routes/admin-payroll.ts"
click node_payroll "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/payroll/runs.ts"
click node_engine "https://github.com/soult-io/wagon-payroll/blob/main/packages/engine/src/payroll.ts"
click node_documents "https://github.com/soult-io/wagon-payroll/blob/main/packages/documents/src/w2.ts"
click node_db "https://github.com/soult-io/wagon-payroll/blob/main/packages/db/src/schema.ts"
click node_self_service "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/routes/my.ts"
click node_change_requests "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/change-requests/service.ts"
click node_contractors "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/contractors/service.ts"
click node_deposits "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/deposits/service.ts"
click node_filings "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/filings/service.ts"
click node_calendar "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/calendar/service.ts"
click node_outbox "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/notify/outbox.ts"
click node_legacy "https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/migrate/cli.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_spa,node_web_auth toneBlue
class node_api,node_payroll_routes,node_self_service,node_change_requests,node_contractors,node_legacy_db toneAmber
class node_payroll,node_engine,node_documents,node_db toneMint
class node_deposits,node_filings,node_calendar toneRose
class node_auth,node_outbox,node_legacy,node_admins,node_employees,node_smtp toneIndigo
```

## Components

### Web application

- [Payroll SPA](https://github.com/soult-io/wagon-payroll/blob/main/apps/web/src/App.vue): `apps/web/src/App.vue`
- [Web auth client](https://github.com/soult-io/wagon-payroll/blob/main/apps/web/src/lib/auth-client.ts): `apps/web/src/lib/auth-client.ts`

### API and workflows

- [Fastify API](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/app.ts): `apps/server/src/app.ts`
- [Payroll routes](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/routes/admin-payroll.ts): `apps/server/src/routes/admin-payroll.ts`
- [Employee services](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/routes/my.ts): `apps/server/src/routes/my.ts`
- [Change requests](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/change-requests/service.ts): `apps/server/src/change-requests/service.ts`
- [Contractor workflow](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/contractors/service.ts): `apps/server/src/contractors/service.ts`

### Payroll and records

- [Payroll lifecycle](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/payroll/runs.ts): `apps/server/src/payroll/runs.ts`
- [Payroll engine](https://github.com/soult-io/wagon-payroll/blob/main/packages/engine/src/payroll.ts): `packages/engine/src/payroll.ts`
- [Payroll documents](https://github.com/soult-io/wagon-payroll/blob/main/packages/documents/src/w2.ts): `packages/documents/src/w2.ts`
- [Postgres data](https://github.com/soult-io/wagon-payroll/blob/main/packages/db/src/schema.ts): `packages/db/src/schema.ts`

### Tax compliance

- [Tax deposits](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/deposits/service.ts): `apps/server/src/deposits/service.ts`
- [Tax filings](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/filings/service.ts): `apps/server/src/filings/service.ts`
- [Obligations calendar](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/calendar/service.ts): `apps/server/src/calendar/service.ts`

### Platform services

- [Authentication](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/auth/auth.ts): `apps/server/src/auth/auth.ts`
- [Notification outbox](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/notify/outbox.ts): `apps/server/src/notify/outbox.ts`
- [Legacy importer](https://github.com/soult-io/wagon-payroll/blob/main/apps/server/src/migrate/cli.ts): `apps/server/src/migrate/cli.ts`

### Other components

- **Admins**
- **Employees**
- **Legacy accounting DB**
- **SMTP service**

## Connections

- Admins → Payroll SPA: use admin UI
- Employees → Payroll SPA: use self-service
- Payroll SPA → Fastify API: call API
- Payroll SPA → Web auth client: authenticate via
- Web auth client → Fastify API: auth requests
- Fastify API → Authentication: create auth
- Fastify API → Payroll routes: register routes
- Payroll routes → Payroll lifecycle: manage payroll
- Payroll lifecycle → Payroll engine: calculate payroll
- Payroll lifecycle → Postgres data: persist runs
- Payroll lifecycle → Payroll documents: generate documents
- Fastify API → Employee services: register routes
- Fastify API → Change requests: register routes
- Change requests → Postgres data: update employee data
- Fastify API → Contractor workflow: register contractor routes
- Contractor workflow → Postgres data: store invoices and payments
- Fastify API → Tax deposits: register deposit routes
- Tax deposits → Postgres data: track liabilities
- Fastify API → Tax filings: register filing routes
- Tax filings → Postgres data: read payroll records
- Fastify API → Obligations calendar: register calendar routes
- Obligations calendar → Postgres data: aggregate obligations
- Change requests → Notification outbox: enqueue notices
- Contractor workflow → Notification outbox: enqueue notices
- Notification outbox → SMTP service: send email
- Legacy accounting DB → Legacy importer: import history
- Legacy importer → Postgres data: write migrated data
