Course navigationPhase 36
Volume 08 · Phase 36

TaskFlow -> Enterprise Systems

Generalize TaskFlow patterns into larger enterprise systems while preserving modular boundaries, workflows, auditability, integration reliability, and migration paths.

16lessons + labs
4klesson words
19source references
What you will ship

Phase outcome and project increment

Learning outcome

Generalize TaskFlow patterns into larger enterprise systems while preserving modular boundaries, workflows, auditability, integration reliability, and migration paths.

Concrete deliverable

Enterprise expansion blueprint for an HRIS/procurement/inventory/payroll-style system with modules, workflows, events, audit, and scaling triggers.

Figure 36.1 — Where this phase lives in TaskFlow
business capabilities
modular monolith
workflow/state machines
transactional boundaries
outbox/events
background workers
reporting/integrations
scale-out only when earned
Trace the flow left-to-right for implementation and right-to-left for debugging. At every arrow, ask what data crosses the boundary and what proves it is trustworthy.
Instructor mental model

Principles to keep while coding

01

Enterprise scaling starts by identifying new business boundaries, compliance needs, load, and organizational ownership.

02

Keep the modular monolith viable until scale or team boundaries justify distributing the system.

03

Add queues, caches, services, and orchestration only for concrete bottlenecks or ownership needs.

04

Design replaceable infrastructure interfaces so managed services can evolve without rewriting core business rules.

Code-along path

Guided phase lab

Do these in order. Each step should end with evidence before the next one starts.

  1. 01

    Choose one enterprise domain and identify business capabilities before choosing services/databases.

  2. 02

    Design modules with explicit ownership and public interfaces inside a modular monolith.

  3. 03

    Model one long-running approval as a state machine with actors, transitions, evidence, and audit records.

  4. 04

    Identify a transaction that crosses an integration boundary and design an outbox/event handoff.

  5. 05

    Separate synchronous user requests from background work such as reports, imports, notifications, or payroll runs.

  6. 06

    Write concrete scaling triggers that would justify extracting a service, queue, cache, or separate database later.

Debugging studio

Failures you should know how to diagnose

Failure drill 1

Microservices before module boundaries are understood

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Failure drill 2

Boolean fields replacing explicit workflow states

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Failure drill 3

Dual writes to database and message broker without reliability design

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Failure drill 4

Shared database tables with unclear ownership across domains

Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.

Watch-order style

Lessons

The source chapters come first. Every phase now ends with a guided build, a debugging workshop, and an independent challenge so reading turns into transferable skill.

01

Modular Monolith and Domain Boundaries

Modular Monolith First: Domain Boundaries A growing system should first become modular in code and data ownership. A modular monolith keeps one deployment while giving each business capabili

2 min
02

Enterprise Domain Decomposition Blueprints

Domain Decomposition Blueprints TaskFlow concepts transfer into enterprise domains, but the nouns and invariants change. Model the business capability first, then reuse the architectural pat

2 min
03

Approval Workflows and Long Running Processes

Approval Workflows and Long-Running Processes Enterprise systems contain processes that live longer than one HTTP request. Model the workflow explicitly instead of scattering booleans such a

2 min
04

Audit Trails History and Effective Dates

Audit Trails, History, and Effective Dates Enterprise data often needs an answer to “who changed what, when, why, and from which business state?” That is different from ordinary application

2 min
05

Background Jobs Idempotency and Retries

Background Jobs, Idempotency, and Retries Payroll calculation, report generation, imports, email batches, document generation, and integrations should not turn user-facing HTTP requests into

2 min
06

Financial Correctness Payroll and Accounting

Financial Correctness: Payroll and Accounting Financial systems need stronger invariants than ordinary CRUD. Monetary arithmetic, finalization, periods, rounding, and reproducibility must be

2 min
07

Procurement Inventory and Stock Consistency

Procurement, Inventory, and Stock Consistency Procurement and inventory illustrate why enterprise systems need ledgers, reservations, and transaction boundaries rather than one mutable “quan

