---
name: erp-kit-app-5-impl-backend
description: Implement backend code for applications using erp-kit modules. Use after completing plan review with erp-kit-app-4-plan-review. Triggers when implementing backend resolvers, wiring modules, configuring applications, or when the user mentions implementing backend, writing resolvers, or connecting erp-kit modules.
metadata:
  erp-kit-version: "0.23.0"
---

# Application Backend Implementation

Implement backend resolvers and application configuration for an application, driven by Tier 1-4 documentation. This phase adapts the existing backend to match the actual requirements.

## Version Check

Run `npx erp-kit --version` and compare against this skill's `metadata.erp-kit-version`. If they differ, the local skills are outdated — tell the user to run `pnpm erp-kit update skills` and stop.

## Progress Logging

Run `npx erp-kit app progress schema` once to load the schema before your first log. Log at every step boundary marked with **Log:** below using `npx erp-kit app progress log --json '<payload>'`. Every payload requires: `v` (always `1`), `sessionId`, `prompt` (user's original request), `event`, `data`, and `conversation` (array of `{role, message}` since last log). See [progress-protocol.md](../erp-kit-shared/references/progress-protocol.md) for the full schema reference.

## When to Use

- Implementing backend resolvers from resolver spec docs
- Wiring erp-kit modules into an application
- Configuring the Tailor application (auth, DB, resolvers)
- Deploying the backend for frontend schema generation

## Prerequisites

All four tiers of documentation must exist:

- `README.md` — Application overview
- `docs/actors/*.md` — Actor definitions
- `docs/business-flow/*/README.md` + `story/*.md` — Business flows and user stories
- `docs/screen/*.md` — Screen specifications (ListView, Form, DetailView)
- `docs/resolver/*.md` — Resolver specifications (mutations, queries)

> **Log:** `step.start` with `data: { skill: "erp-kit-app-5-impl-backend", context: { app: APP_NAME, resolvers: count, screens: count } }`

## Workflow

```
ANALYZE DOCS → MODULE WIRING → CONFIG → RESOLVERS → GENERATED FILES → DEPLOY
```

### Incremental Verification

Run `pnpm lint` and `pnpm typecheck` after each of Phase 2, 3, and 4. Fix errors before moving on.

### Phase 1: Analyze Documentation

Read all resolver and screen specs to build a complete picture:

1. **Resolver docs** (`docs/resolver/*.md`) — Identify which module commands each resolver calls, what inputs/outputs it needs, and what errors it handles
2. **Screen docs** (`docs/screen/*.md`) — Identify screen types (ListView, Form, DetailView) and their fields/columns/actions
3. **Command source types** — For each module command the resolver calls, read the input type at `node_modules/@tailor-platform/erp-kit/src/modules/<module>/command/<commandName>.ts`. Do not invent fields that don't exist in the command, and preserve the required/optional distinction.

Classify resolvers per [erp-kit-shared/references/resolver-classification.md](../erp-kit-shared/references/resolver-classification.md).

> **Parallelize if possible:** Dispatch one agent per resolver spec to extract inputs, outputs, module mapping, and error scenarios. Each agent reads a single resolver doc and returns structured analysis.

### Phase 1b: Code Orientation

Read `src/resolvers/`, `src/modules.ts`, and `src/executors/` to understand the existing implementation patterns. Keep what applies, adapt what's close, and remove what doesn't fit.

`erp-kit app generate code` produces additional stubs from `docs/resolver/*.md` for new resolvers added during the plan phase.

### Phase 2: Wire Modules (`src/modules.ts` + `src/modules-db.ts`)

Create the module wiring files that compose all required erp-kit modules.

**Read [module wiring reference](references/module-wiring.md) for the composition pattern.**

**Read [field builder API](../erp-kit-shared/references/db-field-api.md) and [database relations](references/db-relations.md) before writing any TailorDB model definitions.**

Key points:

- `modules.ts` — Use `defineXxxModule()` functions from `@tailor-platform/erp-kit/module` and export module objects for resolver use
- `modules-db.ts` — Destructure DB types into individual named exports for the DB scanner. This file must NOT be imported by resolvers.
- Pass inter-module dependencies explicitly (e.g., item-management needs primitives' unit type and query)

### Phase 3: Configure Application (`tailor.config.ts`)

**Read [application config reference](references/app-config.md) for the config pattern.**

Key points:

- Single DB namespace (`"main-db"`) with `gqlOperations: "query"` for automatic list/get queries
- Resolver/executor discovery via glob patterns
- Auth with OAuth2, DPoP, and user profile mapping
- Generators for Kysely types and seed data

> **Sync barrier:** Module wiring and configuration must complete before resolver implementation. These files are shared across all resolvers.

### Phase 4: Implement Backend Resolvers and Executors

Write one file per resolver under `src/resolvers/`, one per executor under `executors/`.

**Read [resolver patterns](references/resolver-patterns.md) and [executor patterns](references/executor-patterns.md).**

For each resolver, check whether its spec (`docs/resolver/*.md`) documents error codes. If it does, implement a `switch(result.error.code)` block — do not use generic `throw result.error`.

Do not directly mutate module-owned tables via Kysely — always use module commands.

After resolvers are done, implement the story integration test stubs in `backend/src/tests/stories/`. Each stub has `it()` descriptions from the story doc's `## Test Cases`. Use the GraphQL client and `inject("url")` / `inject("token")` to call resolvers. Run `pnpm test:integration` and `pnpm erp-kit app sync-check` to verify.

> **Parallelize if possible:** Dispatch one agent per resolver. Each agent writes only to its own files:
>
> - `src/resolvers/<resolverName>.ts`
> - `src/executors/<resolverName>.ts`
>
> **Shared-file guard:** `src/modules.ts`, `src/modules-db.ts`, and `tailor.config.ts` are written in the sync barrier phase above. Resolver agents must NOT modify these files.

### Phase 5: Generated Files

- **Kysely types** (`src/generated/kysely-tailordb.ts`) — Auto-generated by `pnpm generate` after deployment. Before deployment, create a minimal placeholder so the codebase typechecks.
- **Seed data** (`seed/`) — `exec.mjs` runner + `data/*.jsonl` (records) and `data/*.schema.ts` (validation).
  1. **Module seed** — Run `pnpm erp-kit app generate seed -p <app-path>` to generate module-provided defaults (currencies, units, UoM categories, exchange rates). This writes JSONL files to `seed/data/`, skipping files that already exist.
  2. **App-specific seed** — Manually create seed records for roles, test users, and domain-specific data. Permission keys support hierarchical matching — scope-level keys like `user-management:role` grant all commands under that scope.
  3. **Validate seed** — Run `pnpm run seed:validate` and fix any errors before proceeding.

### Phase 6: Redeploy Backend & Next Steps

After implementation changes, redeploy following [deploy workflow](../erp-kit-shared/references/deploy.md). Wait for the user to confirm deployment is complete before proceeding.

> **Log:** `step.complete` with `data: { status: "pass"|"fail"|"blocked", summary: "<one-line result with resolver/module counts>", artifacts: ["<list of created code paths>"] }`

After deployment is confirmed, proceed to frontend implementation with `/erp-kit-app-6-impl-frontend`.
