Skip to main content

Canonical crp module surface - design

Tier: Public
Status: Draft surface design 2026-05-26; Wave 5 read-only AI planning advisor, Wave 6 rendering templates, and alpha demo walkthrough automation shipped; alpha proof not complete (human sign-off pending) Audience: core team, CRP implementers, brewery-vertical maintainers, automation maintainers, module SDK authors, AI-consultant maintainers
Resolves: crp open-door next step from modules/canonical/crp.md
Builds on: RFC-0001, RFC-0002, canonical-automation-module-surface.md, mrp-crp-august-2026-co-design-plan.md

[!NOTE] Wave 1 shipped @umbraculum/crp-contracts, the crp Prisma schema, read-only API skeleton routes, module/web-segment registration, and L2 isolation tests. Wave 2 projects brewery/automation planning sources into those read routes at request time. Wave 3 exposes those read models in the web app through read-only resources, capacity, and schedule pages. Wave 4 adds deterministic E2E fixture proof across resources, work-center context, capacity load, scheduled operations, and read-only conflicts. Wave 5 adds module-owned read-only AI tools for resources, work centers, scheduled operations, capacity load, and conflicts. Wave 6 registers four RFC-0007 document templates and capacity/schedule render-job routes. This is still not alpha-complete: no native write workflow, optimizer, automation-control behavior, or complete public-alpha proof is claimed as shipped.


1. Summary

crp is the canonical capacity requirements planning module: the shared capacity-planning kernel for resources, work centers, calendars, scheduled operations, capacity load, and conflict detection. It consumes production operations from mrp and resource/vessel references from automation/brewery, but it does not own production-order lifecycle or live controller state.

LayerPlanned beta-layout locationPlanned responsibility
Contractspackages/canonical/crp/contracts/ -> @umbraculum/crp-contractsWave 1 shipped: DTOs, Zod schemas, CONTRACT_VERSION, resource/work-center/calendar/load/conflict refs, planned AI/rendering payload schemas.
APIservices/api/src/modules/crp/Wave 1–6 shipped (read + rendering): read-only routes, services, Prisma crp schema, module registration, read-time brewery/automation projections, read-only AI tool handlers, and RFC-0007 document templates with render-job routes.
Webapps/web/app/[locale]/(crp)/Wave 3 shipped: read-only resources, resource detail, capacity-load, schedule, and conflict pages under registered static URL segments. Proposal/write pages remain future work.
Nativeapps/native/src/modules/crp/Future operator/manager screens; may trail web in alpha.
Renderingmodule-registered templatesWave 6 shipped: capacity-load XLSX, schedule PDF, resource-calendar CSV, conflict-report PDF via RFC-0007.
AI toolsmodule-owned registerAiTools hookWave 5 shipped: crp.listResources, crp.listWorkCenters, crp.listScheduledOperations, crp.explainCapacityLoad, and crp.listConflicts as read-only advisor tools. Propose/write tools and optimizer behavior remain future work.

2. Canonical extensibility stance

crp is an extensible canonical kernel, not a complete commercial CRP/APS suite. The first implementation should expose stable primitives and extension points:

  • resources and work centers,
  • calendars and availability windows,
  • scheduled operations,
  • capacity-load calculations,
  • conflict detection,
  • scheduling proposals,
  • future optimizer plug-in boundary,
  • AI-tool hooks,
  • rendering-template hooks,
  • tier-limit/add-on declarations,
  • clear handoff from MRP and automation.

Out of scope for the first alpha surface:

  • full finite-capacity optimizer,
  • labor planning and skill matrices,
  • multi-plant scheduling,
  • MES dispatch and shop-floor execution,
  • autonomous schedule writes,
  • detailed costing,
  • procurement or material planning decisions owned by MRP/WMS,
  • direct PLC/control behavior owned by automation.

Future optimizers can plug into CRP through explicit proposal APIs; the optimizer must not become the module's core contract.


3. Domain scope

3.1 In scope