2 min
08

Integration Boundaries Events and Outbox

Integration Boundaries, Events, and the Outbox Pattern Enterprise systems integrate with banks, biometrics, email/SMS, government services, accounting systems, suppliers, and identity provid

2 min
09

Reporting Read Models and Exports

Reporting, Read Models, and Exports Operational screens and enterprise reports have different query needs. Do not distort transactional models only to make one heavy report convenient. Trans

2 min
10

Enterprise Permissions and Segregation of Duties

Enterprise Permissions and Segregation of Duties OWNER/ADMIN/MEMBER is sufficient for TaskFlow, but enterprise systems often need permission scopes, organizational context, approval limits,

2 min
11

Scaling Migration and Service Extraction

Scaling and Migration Without a Rewrite The TaskFlow architecture is intentionally replaceable. Scale the constrained boundary first, then extract only where independent operation creates mo

2 min
12

Enterprise Capstone and Course Exit

Enterprise Capstone and Course Exit The final exercise is to convert one enterprise domain into an implementable architecture using the same reasoning applied throughout TaskFlow. - - - - Pl

2 min
LAB

Guided Build Lab

Purpose Generalize TaskFlow patterns into larger enterprise systems while preserving modular boundaries, workflows, auditability, integration reliability, and migration paths.

3 min
LAB

Debugging Workshop

Goal Learn to diagnose this phase's failures systematically instead of reinstalling packages, changing random configuration, or copying a fix without understanding it.

2 min
LAB

Phase Synthesis & Independent Challenge

Mission Rebuild the capability of Phase 36 without following the exact code line-by-line. The goal is transfer: can you use the ideas when the variable names, UI, or route shape changes?

2 min
LAB

Mastery Capstone Lab

Integrate Phase 36 without following a transcript.

2 min
Practice ladder

Exercises that increase independence

Guided

Choose one enterprise domain and identify business capabilities before choosing services/databases.

Practice

Model one long-running approval as a state machine with actors, transitions, evidence, and audit records.

Debug

reproduce and diagnose — Microservices before module boundaries are understood.

Independent

deliver Enterprise expansion blueprint for an HRIS/procurement/inventory/payroll-style system with modules, workflows, events, audit, and scaling triggers.

Explain-back

Can decompose by business capability and Can model long-running workflows.

Mastery gate

Do not leave the phase only because you reached the bottom

Phase exit criteria

Knowledge check

Scenario and concept quiz

These questions test engineering choices rather than whether you remember a lesson title.

0/0 correct · 0/8 answered
01Which practice best matches Phase 36's engineering goal?
02Which practice best matches Phase 36's engineering goal?
03Which practice best matches Phase 36's engineering goal?
04Which practice best matches Phase 36's engineering goal?
05You are working through the Phase 36 lab. Which next action is the most disciplined step?
06You are working through the Phase 36 lab. Which next action is the most disciplined step?
07You are working through the Phase 36 lab. Which next action is the most disciplined step?
08You are working through the Phase 36 lab. Which next action is the most disciplined step?
Source snapshot

Reference files

Attempt the work first. Use snapshots to compare a checkpoint, not as a substitute for understanding.

reference/TaskFlow_Enterprise_Systems_Blueprint/APPROVAL_WORKFLOW_TEMPLATE.md
# Approval Workflow Template

## States
DRAFT -> SUBMITTED -> REVIEW -> APPROVED -> EXECUTED

## For each transition define
- command name
- allowed source state
- target state
- actor permission
- organizational scope
- monetary/other approval limits
- preconditions
- required reason/comment
- audit event
- side effects / queued work

Never expose a generic API that lets a client assign any workflow state directly.
reference/TaskFlow_Enterprise_Systems_Blueprint/AUDIT_EVENT_SCHEMA.md
# Audit Event Schema

Suggested fields:

