AI Skill Report Card
Engineering Backend Services
Markdown--- name: engineering-backend-services description: Designs and implements secure, production-ready backend services covering REST APIs, GraphQL, databases, authentication, authorization, validation, and logging. Use when building or reviewing backend endpoints, database schemas, auth flows, or any server-side code that must be secure by default with proper error handling, audit logging, and rollback strategies. ---
Quick Start15 / 15
When asked to build a backend feature, produce these four deliverables together:
- Folder structure — where files live
- Files — list of files created/modified
- Code — full implementation, secure by default
- Validation Flow — diagram/steps of how input is validated and rejected
Example request: "Create an endpoint to register a new user"
src/
modules/
auth/
auth.controller.ts
auth.service.ts
auth.validation.ts
auth.repository.ts
middleware/
errorHandler.ts
auditLogger.ts
db/
migrations/
001_create_users_table.sql
TypeScript// auth.validation.ts import { z } from "zod"; export const registerSchema = z.object({ email: z.string().email(), password: z.string().min(8).max(72), name: z.string().min(2).max(100), });
TypeScript// auth.controller.ts import { registerSchema } from "./auth.validation"; import { AuthService } from "./auth.service"; import { auditLog } from "../../middleware/auditLogger"; export async function register(req, res, next) { try { const parsed = registerSchema.safeParse(req.body); if (!parsed.success) { return res.status(400).json({ error: "ValidationError", details: parsed.error.flatten() }); } const user = await AuthService.registerUser(parsed.data); auditLog({ action: "USER_REGISTER", actorId: user.id, metadata: { email: user.email }, }); return res.status(201).json({ id: user.id, email: user.email }); } catch (err) { next(err); // delegate to centralized error handler } }
Validation Flow:
Request → Schema Validation (reject 400) → Business Rule Check
(e.g. email uniqueness, reject 409) → DB Transaction (begin)
→ Hash password → Insert user → Commit
→ On any failure: Rollback → Audit log failure → Return safe error
→ Audit log success → Response
Recommendation▾
Add an example showing a rejected/failure-path output (bad outcome), not just successful designs
Workflow14 / 15
Progress checklist for every backend task:
- Step 1: Clarify the resource/entity and its data model
- Step 2: Define validation schema (input boundaries, types, limits)
- Step 3: Design folder structure (controller/service/repository/validation separation)
- Step 4: Implement authentication check (who is calling)
- Step 5: Implement authorization check (what they're allowed to do)
- Step 6: Implement core logic wrapped in DB transaction with rollback on failure
- Step 7: Add centralized error handling (never leak stack traces/internal errors to client)
- Step 8: Add audit logging for security-relevant actions (create/update/delete/auth events)
- Step 9: Write the Validation Flow explanation
- Step 10: List Folder + Files summary
Recommendation▾
Include a brief note on database choice tradeoffs (SQL vs NoSQL) or defer explicitly to keep scope tight
Examples18 / 20
Example 1: Input: "Buat REST endpoint untuk update role user (admin only)" Output:
- Folder:
src/modules/users/withusers.controller.ts,users.service.ts,users.validation.ts - Files: role update handler + middleware
requireRole('admin') - Code: Zod schema validating
{ userId: uuid, role: enum }, controller checksreq.user.role === 'admin'before calling service, service wraps update in a DB transaction, catches unique/foreign-key errors and rolls back - Validation Flow:
Auth token check → Authorization (admin only, else 403) → Schema validation (else 400) → Check target user exists (else 404) → Transaction: update role → commit → audit log (ROLE_CHANGED, actor, target, oldRole, newRole) → response
Example 2: Input: "Buat GraphQL mutation createOrder" Output:
- Folder:
src/graphql/order/withorder.resolver.ts,order.schema.graphql,order.validation.ts - Files: resolver, typeDefs, input validation, repository
- Code: resolver validates input via Zod before touching DB, wraps stock-decrement + order-insert in one transaction, throws
GraphQLErrorwith safe message on failure, logs full error internally - Validation Flow:
Auth context check (JWT in context) → Input validation (Zod, else GraphQLError BAD_USER_INPUT) → Authorization (user owns cart / has permission) → Transaction: decrement stock, create order → on stock insufficient: rollback + return controlled error → commit → audit log ORDER_CREATED → return order payload
Recommendation▾
Consider adding a minimal test/verification checklist item (e.g., unit test for validation edge cases)
Best Practices
- Secure by default: whitelist inputs (never trust client), deny by default on authorization, hash/encrypt sensitive fields, never log secrets/passwords/tokens.
- Separate layers: controller (HTTP/GraphQL concerns) → service (business logic) → repository (DB access). Validation happens before service is called.
- Transactions for multi-step writes: any operation touching 2+ tables/documents must be atomic with explicit rollback on error.
- Centralized error handler: map internal errors to safe, consistent client responses (
{ error: string, code: string }); never expose stack traces or SQL errors. - Audit logging: log actor, action, target, timestamp, and outcome for all state-changing and auth-related operations — store separately from application debug logs.
- Idempotency where relevant (payments, retries) using idempotency keys.
- Parameterized queries only — never string-concatenate SQL.
- Rate limiting & input size limits on public-facing endpoints.
Common Pitfalls
- Do NOT trust client-supplied IDs/roles without server-side authorization checks.
- Do NOT skip transactions on multi-table writes — partial failures leave inconsistent state.
- Do NOT log raw passwords, tokens, or PII in audit/debug logs.
- Do NOT return raw exception messages or stack traces to the client.
- Do NOT mix validation logic inside controllers/resolvers — keep it in a dedicated schema file.
- Do NOT forget rollback path — every
BEGINneeds a guaranteedCOMMITorROLLBACK. - Do NOT skip the Validation Flow output — it's required alongside code, not optional documentation.