ConcernCRP stance
ResourceA constrained planning unit: vessel, line, room, work center, labor pool, or other schedulable capacity.
Work centerGrouping of resources that share a planning purpose or capacity class.
CalendarAvailability windows, downtime, blackout windows, and planning horizon.
Scheduled operationPlacement of an MRP operation on a resource/window.
Capacity bucketTime-window aggregation for load/capacity comparison.
Capacity loadPlanned and committed load per resource/window.
ConflictOverbooking, unavailable resource assignment, missed due date, or capacity exhaustion.
Scheduling proposalHuman-approved suggestion for moving/splitting/reassigning operations.

3.2 Out of scope

ConcernOwner
Production-order lifecycle, BOMs, material requirementsmrp
Live vessel/controller telemetry, alarms, adapter stateautomation
Stock availability and inventory constraintswms later; MRP assumptions during alpha
Brewery equipment-profile editingbrewery
Product/variant identitypim
PLC execution and safety interlocksautomation + brewery OpenPLC sister repo

4. Automation boundary

The automation module answers: "what is this vessel doing right now according to the adapter?"

CRP answers: "what is this resource scheduled for, when, and is that schedule feasible?"

CRP may consume:

  • automation.Vessel identity,
  • vessel display name/code/kind,
  • optional equipment-profile reference,
  • coarse current state for operator context.

CRP must not:

  • deep-import services/api/src/modules/automation/ internals,
  • own live telemetry or alarms,
  • issue PLC commands,
  • put scheduling fields onto automation routes,
  • turn (automation)/ pages into scheduling pages.

This preserves the boundary already documented in services/api/src/modules/automation/README.md.


5. Equipment contracts decision

CRP is the first concrete second consumer of brewery EquipmentProfile as planning-resource metadata. The design therefore treats an equipment contract extraction as part of the CRP planning surface:

  • Preferred shape: @umbraculum/equipment-contracts as a small MIT contracts package for shared equipment/resource references.
  • Alpha fallback: if implementation risk is too high, CRP can initially store a minimal externalResourceRef and link to brewery/automation by (ownerModule, refId) while documenting the extraction as the next migration.

The surface doc recommendation is to design as if the shared contract exists, but not to block documentation acceptance on physically creating the package.


6. Data model sketch

Illustrative only; exact Prisma names and fields land with implementation.

model CrpResource {
id String @id @default(uuid())
workspaceId String @map("workspace_id")
code String
displayName String @map("display_name")
resourceKind String @map("resource_kind")
workCenterId String? @map("work_center_id")
ownerModule String? @map("owner_module")
ownerRefId String? @map("owner_ref_id")
equipmentProfileId String? @map("equipment_profile_id")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
workCenter CrpWorkCenter? @relation(fields: [workCenterId], references: [id])
scheduledOperations CrpScheduledOperation[]
@@unique([workspaceId, code])
@@index([workspaceId, resourceKind])
@@map("resources")
@@schema("crp")
}

model CrpScheduledOperation {
id String @id @default(uuid())
workspaceId String @map("workspace_id")
resourceId String @map("resource_id")
mrpProductionOrderId String @map("mrp_production_order_id")
mrpOperationId String @map("mrp_operation_id")
status String
startsAt DateTime @map("starts_at")
endsAt DateTime @map("ends_at")
loadQuantity Decimal? @map("load_quantity")
loadUnit String? @map("load_unit")
resource CrpResource @relation(fields: [resourceId], references: [id])
@@index([workspaceId, startsAt])
@@index([resourceId, startsAt, endsAt])
@@map("scheduled_operations")
@@schema("crp")
}

CRP references MRP operations by contract-level IDs, not by direct Prisma relations into the MRP schema unless a later implementation explicitly chooses cross-schema relations.


7. Contracts package

Wave 1 package: packages/canonical/crp/contracts/ published in-repo as @umbraculum/crp-contracts.