- id
- occurredAt
- actorUserId / auth subject
- workspace/company/department context
- action
- entityType
- entityId
- reason
- beforeJson (only appropriate fields)
- afterJson (only appropriate fields)
- requestId / correlationId
- source (WEB/API/JOB/INTEGRATION)

For critical changes, write the audit event in the same database transaction as the business change. Do not put credentials or unnecessary sensitive data into audit payloads.
reference/TaskFlow_Enterprise_Systems_Blueprint/CAPSTONE_BLUEPRINT.md
# Final Enterprise Capstone Blueprint

Choose HRIS, Procurement+Inventory, or Accounting. Produce:

1. Module/bounded-context map.
2. Key entities and invariants.
3. State/approval workflows.
4. Permission + scope + segregation-of-duties matrix.
5. Transaction boundaries.
6. Audit-event model.
7. Background-job and idempotency plan.
8. Integration contracts and outbox/inbox strategy.
9. Reporting/read-model strategy.
10. Test matrix and failure-recovery cases.
11. Deployment/observability plan.
12. ADRs for the three highest-impact architecture decisions.
13. Evidence/triggers that would justify future service extraction.
reference/TaskFlow_Enterprise_Systems_Blueprint/DOMAIN_MODULE_CATALOG.md
# Domain Module Catalog

| Module | Owns | Example commands |
|---|---|---|
| People | Employee/employment/org assignments | hireEmployee, transferEmployee, terminateEmployment |
| Leave | Leave balances and requests | submitLeave, approveLeave, cancelLeave |
| Payroll | Payroll runs/pay items/deductions | calculatePayroll, finalizePayroll, markPaid |
| Procurement | Requisitions/POs/suppliers | submitRequisition, approvePO, cancelPO |
| Inventory | Items/warehouses/movements | receiveStock, issueStock, transferStock |
| Accounting | Accounts/journals/periods | postJournal, closePeriod, reverseJournal |
| Recruitment | Openings/applicants/offers | advanceApplicant, approveOffer, hireApplicant |

Each module exports a small public service/event contract. Do not expose repositories or Prisma models as the default cross-module API.
reference/TaskFlow_Enterprise_Systems_Blueprint/ENTERPRISE_ARCHITECTURE_MAP.md
# Enterprise Architecture Map

```text
Next.js
  -> NestJS/Fastify modular application
      -> People / Payroll / Leave / Procurement / Inventory / Accounting / Recruitment
      -> Repository interfaces / Prisma implementations
      -> PostgreSQL
      -> BullMQ workers for long-running work
      -> Supabase Auth / Storage / Realtime where applicable
```

Start as a modular monolith. Extract workers or services only when scaling, reliability, compliance, release cadence, or team ownership creates real pressure.
reference/TaskFlow_Enterprise_Systems_Blueprint/ENTERPRISE_PERMISSION_MATRIX.md
# Enterprise Permission Matrix - Example

| Role | Scope | Example permissions | Extra constraints |
|---|---|---|---|
| HR Officer | company/department | employee.read, leave.review | cannot edit payroll result |
| Payroll Officer | company | payroll.calculate, payslip.generate | finalization may require second approver |
| Supervisor | team | leave.approve, employee.read.team | relationship-scoped |
| Procurement Officer | business unit | requisition.manage, po.create | cannot final approve own PO |
| Department Head | department | po.approve | approval amount threshold |
| Accounting | company | journal.post, period.read | closed-period rule |

Authorization decision = identity + scope + permission + relationship + business rule.
reference/TaskFlow_Enterprise_Systems_Blueprint/FINANCIAL_CORRECTNESS.md
# Financial Correctness Checklist

- Use exact decimal/numeric amounts, never binary float for authoritative money.
- Store currency explicitly.
- Define rounding mode and rounding stage.
- Version tables/formulas/rates used for payroll calculations.
- Finalized payroll/journals should be immutable; corrections use adjustments/reversals.
- Journal entries must balance before posting.
- Closed accounting periods reject normal postings.
- Recalculation must be reproducible from durable inputs/version references.
reference/TaskFlow_Enterprise_Systems_Blueprint/IDEMPOTENCY_AND_JOBS.md
# Idempotency and Background Jobs

