| name | open-accounting-development |
| description | Use when developing or debugging open-accounting - covers multi-tenant architecture, testing strategy (especially E2E for demo interface), and layer responsibilities. Activate for feature work, bug fixes, test writing, or demo mode issues. |
Open Accounting Development Guide
Architecture Context
Multi-Tenant Data Flow
Request → Auth Middleware (JWT → user_id, tenant_id, role)
→ Tenant Middleware (sets schema name: "tenant_{uuid}")
→ Handler (validates input, extracts tenant context)
→ Service (business logic, orchestrates repositories)
→ Repository (schema-qualified queries: SELECT FROM {schema}.table)
Layer Responsibilities
| Layer | Owns | Does NOT Own |
|---|
| Handler | HTTP concerns, input validation, response formatting | Business logic, DB transactions |
| Service | Business rules, orchestration, cross-entity logic | HTTP details, direct SQL |
| Repository | Data access, schema qualification, query building | Business validation, HTTP context |
Key Files for Debugging
- Tenant context:
internal/auth/middleware.go (JWT extraction)
- Schema routing:
internal/tenant/service.go (schema name generation)
- Demo detection: Check for
demo@example.com user or demo tenant ID
- Multi-tenant queries: All repositories use
schemaName parameter for table qualification
Testing Strategy
Decision Tree - Which Test Type?
Is the change in...
├── Repository layer? → Integration test (needs real DB)
│ └── File: internal/{domain}/*_test.go with //go:build integration
│
├── Service layer? → Unit test with mocked repository
│ └── File: internal/{domain}/*_test.go
│
├── Handler layer? → Unit test with mocked service
│ └── File: internal/{domain}/handlers_test.go
│
├── Frontend component? → Vitest component test
│ └── File: frontend/src/tests/components/*.test.ts
│
├── User-facing workflow? → E2E test
│ └── Demo flow? → frontend/e2e/demo-*.spec.ts
│ └── Regular flow? → frontend/e2e/*.spec.ts
Coverage Targets
| Layer | Target |
|---|
| Backend (unit + integration) | 90%+ |
| Frontend | 95%+ |
| Critical paths (auth, payments) | 95%+ |
| Demo interface | 100% E2E |
Demo E2E Priority
The demo at open-accounting.up.railway.app is the first impression for users. All demo functionality must have E2E coverage:
- Login/logout flow
- Dashboard widgets and navigation
- CRUD operations (invoices, contacts, payments)
- Report generation and exports
- Error states and edge cases
Demo Mode Reference
Credentials
- Email:
demo@example.com
- Password:
demo123
- Live demo:
open-accounting.up.railway.app
Demo Data Seeding Flow
Login as demo@example.com
→ Backend checks if demo tenant exists
→ If not: creates tenant + schema + seeds demo data
→ If exists: optionally resets to fresh state (hourly on Railway)
Key Demo Files
| Purpose | Location |
|---|
| Seed logic | internal/tenant/demo_seed.go |
| Demo handlers | internal/tenant/handlers.go (demo reset endpoint) |
| E2E tests | frontend/e2e/demo-*.spec.ts |
| Test config | frontend/playwright.config.ts |
| Test reports | frontend/playwright-report-demo/ |
Multi-User Parallel Testing
E2E tests support parallel execution with isolated demo data:
- Each test worker gets unique demo seed
- Tenant IDs passed via URL parameters for data isolation
- Prevents test interference when running in CI
Debugging Demo Issues
-
Check tenant schema exists:
SELECT schema_name FROM information_schema.schemata
WHERE schema_name LIKE 'tenant_%';
-
Verify seed data: Check internal/tenant/demo_seed.go for expected accounts/contacts/invoices
-
Check E2E logs: Review frontend/playwright-report-demo/ for failure screenshots and traces
-
Test locally: cd frontend && bun run test:e2e:demo
Documentation Checklist
After implementing a feature or fix, update relevant docs:
| Change Type | Update |
|---|
| API change | docs/API.md |
| Architecture change | docs/ARCHITECTURE.md |
| Demo behavior change | README.md demo section |
| New E2E test patterns | docs/plans/ design doc |
| Translation keys added | Both messages/en.json and messages/et.json |
Plan Documents
For non-trivial work, create a design doc before implementation:
- Location:
docs/plans/YYYY-MM-DD-{topic}-design.md
- Purpose: Capture decisions, trade-offs, implementation approach
- Example:
docs/plans/2026-01-04-demo-data-reset-testing-design.md
Commit Message Format
feat: add new capability
fix: resolve bug
docs: documentation only
test: add or update tests
refactor: restructure without behavior change
chore: maintenance tasks
Error Handling Patterns
Tenant Validation (Frontend)
All action handlers must validate tenant context and show errors to users:
import { requireTenantId, parseApiError } from '$lib/utils/tenant';
import ErrorAlert from '$lib/components/ErrorAlert.svelte';
async function doAction() {
const tenantId = requireTenantId($page, (err) => (error = err));
if (!tenantId) return;
actionLoading = true;
error = '';
try {
await api.someAction(tenantId, ...);
success = 'Action completed';
} catch (err) {
error = parseApiError(err);
} finally {
actionLoading = false;
}
}
Common Error Types
| Error | Cause | User Message |
|---|
| No tenant | URL missing ?tenant= param | "Please select an organization first" |
| Access denied | User not member of tenant | "Access denied to this organization" |
| Session expired | JWT expired | "Your session has expired. Please log in again." |
| Network error | API unreachable | "Network error. Please try again." |
Key Files
| Purpose | Location |
|---|
| Tenant validation | frontend/src/lib/utils/tenant.ts |
| Error alerts | frontend/src/lib/components/ErrorAlert.svelte |
| Global error page | frontend/src/routes/+error.svelte |
| API error parsing | frontend/src/lib/utils/tenant.ts (parseApiError) |
MCP Server
The project includes an MCP server for AI assistant integration.
Setup
cd mcp-server
bun install
bun run dev
Add to Claude Code
claude mcp add open-accounting -- npx tsx /path/to/mcp-server/src/index.ts
Environment Variables
OPEN_ACCOUNTING_API_URL=http://localhost:8080
OPEN_ACCOUNTING_API_TOKEN=your-jwt-token
Available Tools
list_invoices - List invoices with filters
create_invoice - Create new invoice
get_account_balance - Get account balance
generate_report - Generate financial reports
list_contacts - List customers/vendors
record_payment - Record a payment
get_chart_of_accounts - Get chart of accounts
Quick Reference
Common Commands
go test -race -cover ./...
go test -tags=integration -race ./...
go run ./cmd/api
cd frontend
bun run dev
bun test
bun run test:e2e
bun run test:e2e:demo
bun run check
bun run paraglide
Project URLs (Local)
- API:
http://localhost:8080
- Frontend:
http://localhost:5173
- Swagger:
http://localhost:8080/swagger/