Expected exports:

  • CONTRACT_VERSION and version-skew helpers.
  • ResourceSchema, ResourceRefSchema, ResourceKindSchema.
  • WorkCenterSchema.
  • ResourceCalendarSchema, AvailabilityWindowSchema.
  • ScheduledOperationSchema.
  • CapacityBucketSchema.
  • CapacityLoadSchema.
  • CapacityConflictSchema.
  • ScheduleProposalSchema.
  • Response envelopes for list/get/load/conflict routes.
  • AI tool input/output schemas.
  • Document-template input schemas for schedules and load exports.

Internal Umbraculum code uses Zod v4 schemas per RFC-0003. Runtime payloads must be parsed at package, HTTP, AI-tool, and rendering-template boundaries.


8. API surface

Wave 1 read-only API routes (also in OpenAPI tag crpAPI-OPENAPI.md):

RouteMethodPurpose
/crp/resourcesGETList resources for the active workspace.
/crp/resources/:resourceIdGETGet one resource and its planning metadata.
/crp/work-centersGETList work centers.
/crp/capacity-loadGETLoad/capacity summary by resource/window.
/crp/scheduled-operationsGETList scheduled operations by time/resource/order filters.
/crp/conflictsGETList detected conflicts.
/crp/schedule-proposalsPOSTFuture: produce a human-reviewable schedule proposal, not a direct write.
/crp/capacity-load/render-jobsPOSTWave 6 shipped: capacity-load XLSX export through @umbraculum/rendering.
/crp/schedule/render-jobsPOSTWave 6 shipped: schedule PDF export.
/crp/resources/calendar/render-jobsPOSTWave 6 shipped: resource calendar CSV export.
/crp/conflicts/render-jobsPOSTWave 6 shipped: conflict-report PDF export.

Every route must:

  • require an active session and active workspace,
  • scope all reads by workspaceId,
  • use Zod request/response schemas,
  • return contract-validated DTOs,
  • avoid raw SQL exposure to AI tools,
  • avoid deep imports from MRP or automation internals.

9. Web and native slices

Planned web route group: apps/web/app/[locale]/(crp)/.

Planned URL segments, subject to registerWebModule({ ownedUrlSegments }):

SegmentPurpose
capacityCapacity-load summary.
scheduleScheduled operations and conflict review.
resourcesResource/work-center list and detail.

The route group must follow the two beta disciplines from RFC-0002:

  • no apps/web/app/[locale]/(crp)/page.tsx,
  • no group-root dynamic segment such as apps/web/app/[locale]/(crp)/[id]/page.tsx.

Native slice: apps/native/src/modules/crp/. For alpha, native may be limited to shared contracts/navigation readiness unless user testing requires operator-facing schedule/resource views.


10. Brewery alpha projection

Brewery proves CRP without becoming CRP.

Brewery / canonical sourceCRP projection
BrewSession via MRPScheduled operation input.
BrewdaySettingsPlanned duration and operation sequence.
EquipmentProfileResource capacity assumptions.
automation.VesselVessel/resource identity and optional current-state context.
MRP production orderDemand/load source.

Wave 2 shipped the first read-time adapter: automation vessels project as CRP resources, brewery equipment profiles project as work centers, and timed brew-session steps project as scheduled operations/load where the source data is sufficient. Missing duration or missing unambiguous resource assignment is surfaced as a conservative read-only conflict rather than invented scheduling data.

Wave 3 shipped the first web proof of that adapter: /resources, /resources/<resourceId>, /capacity, and /schedule render the existing HTTP read APIs with contract-schema validation and explicit provenance labels such as "Projected from automation vessel" and "Projected from brewery." Wave 4 hardens that proof with deterministic fixture coverage for automation vessel resources, brewery equipment-profile work centers, capacity-load buckets, scheduled operations, and read-only conflicts. Wave 5 exposes the same evidence to the AI consultant through module-owned read-only tools. The UI and AI layer are read-only and do not parse projection IDs to infer source ownership.

The alpha implementation should continue to prefer projections and references over irreversible data migration. Existing brewery and automation routes remain stable.


11. MRP handoff

CRP consumes scheduleable operations from MRP:

  • production order ID,
  • operation ID/code,
  • required resource class,
  • planned duration,
  • earliest start / due date,
  • quantity/batch size,
  • priority if available.