Course line:
- @nestjs/bullmq 12.0.0
- BullMQ 6.x

## Example job key
`payroll-run:<runId>:calculate`

## Worker rule
1. Load durable operation state.
2. If already completed, return the durable result.
3. Claim/process according to concurrency policy.
4. Persist progress/results.
5. Make external side effects independently idempotent.

BullMQ recommends idempotent jobs so retries converge to the same final state. BullMQ 6 uses Job Schedulers for recurring work.
reference/TaskFlow_Enterprise_Systems_Blueprint/INTEGRATION_BOUNDARIES.md
# Integration Boundaries

## Outbound
Business transaction -> outbox row -> worker -> external provider -> delivery state.

## Inbound webhook
Verify authenticity -> persist provider event ID -> deduplicate -> process business command -> persist result.

## Contract rule
Use business events such as `PurchaseOrderApproved` and version their payloads. Avoid publishing raw Prisma rows as long-lived external contracts.
reference/TaskFlow_Enterprise_Systems_Blueprint/MIGRATION_ROADMAP.md
# Migration Roadmap

## Stage 1 - Modular monolith
Single API, explicit Nest feature modules, one PostgreSQL cluster.

## Stage 2 - Worker separation
BullMQ workers for payroll calculation, imports, exports, notification batches, integrations.

## Stage 3 - Read scaling
Indexes, read models, replicas/analytics pipeline where evidence requires.

## Stage 4 - Selective service extraction
Only modules with independent scale/reliability/team/compliance pressure.

## Infrastructure replacement path
- Supabase PostgreSQL -> self-hosted/AWS PostgreSQL
- Supabase Storage -> S3-compatible storage adapter
- Upstash/managed Redis -> alternate Redis
- Railway/Render -> AWS containers/Kubernetes when operations justify it
reference/TaskFlow_Enterprise_Systems_Blueprint/README.md
# TaskFlow Enterprise Systems Blueprint

This is the final course reference snapshot. It does not turn TaskFlow into one giant ERP implementation. Instead it provides reusable architecture templates for evolving the same principles into HRIS, payroll, procurement, inventory, accounting, recruitment, and other enterprise modules.

The default evolution strategy is:
1. modular monolith,
2. durable background workers,
3. purpose-built read models,
4. selective service extraction only when evidence justifies it.
reference/TaskFlow_Enterprise_Systems_Blueprint/REPORTING_ARCHITECTURE.md
# Reporting Architecture

Start simple:
1. Indexed PostgreSQL query.
2. Purpose-built projection/select.
3. View/materialized read model if repeated pressure justifies it.
4. Background job for large Excel/PDF exports.
5. Store generated artifact metadata; Storage holds bytes.

Always apply tenant/department authorization to reports and exports. Historical reports must use effective-dated/versioned business data where required.
reference/TaskFlow_Enterprise_Systems_Blueprint/SOURCES.md
# Phase 36 Sources

Official references consulted:

- NestJS Modules: https://docs.nestjs.com/modules
- BullMQ Idempotent Jobs: https://docs.bullmq.io/patterns/idempotent-jobs
- BullMQ Job IDs/Deduplication: https://docs.bullmq.io/guide/jobs/job-ids
- BullMQ Job Schedulers: https://docs.bullmq.io/guide/job-schedulers/
- BullMQ Flows: https://docs.bullmq.io/guide/flows/
- @nestjs/bullmq npm: https://www.npmjs.com/package/@nestjs/bullmq
- BullMQ npm: https://www.npmjs.com/package/bullmq
- PostgreSQL 18 Monetary Types: https://www.postgresql.org/docs/18/datatype-money.html
- PostgreSQL 18 Data Types (`numeric` / `decimal` exact numeric): https://www.postgresql.org/docs/18/datatype.html

