---
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.9.0"
---

# Application Backend Implementation

Implement backend resolvers and application configuration for an application, driven by Tier 1-4 documentation (actors, business flows, stories, screens, resolvers).

## 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

Log to the audit trail at every checkpoint. See [erp-kit-app-shared/references/progress-protocol.md](../erp-kit-app-shared/references/progress-protocol.md) for the full protocol.

```bash
npx erp-kit app progress log --json '<ProgressInput JSON>'
```

Required checkpoints: `step.start` (on invocation), `decision` (on user choices), `agent.dispatch`/`agent.result` (on subagent lifecycle), `artifact.create` (on file writes), `validation` (on `erp-kit app check` or build commands), `step.complete` (on finish), `error` (on failures).

Bundle all conversation since the last checkpoint into the `conversation` array. Use your session ID as `sessionId`. Use the user's original prompt as `prompt`.

## 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)

## 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-app-shared/references/resolver-classification.md](../erp-kit-app-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: Scaffolded Code Orientation

`erp-kit app generate code` produces two kinds of files:

- **Reference examples** — `src/resolvers/createUser.ts`, `src/modules.ts`, `src/executors/permissionCreated.ts` show the implementation pattern (command invocation, error handling, context creation). Use these as a guide.
- **Generated stubs** — Minimal resolver files created from `docs/resolver/*.md`. These are your starting points for actual implementation.

When implementing in Phase 4, follow the patterns from the reference examples. Once all actual resolvers are implemented, delete the reference files that aren't needed by your app.

### 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.**

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 & executor patterns reference](references/resolver-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 generated in Phase 1b (`backend/src/tests/stories/`). Each stub has `it()` descriptions from the story doc's `## Test Cases`. Use the scaffolded 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 permissions, roles, test users, and domain-specific data. Seeded users must have concrete permission keys required by the wired modules.
  3. **Validate seed** — Run `pnpm run seed:validate` and fix any errors before proceeding.

### Phase 6: Deploy Backend & Next Steps

Frontend implementation requires a deployed backend (for GraphQL schema generation). Prompt the user to:

1. Create a workspace via `tailor-sdk workspace create --name <NAME> --region <us-west|asia-northeast>` and configure `.env` (including `TAILOR_PLATFORM_WORKSPACE_ID`)
2. Run `pnpm run deploy` and `pnpm run generate`
3. Run `pnpm run seed` if seed data was created
4. Retrieve OAuth2 client ID via `tailor-sdk oauth2client get default --json --env-file-if-exists .env` for frontend `.env`

Wait for the user to confirm deployment is complete before proceeding.

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