CRP returns:

  • scheduled operations,
  • capacity loads,
  • conflicts,
  • proposals for moving/splitting/reassigning operations.

MRP remains the source for production-order lifecycle. CRP does not silently mutate MRP state.


12. AI tools

First AI tools, read-only subset shipped in Wave 5:

ToolScopePurpose
crp.listResourcesreadList resources/work centers and planning metadata.
crp.listWorkCentersreadList work centers and planning metadata.
crp.listScheduledOperationsreadList scheduled operations projected from existing planning sources.
crp.explainCapacityLoadreadSummarize load/capacity for a resource/window.
crp.listConflictsreadExplain conflicts and capacity exhaustion.
crp.explainResourceCalendarfuture readExplain availability windows and downtime.
crp.proposeScheduleAdjustmentproposeSuggest schedule/capacity adjustments; human approval required (canonical-ai-propose-write-surface.md).

The shipped Wave 5 tools are scope: "read" and return the existing route response envelopes. The future propose-write tool returns structured proposals. It must not directly mutate schedule state.


13. Rendering templates

Wave 6 shipped. Module-owned templates registered via registerModule({ documentTemplates }):

Template refKindPurpose
crp:capacity-load-xlsx@v1xlsxCapacity load export for planning/review.
crp:schedule-pdf@v1pdfHuman-readable schedule view.
crp:resource-calendar-csv@v1csvCalendar/availability export.
crp:conflict-report-pdf@v1pdfConflict summary for operator review.

CRP must not bundle its own PDF/XLSX/CSV libraries. Rendering is a horizontal platform concern per RFC-0007.


14. Tier limits and add-ons

Illustrative future tier-limit slice:

FieldMeaning
crpEnabledWhether the module surface is enabled for the workspace.
crpAiToolsEnabledWhether CRP tools are visible to the AI orchestrator.
maxPlanningResourcesResource count guardrail by tier.
maxScheduledOperationsHorizonDaysPlanning-horizon guardrail by tier.

Potential addon code: crp_module.

The exact values belong to the future implementation plan; this surface doc only records that limits attach through the module SDK rather than a brewery-private tier-limit path.


15. Phasing

PhaseOutput
AContracts package with schemas, tests, version helpers, and equipment-contract extraction decision.
BAPI skeleton and read-only routes registered via registerModule().
CResource projection from brewery equipment and automation vessels.
DCapacity-load and conflict calculations.
EWave 4 shipped: deterministic read-only web proof over resources, work centers, capacity, schedule, and conflicts. Proposal pages remain future work.
FWave 6 shipped: rendering templates and capacity export routes.
GWave 5 shipped: read-only AI tools and integration proof with MRP. Propose tools remain future work.
MatureHuman-approved writes, richer scheduler/optimizer plug-ins, WMS constraints, native operator flows.

16. Alpha acceptance proof

The alpha proof is complete when a user can:

  1. Start from MRP operations for one brewery production order.
  2. See resources derived from brewery equipment/automation vessel references.
  3. See a capacity-load view over a bounded planning window.
  4. Detect at least one conflict or at-capacity condition.
  5. Generate a schedule/load artifact through the rendering pipeline.
  6. Ask the AI consultant to explain the capacity picture and propose an adjustment.

The proof must make clear that this is an extensible canonical module surface, not a finished commercial CRP/APS product.

Wave 4 satisfies the deterministic read-only web visibility portions of this proof (items 1-4). Wave 5 satisfies the read-only AI explanation portion of item 6 for resources, capacity load, scheduled operations, and conflicts. Wave 6 satisfies item 5 for CRP schedule/load artifacts via the rendering pipeline. Alpha demo walkthrough ready (2026-05-26): browser export buttons on capacity (and stretch schedule/resources pages), runbook mrp-crp-alpha-demo-walkthrough.md (includes quick gates before Playwright — stack health, seed, stale .auth), CI coverage for all CRP render-job routes, Playwright export smoke — human gap-log sign-off still pending. Propose/write workflows, optimizer, native, and WMS portions remain open.


17. Cross-references