Architecture patterns such as modular monoliths, transactional outbox/inbox, effective-dated history, segregation of duties, and read models are presented as engineering patterns; their exact implementation must follow the target organization's regulatory and business requirements.
reference/TaskFlow_Enterprise_Systems_Blueprint/VERSION_LOCK.md
# Phase 36 Version Notes

Existing course locks remain:
- Next.js 16.x
- NestJS 12.x
- Fastify 5.x
- Prisma 7.9.1 (hard course lock)
- PostgreSQL 18 line
- Zod 4.x
- TanStack Query 5.x

New enterprise-worker line verified for this phase:
- @nestjs/bullmq 12.0.0
- BullMQ 6.x (current npm line observed: 6.3.x)

Do not auto-upgrade these inside an existing course checkpoint. Verify release notes and tests first.
reference/TaskFlow_Enterprise_Systems_Blueprint/apps/api/src/modules/payroll/payroll-run.states.ts
export type PayrollRunState =
  | "DRAFT"
  | "CALCULATING"
  | "REVIEW"
  | "FINALIZED"
  | "PAID";

// FINALIZED results should normally become immutable.
// Corrections should create explicit adjustments/reversals rather than
// silently rewriting historical payroll evidence.
reference/TaskFlow_Enterprise_Systems_Blueprint/apps/api/src/modules/procurement/approval-state-machine.ts
export type PurchaseOrderState =
  | "DRAFT"
  | "SUBMITTED"
  | "APPROVED"
  | "REJECTED"
  | "CANCELED";

export function canApprovePurchaseOrder(
  state: PurchaseOrderState,
): boolean {
  return state === "SUBMITTED";
}

// Real policy additionally checks permission, scope, approval limit,
// segregation of duties, budget, and other organization rules.
reference/TaskFlow_Enterprise_Systems_Blueprint/apps/api/src/modules/procurement/procurement.module.ts
import { Module } from "@nestjs/common";

// Illustrative final-course module boundary.
@Module({
  imports: [],
  controllers: [],
  providers: [],
  exports: [],
})
export class ProcurementModule {}
reference/TaskFlow_Enterprise_Systems_Blueprint/apps/api/src/workers/payroll.worker.example.ts
// Pseudocode-level example for Phase 36.

async function calculatePayrollJob(runId: string) {
  const run = await loadPayrollRun(runId);

  if (run.status === "FINALIZED" || run.status === "CALCULATED") {
    return run; // durable idempotent result
  }

  await claimRunForCalculation(runId);
  const result = await calculateFromVersionedInputs(runId);
  return persistCalculatedResult(runId, result);
}

declare function loadPayrollRun(id: string): Promise<any>;
declare function claimRunForCalculation(id: string): Promise<void>;
declare function calculateFromVersionedInputs(id: string): Promise<any>;
declare function persistCalculatedResult(id: string, value: any): Promise<any>;
reference/TaskFlow_Enterprise_Systems_Blueprint/tests/enterprise-test-matrix.md
# Enterprise Test Matrix

| Risk | Minimum verification |
|---|---|
| Unauthorized payroll finalization | HTTP E2E + permission policy test |
| Duplicate payroll job delivery | idempotency integration test |
| PO creator self-approves despite SoD | authorization/business policy test |
| Stock transfer partially commits | PostgreSQL transaction/failure integration test |
| Accounting journal unbalanced | pure policy + service test |
| Closed-period posting | service + HTTP E2E |
| Webhook delivered twice | inbox/idempotency integration test |
| Outbox publish fails after DB commit | worker recovery test |
| Report leaks another department | real PostgreSQL scoped query + E2E |
| Audit record missing on critical command | transaction integration test |
| Finalized payroll mutated | repository/service invariant test |
| Worker retry exposes duplicate external side effect | integration contract/idempotency test |