---
id: GridflockMappingReady
name: GridFlock Mapping Ready
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when the GridFlock pipeline completes (STL → slice → upload → mapping) or an existing mapping is found. The Order Service can now create print jobs for this SKU.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
- content: GridFlock
backgroundColor: purple
textColor: purple
---
Published when the GridFlock pipeline successfully completes the full generation cycle (STL → slice → upload → product mapping creation), or when an existing mapping is found for the requested SKU. The Order Service orchestration proceeds to create print jobs.
## Flow
`GridflockPipelineService.processOrderLineItem()` → EventEmitter `grid.mapping-ready` → `EventPublisherService` → BullMQ
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `grid.mapping-ready` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Grid Service |
| **Subscriber(s)** | Order Service |
## Example Payload
```json
{
"eventId": "d0e1f2a3-b4c5-6789-defa-012345678901",
"eventType": "grid.mapping-ready",
"source": "grid-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T11:00:00.000Z",
"orderId": "order-456",
"lineItemId": "li-789",
"sku": "GRID-2x3-MAG-NONE"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface GridflockMappingReadyEvent extends ServiceEvent {
eventType: 'grid.mapping-ready';
orderId: string;
lineItemId: string;
sku: string;
}
---
id: GridflockPipelineFailed
name: GridFlock Pipeline Failed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when the GridFlock pipeline fails at any step (STL generation, slicing, SimplyPrint upload, or mapping creation). Includes the failed step and error message.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
- content: GridFlock
backgroundColor: purple
textColor: purple
- content: Error
backgroundColor: red
textColor: red
---
Published when the GridFlock pipeline fails at any step. The Order Service marks the line item as FAILED and may trigger notifications.
## Flow
`GridflockPipelineService.processOrderLineItem()` → EventEmitter `grid.pipeline-failed` → `EventPublisherService` → BullMQ
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `grid.pipeline-failed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Grid Service |
| **Subscriber(s)** | Order Service |
## Pipeline Steps
The `failedStep` field indicates which step failed:
| Step | Description |
| --- | --- |
| `stl-generation` | OpenSCAD parametric STL generation failed |
| `slicing` | BambuStudio CLI slicing failed |
| `simplyprint-upload` | Uploading gcode to SimplyPrint failed |
| `mapping-creation` | Creating the product mapping in the database failed |
## Example Payload
```json
{
"eventId": "e1f2a3b4-c5d6-7890-efab-123456789012",
"eventType": "grid.pipeline-failed",
"source": "grid-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T11:05:00.000Z",
"orderId": "order-456",
"lineItemId": "li-789",
"sku": "GRID-2x3-MAG-NONE",
"errorMessage": "Slicer container returned HTTP 500: slicing timeout exceeded",
"failedStep": "slicing"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface GridflockPipelineFailedEvent extends ServiceEvent {
eventType: 'grid.pipeline-failed';
orderId: string;
lineItemId: string;
sku: string;
errorMessage: string;
failedStep:
| 'stl-generation'
| 'slicing'
| 'simplyprint-upload'
| 'mapping-creation';
}
---
id: IntegrationSendcloudChanged
name: Integration Sendcloud Changed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when the Sendcloud integration is connected or disconnected via the Settings UI. Consumer services reload their API client credentials from the database.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
- content: Infrastructure
backgroundColor: gray
textColor: gray
---
Published by the Shipping Service when a user connects or disconnects the Sendcloud integration via Settings > Integrations. The Order Service subscribes and re-initializes (or disables) its own `SendcloudApiClient` so that all services stay in sync without requiring a container restart.
## Flow
`SendcloudConnectionService.saveConnection()` / `.disconnect()` → `BullMQEventBus.publish()` → BullMQ `integration.sendcloud-changed`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `integration.sendcloud-changed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Shipping Service |
| **Subscriber(s)** | Order Service |
## Behavior
| Action | Publisher Side | Subscriber Side |
| --- | --- | --- |
| `connected` | API client re-initialized with new credentials | Loads credentials from DB, calls `initializeWithCredentials()` |
| `disconnected` | API client disabled | Calls `disable()` on local API client |
## Example Payload
```json
{
"eventId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"eventType": "integration.sendcloud-changed",
"source": "shipping-service",
"tenantId": "00000000-0000-0000-0000-000000000001",
"timestamp": "2026-02-20T17:25:00.000Z",
"action": "disconnected"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface IntegrationChangedEvent extends ServiceEvent {
eventType: 'integration.simplyprint-changed' | 'integration.sendcloud-changed';
action: 'connected' | 'disconnected';
}
---
id: IntegrationSimplyPrintChanged
name: Integration SimplyPrint Changed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when the SimplyPrint integration is connected or disconnected via the Settings UI. Consumer services reload their API client credentials from the database.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
- content: Infrastructure
backgroundColor: gray
textColor: gray
---
Published by the Print Service when a user connects or disconnects the SimplyPrint integration via Settings > Integrations. The Order Service subscribes and re-initializes (or disables) its own `SimplyPrintApiClient` so that all services stay in sync without requiring a container restart.
## Flow
`SimplyPrintConnectionService.saveConnection()` / `.disconnect()` → `BullMQEventBus.publish()` → BullMQ `integration.simplyprint-changed`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `integration.simplyprint-changed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Print Service |
| **Subscriber(s)** | Order Service |
## Behavior
| Action | Publisher Side | Subscriber Side |
| --- | --- | --- |
| `connected` | API client re-initialized with new credentials | Loads credentials from DB, calls `initializeWithCredentials()` |
| `disconnected` | API client disabled | Calls `disable()` on local API client |
## Example Payload
```json
{
"eventId": "f1a2b3c4-d5e6-7890-abcd-ef1234567890",
"eventType": "integration.simplyprint-changed",
"source": "print-service",
"tenantId": "00000000-0000-0000-0000-000000000001",
"timestamp": "2026-02-20T17:25:00.000Z",
"action": "connected"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface IntegrationChangedEvent extends ServiceEvent {
eventType: 'integration.simplyprint-changed' | 'integration.sendcloud-changed';
action: 'connected' | 'disconnected';
}
---
id: OrderCancelled
name: Order Cancelled
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when an order is cancelled. Triggers cancellation of print jobs in Print Service and shipments in Shipping Service.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when an order is cancelled. Both Print Service and Shipping Service subscribe to initiate their respective cancellation flows.
## Flow
`OrdersService.cancelOrder()` → EventEmitter `order.cancelled` → `EventPublisherService` → BullMQ
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `order.cancelled` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Order Service |
| **Subscriber(s)** | Print Service, Shipping Service |
## Example Payload
```json
{
"eventId": "c3d4e5f6-a7b8-9012-cdef-345678901234",
"eventType": "order.cancelled",
"source": "order-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T15:00:00.000Z",
"orderId": "order-456"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface OrderCancelledEvent extends ServiceEvent {
eventType: 'order.cancelled';
orderId: string;
}
---
id: OrderCreated
name: Order Created
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a new order is ingested from Shopify (including via backfill). Triggers print job creation in the Print Service.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when a new order is ingested from Shopify, either via webhook or backfill.
## Flow
`OrdersService.createFromShopify()` → EventEmitter `order.created` → `EventPublisherService` → BullMQ queue `order.created`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `order.created` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Order Service |
| **Subscriber(s)** | Print Service |
## Example Payload
```json
{
"eventId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"eventType": "order.created",
"source": "order-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T10:30:00.000Z",
"correlationId": "corr-123",
"orderId": "order-456",
"lineItems": [
{
"lineItemId": "li-789",
"productSku": "GRID-2x3-MAG-NONE",
"quantity": 2
}
]
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface OrderCreatedEvent extends ServiceEvent {
eventType: 'order.created';
orderId: string;
lineItems: Array<{
lineItemId: string;
productSku: string;
quantity: number;
}>;
}
---
id: OrderReadyForFulfillment
name: Order Ready for Fulfillment
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when all print jobs for an order are complete. Triggers shipment creation in the Shipping Service.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when the orchestration service determines all print jobs for an order have completed successfully. This triggers the Shipping Service to create a shipment.
## Flow
`OrchestrationService.markOrderReadyForFulfillment()` → EventEmitter `order.ready-for-fulfillment` → `EventPublisherService` → BullMQ
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `order.ready-for-fulfillment` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Order Service |
| **Subscriber(s)** | Shipping Service |
## Example Payload
```json
{
"eventId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"eventType": "order.ready-for-fulfillment",
"source": "order-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T14:00:00.000Z",
"orderId": "order-456"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface OrderReadyForFulfillmentEvent extends ServiceEvent {
eventType: 'order.ready-for-fulfillment';
orderId: string;
}
---
id: PrintJobCancelled
name: Print Job Cancelled
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a print job is cancelled (typically as part of an order cancellation flow). The Order Service updates the line item status.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when a print job is cancelled, typically triggered by an order cancellation cascade. The Order Service orchestration updates the line item status accordingly.
## Flow
`PrintJobsService.cancelJob()` → EventEmitter `printjob.cancelled` → `EventPublisherService` → BullMQ `print-job.cancelled`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `print-job.cancelled` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Print Service |
| **Subscriber(s)** | Order Service |
## Example Payload
```json
{
"eventId": "a7b8c9d0-e1f2-3456-abcd-789012345678",
"eventType": "print-job.cancelled",
"source": "print-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T17:00:00.000Z",
"printJobId": "pj-003",
"orderId": "order-456",
"lineItemId": "li-791"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface PrintJobCancelledEvent extends ServiceEvent {
eventType: 'print-job.cancelled';
printJobId: string;
orderId: string;
lineItemId: string | null;
}
---
id: PrintJobCompleted
name: Print Job Completed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a print job finishes successfully. The Order Service uses this to track completion progress and determine when all jobs are done.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when a print job completes successfully on SimplyPrint. The Order Service `EventSubscriberService` routes this event based on the print job's `purpose` field:
- **`ORDER` purpose** — Standard flow: updates line item progress, checks if all jobs complete → triggers `OrderReadyForFulfillment`
- **`STOCK` purpose** — Inventory flow: routes to `InventoryService.handleStockJobCompleted()` which increments the `StockBatch` progress counter. When the batch is fully complete, `currentStock` is atomically incremented.
## Flow
`PrintJobsService.updateJobStatus()` → EventEmitter `printjob.completed` → `EventPublisherService` → BullMQ `print-job.completed`
### Subscriber Routing (Order Service)
```
EventSubscriberService receives print-job.completed
├─ purpose === 'STOCK' → InventoryService.handleStockJobCompleted()
└─ purpose === 'ORDER' → EventEmitter emit('printjob.completed') → OrchestrationService
```
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `print-job.completed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Print Service |
| **Subscriber(s)** | Order Service (with purpose-based routing) |
## Example Payload (ORDER purpose)
```json
{
"eventId": "d4e5f6a7-b8c9-0123-defa-456789012345",
"eventType": "print-job.completed",
"source": "print-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T16:30:00.000Z",
"printJobId": "pj-001",
"orderId": "order-456",
"lineItemId": "li-789"
}
```
## Example Payload (STOCK purpose)
```json
{
"eventId": "e5f6a7b8-c9d0-1234-efab-567890123456",
"eventType": "print-job.completed",
"source": "print-service",
"tenantId": "tenant-abc",
"timestamp": "2026-03-08T03:12:00.000Z",
"printJobId": "pj-stock-001",
"orderId": "",
"lineItemId": null
}
```
## Related Events
- **ORDER purpose**: When all print jobs for an order complete → `OrderReadyForFulfillment` is published
- **ORDER purpose**: If some jobs fail → `PrintJobFailed` is published instead
- **STOCK purpose**: When all jobs in a `StockBatch` complete → `StockBatchCompleted` is published and stock is incremented
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface PrintJobCompletedEvent extends ServiceEvent {
eventType: 'print-job.completed';
printJobId: string;
orderId: string;
lineItemId: string | null;
}
---
id: PrintJobFailed
name: Print Job Failed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a print job fails on SimplyPrint. Includes the error message. The Order Service orchestration updates the line item status accordingly.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when a print job fails on SimplyPrint. The Order Service updates the line item status and may retry or mark the order as failed depending on the failure pattern.
If the failed job is later requeued (triggering a `print-job.status-changed` event with FAILED→QUEUED), the Order Service automatically reverts the order from FAILED/PARTIALLY_COMPLETED back to PROCESSING via the order revival mechanism.
## Flow
`PrintJobsService.updateJobStatus()` → EventEmitter `printjob.failed` → `EventPublisherService` → BullMQ `print-job.failed`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `print-job.failed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Print Service |
| **Subscriber(s)** | Order Service |
## Example Payload
```json
{
"eventId": "e5f6a7b8-c9d0-1234-efab-567890123456",
"eventType": "print-job.failed",
"source": "print-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T16:45:00.000Z",
"printJobId": "pj-002",
"orderId": "order-456",
"lineItemId": "li-790",
"errorMessage": "Printer head temperature exceeded safe limit"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface PrintJobFailedEvent extends ServiceEvent {
eventType: 'print-job.failed';
printJobId: string;
orderId: string;
lineItemId: string | null;
errorMessage: string;
}
---
id: PrintJobStatusChanged
name: Print Job Status Changed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a print job transitions between statuses (e.g., QUEUED → ASSIGNED → PRINTING). Used for real-time UI updates via Socket.IO.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published whenever a print job status changes on SimplyPrint. This event is used for real-time UI updates via Socket.IO, tracking status history, and **order revival** — when a terminal→active transition is detected (e.g., CANCELLED→QUEUED or FAILED→QUEUED), the OrchestrationService automatically reverts the order from FAILED/PARTIALLY_COMPLETED/CANCELLED back to PROCESSING.
## Flow
`PrintJobsService.updateJobStatus()` → EventEmitter `printjob.status-changed` → `EventPublisherService` → BullMQ `print-job.status-changed`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `print-job.status-changed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Print Service |
| **Subscriber(s)** | Order Service |
## Example Payload
```json
{
"eventId": "f6a7b8c9-d0e1-2345-fabc-678901234567",
"eventType": "print-job.status-changed",
"source": "print-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T16:00:00.000Z",
"printJobId": "pj-001",
"orderId": "order-456",
"lineItemId": "li-789",
"previousStatus": "QUEUED",
"newStatus": "PRINTING"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface PrintJobStatusChangedEvent extends ServiceEvent {
eventType: 'print-job.status-changed';
printJobId: string;
orderId: string;
lineItemId: string | null;
previousStatus: string;
newStatus: string;
}
---
id: ShipmentCreated
name: Shipment Created
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a shipment is created via Sendcloud. The Order Service uses this to create a Shopify fulfillment with tracking information.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when the Shipping Service successfully creates a shipment via the Sendcloud API. The Order Service's FulfillmentService uses this event to create a Shopify fulfillment with the tracking information.
## Flow
`SendcloudService.createShipment()` → EventEmitter `shipment.created` → `EventPublisherService` → BullMQ `shipment.created`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `shipment.created` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Shipping Service |
| **Subscriber(s)** | Order Service |
## Example Payload
```json
{
"eventId": "b8c9d0e1-f2a3-4567-bcde-890123456789",
"eventType": "shipment.created",
"source": "shipping-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T18:00:00.000Z",
"shipmentId": "ship-001",
"orderId": "order-456",
"trackingNumber": "3SPOST1234567890",
"trackingUrl": "https://tracking.sendcloud.sc/forward?carrier=postnl&code=3SPOST1234567890",
"carrier": "PostNL"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface ShipmentCreatedEvent extends ServiceEvent {
eventType: 'shipment.created';
shipmentId: string;
orderId: string;
trackingNumber: string | null;
trackingUrl: string | null;
carrier: string | null;
}
---
id: ShipmentStatusChanged
name: Shipment Status Changed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when a shipment status changes (e.g., label created → in transit → delivered). Originates from Sendcloud webhooks or reconciliation polling.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
---
Published when a shipment's status changes, typically triggered by Sendcloud webhooks or the periodic reconciliation polling service.
## Flow
`SendcloudWebhookService.processStatusChange()` or `SendcloudReconciliationService` → EventEmitter `sendcloud.shipment.status_changed` → `EventPublisherService` → BullMQ `shipment.status-changed`
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `shipment.status-changed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Shipping Service |
| **Subscriber(s)** | Order Service |
## Example Payload
```json
{
"eventId": "c9d0e1f2-a3b4-5678-cdef-901234567890",
"eventType": "shipment.status-changed",
"source": "shipping-service",
"tenantId": "tenant-abc",
"timestamp": "2026-02-18T20:00:00.000Z",
"shipmentId": "ship-001",
"orderId": "order-456",
"previousStatus": "LABEL_CREATED",
"newStatus": "IN_TRANSIT"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface ShipmentStatusChangedEvent extends ServiceEvent {
eventType: 'shipment.status-changed';
shipmentId: string;
orderId: string;
previousStatus: string;
newStatus: string;
}
---
id: StockBatchCompleted
name: Stock Batch Completed
version: 0.0.1
schemaPath: schema.ts
summary: |
Published when all print jobs in a stock batch have completed. Triggers the atomic stock increment and transaction recording.
badges:
- content: Not Yet Published
backgroundColor: red
textColor: red
- content: Inventory
backgroundColor: green
textColor: green
---
> **Status:** The `SERVICE_EVENTS.STOCK_BATCH_COMPLETED` constant and `StockBatchCompletedEvent` interface are defined in `event-types.ts`, but **no `eventBus.publish()` call** exists for this event. The stock batch completion logic in `InventoryService.handleStockJobCompleted()` updates the database directly without publishing a BullMQ event. This event is reserved for future use (e.g., dashboard notifications).
When the last print job in a `StockBatch` completes, `InventoryService` updates the database directly:
## Current Implementation (no BullMQ event)
`EventSubscriberService` receives `print-job.completed` with `purpose: STOCK` → `InventoryService.handleStockJobCompleted()` → checks `completedJobs >= totalJobs` → `InventoryRepository.recordBatchCompletion()` → atomically increments `ProductMapping.currentStock` and records a `PRODUCED` transaction
## Queue Configuration (reserved, not active)
| Property | Value |
| --- | --- |
| **Queue Name** | `inventory.stock-batch-completed` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | None (not yet published) |
| **Subscriber(s)** | None (future: dashboard notifications) |
## Side Effects
When a stock batch completes:
1. `StockBatch.status` → `COMPLETED`, `completedAt` is set
2. `ProductMapping.currentStock` is atomically incremented by 1
3. An `InventoryTransaction` of type `PRODUCED` with direction `IN` is recorded
4. All operations happen inside a single Prisma `$transaction` for consistency
## Example Payload
```json
{
"eventId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"eventType": "inventory.stock-batch-completed",
"source": "order-service",
"tenantId": "tenant-abc",
"timestamp": "2026-03-08T03:15:00.000Z",
"stockBatchId": "batch-456",
"productMappingId": "pm-789",
"totalJobs": 3
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface StockBatchCompletedEvent extends ServiceEvent {
eventType: 'inventory.stock-batch-completed';
stockBatchId: string;
productMappingId: string;
totalJobs: number;
}
---
id: StockReplenishmentScheduled
name: Stock Replenishment Scheduled
version: 0.0.2
schemaPath: schema.ts
summary: |
Published when the stock replenishment scheduler creates a print job for stock building. One event per print job in the batch. Consumed by the EventSubscriberService to queue the job in SimplyPrint.
badges:
- content: BullMQ
backgroundColor: blue
textColor: blue
- content: Inventory
backgroundColor: green
textColor: green
---
Published by the `StockReplenishmentService` when it creates print jobs for stock building. Each print job in a `StockBatch` triggers a separate event. The `EventSubscriberService` (order-service) subscribes to this event and queues each job in the SimplyPrint print queue via `SimplyPrintApiClient.addToQueue()`.
## Flow
`StockReplenishmentScheduler` (Cron) → `StockReplenishmentService.evaluateAndSchedule()` → `InventoryRepository.createStockBatch()` → BullMQ queue `inventory.stock-replenishment-scheduled` (per job) → `EventSubscriberService.queueStockJobToSimplyPrint()` → `SimplyPrintApiClient.addToQueue()` → SimplyPrint API
## Queue Configuration
| Property | Value |
| --- | --- |
| **Queue Name** | `inventory.stock-replenishment-scheduled` |
| **Channel** | BullMQ Event Bus |
| **Publisher** | Order Service (`StockReplenishmentService`) |
| **Subscriber(s)** | Order Service (`EventSubscriberService`) |
## Subscriber Behavior
When the `EventSubscriberService` receives this event, it:
1. Validates the `fileId` is present (skips if null)
2. Checks that `SimplyPrintApiClient` is enabled
3. Looks up the `PrintJob` by ID in the database
4. Skips if the job already has a `simplyPrintJobId` (idempotency)
5. Calls `SimplyPrintApiClient.addToQueue({ fileId, amount: 1 })`
6. Releases any stale `simplyPrintJobId` from old jobs (ID reuse handling)
7. Updates the `PrintJob` with `simplyPrintJobId` and `simplyPrintQueueItemId`
STOCK jobs are added to the SimplyPrint queue **without** priority reordering — they queue behind ORDER jobs naturally. See ADR-063 for how ORDER jobs are repositioned ahead of STOCK jobs.
## Trigger Conditions
The scheduler only creates stock batches when ALL conditions are met:
1. `STOCK_REPLENISHMENT_ENABLED` is `true`
2. Current hour is within `allowedHours` window
3. Current day is within `allowedDays`
4. Active order queue is below `orderQueueThreshold`
5. Active stock jobs are below `maxConcurrentStockJobs`
6. Product has `minimumStock > 0` and `currentStock < minimumStock`
## Example Payload
```json
{
"eventId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"eventType": "inventory.stock-replenishment-scheduled",
"source": "order-service",
"tenantId": "tenant-abc",
"timestamp": "2026-03-08T02:00:00.000Z",
"printJobId": "pj-stock-001",
"fileId": "sp-file-123",
"purpose": "STOCK",
"stockBatchId": "batch-456"
}
```
## Schema
## Raw Schema:schema.ts
interface ServiceEvent {
eventId: string;
eventType: string;
source: string;
tenantId: string;
timestamp: string;
correlationId?: string;
}
export interface StockReplenishmentScheduledEvent extends ServiceEvent {
eventType: 'inventory.stock-replenishment-scheduled';
printJobId: string;
fileId: string | null;
purpose: 'STOCK';
stockBatchId: string;
}
---
id: CancelJobsForOrder
name: Cancel Jobs for Order
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Order Service to Print Service to cancel all print jobs for a given order.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Cancels all active print jobs for a given order in the Print Service. Called by the Order Service during order cancellation.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/internal/print-jobs/order/:orderId/cancel` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Print Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface CancelJobsForOrderRequest {
orderId: string;
tenantId: string;
}
export interface CancelJobsForOrderResponse {
cancelledCount: number;
skippedCount: number;
}
---
id: CancelShipment
name: Cancel Shipment
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Order Service to Shipping Service to cancel a shipment for a cancelled order.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Cancels an active shipment in the Shipping Service. Called by the Order Service during order cancellation.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/internal/shipments/order/:orderId/cancel` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Shipping Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface CancelShipmentRequest {
orderId: string;
tenantId: string;
}
export interface CancelShipmentResponse {
shipmentId: string;
cancelled: boolean;
labelVoided: boolean;
}
---
id: CreatePrintJobs
name: Create Print Jobs
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Order Service to Print Service to create print jobs for an order's line items.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Creates print jobs in the Print Service for all line items of an order. Called by the Order Service orchestration after order creation.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/internal/print-jobs` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Print Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Request Body
```json
{
"orderId": "order-456",
"tenantId": "tenant-abc",
"lineItems": [
{
"lineItemId": "li-789",
"productSku": "GRID-2x3-MAG-NONE",
"quantity": 2,
"printFileUrl": "https://simplyprint.io/files/abc123.gcode"
}
]
}
```
## Response
```json
{
"printJobs": [
{
"id": "pj-001",
"lineItemId": "li-789",
"status": "QUEUED"
}
]
}
```
## Raw Schema:schema.ts
export interface CreatePrintJobsRequest {
orderId: string;
tenantId: string;
lineItems: Array<{
lineItemId: string;
productSku: string;
quantity: number;
printFileUrl: string;
}>;
}
export interface CreatePrintJobsResponse {
printJobs: Array<{
id: string;
lineItemId: string;
status: 'QUEUED';
}>;
}
---
id: CreateShipment
name: Create Shipment
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Order Service to Shipping Service to create a shipment for a fulfilled order.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Creates a shipment in the Shipping Service via Sendcloud. Called by the Order Service when an order reaches the `READY_FOR_FULFILLMENT` status.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/internal/shipments` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Shipping Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface CreateShipmentRequest {
orderId: string;
tenantId: string;
}
export interface CreateShipmentResponse {
shipmentId: string;
sendcloudParcelId: number;
trackingNumber: string | null;
trackingUrl: string | null;
carrier: string | null;
labelUrl: string | null;
}
---
id: GenerateForOrder
name: Generate for Order
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Order Service to Grid Service to trigger parametric STL generation for GridFlock-eligible line items.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
- content: GridFlock
backgroundColor: purple
textColor: purple
---
Triggers the GridFlock pipeline for order line items with GridFlock-eligible SKUs. The Grid Service processes these asynchronously and publishes `GridflockMappingReady` or `GridflockPipelineFailed` events when complete.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/internal/grid/generate-for-order` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Grid Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GenerateForOrderRequest {
orderId: string;
tenantId: string;
lineItems: Array<{
lineItemId: string;
sku: string;
quantity: number;
}>;
}
export interface GenerateForOrderResponse {
accepted: boolean;
pipelineId: string;
}
---
id: SliceSTL
name: Slice STL
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Grid Service to Slicer Container to convert an STL file to gcode using BambuStudio CLI.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
- content: GridFlock
backgroundColor: purple
textColor: purple
---
Sends an STL buffer to the Slicer Container for conversion to gcode using the BambuStudio CLI headless slicing engine. This is a CPU-intensive operation that may take 10-60 seconds.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/slice` |
| **Channel** | Internal HTTP |
| **Caller** | Grid Service |
| **Handler** | Slicer Container |
| **Auth** | None (internal network only) |
## Raw Schema:schema.ts
export interface SliceSTLRequest {
stlBuffer: Buffer;
printerModel: string;
filamentType: string;
layerHeight?: number;
infillPercentage?: number;
}
export interface SliceSTLResponse {
gcodeBuffer: Buffer;
estimatedPrintTimeSeconds: number;
estimatedFilamentGrams: number;
}
---
id: UpdateTracking
name: Update Tracking
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Shipping Service to Order Service to update tracking information for an order.
badges:
- content: PATCH
backgroundColor: yellow
textColor: yellow
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Updates tracking information (tracking number, URL, carrier) on an order. Called by the Shipping Service after shipment creation.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `PATCH` |
| **Route** | `/internal/orders/:id/tracking` |
| **Channel** | Internal HTTP |
| **Caller** | Shipping Service |
| **Handler** | Order Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface UpdateTrackingRequest {
trackingNumber: string | null;
trackingUrl: string | null;
carrier: string | null;
}
export interface UpdateTrackingResponse {
orderId: string;
updated: boolean;
}
---
id: UploadToSimplyPrint
name: Upload to SimplyPrint
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP command from Grid Service to Print Service to upload a sliced gcode file to SimplyPrint.
badges:
- content: POST
backgroundColor: green
textColor: green
- content: Internal HTTP
backgroundColor: orange
textColor: orange
- content: GridFlock
backgroundColor: purple
textColor: purple
---
Uploads a sliced gcode file to SimplyPrint via the Print Service's SimplyPrint integration. Called by the Grid Service after successful slicing.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `POST` |
| **Route** | `/internal/simplyprint/upload` |
| **Channel** | Internal HTTP |
| **Caller** | Grid Service |
| **Handler** | Print Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface UploadToSimplyPrintRequest {
tenantId: string;
orderId: string;
lineItemId: string;
sku: string;
fileName: string;
gcodeBuffer: Buffer;
}
export interface UploadToSimplyPrintResponse {
simplyPrintFileId: string;
uploadedAt: string;
}
---
id: GetJobsByOrderId
name: Get Jobs by Order ID
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Order Service to Print Service to retrieve all print jobs for a given order.
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Retrieves all print jobs associated with a given order from the Print Service.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/print-jobs/order/:orderId` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Print Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetJobsByOrderIdResponse {
printJobs: Array<{
id: string;
orderId: string;
lineItemId: string;
productSku: string;
status: 'QUEUED' | 'PRINTING' | 'COMPLETED' | 'FAILED' | 'CANCELLED';
simplyPrintJobId: string | null;
createdAt: string;
updatedAt: string;
}>;
}
---
id: GetJobStatusSummary
name: Get Job Status Summary
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Order Service to Print Service to get a summary of print job statuses for an order.
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Retrieves a summary of print job statuses for a given order — how many are queued, printing, completed, failed, etc.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/print-jobs/order/:orderId/status-summary` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Print Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetJobStatusSummaryResponse {
orderId: string;
total: number;
queued: number;
printing: number;
completed: number;
failed: number;
cancelled: number;
allCompleted: boolean;
}
---
id: GetMappingStatus
name: Get Mapping Status
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Order Service to Grid Service to check whether a product mapping exists for a given SKU.
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
- content: GridFlock
backgroundColor: purple
textColor: purple
---
Checks whether the Grid Service has an existing product mapping for a given SKU. Used by the Order Service orchestration to determine whether to trigger the GridFlock pipeline or use an existing mapping.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/grid/mapping-status/:sku` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Grid Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetMappingStatusResponse {
sku: string;
exists: boolean;
mapping: {
simplyPrintFileId: string;
createdAt: string;
} | null;
}
---
id: GetOrderByShopifyId
name: Get Order by Shopify ID
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Shipping Service to Order Service to look up an order by its Shopify order ID.
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Looks up an order in the Order Service using the Shopify order ID. Used by the Shipping Service when processing Sendcloud webhooks that reference Shopify order numbers.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/orders/shopify/:shopifyOrderId` |
| **Channel** | Internal HTTP |
| **Caller** | Shipping Service |
| **Handler** | Order Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetOrderByShopifyIdResponse {
id: string;
shopifyOrderId: string;
tenantId: string;
status: string;
createdAt: string;
updatedAt: string;
}
---
id: GetOrderDetails
name: Get Order Details
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Shipping Service to Order Service to retrieve full order details (shipping address, line items, etc.).
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Retrieves full order details from the Order Service, including shipping address and line items. Used by the Shipping Service to create Sendcloud shipments with correct address information.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/orders/:id` |
| **Channel** | Internal HTTP |
| **Caller** | Shipping Service |
| **Handler** | Order Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetOrderDetailsResponse {
id: string;
shopifyOrderId: string;
tenantId: string;
status: string;
shippingAddress: {
name: string;
company: string | null;
street: string;
houseNumber: string;
city: string;
postalCode: string;
countryCode: string;
phone: string | null;
email: string;
};
lineItems: Array<{
id: string;
productSku: string;
quantity: number;
title: string;
}>;
createdAt: string;
updatedAt: string;
}
---
id: GetOrderLineItems
name: Get Order Line Items
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Grid Service to Order Service to retrieve line items for an order (used to determine GridFlock-eligible SKUs).
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
- content: GridFlock
backgroundColor: purple
textColor: purple
---
Retrieves the line items for a given order from the Order Service. Used by the Grid Service to determine which line items have GridFlock-eligible SKUs and need parametric generation.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/orders/:id/line-items` |
| **Channel** | Internal HTTP |
| **Caller** | Grid Service |
| **Handler** | Order Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetOrderLineItemsResponse {
orderId: string;
lineItems: Array<{
id: string;
productSku: string;
quantity: number;
title: string;
isGridEligible: boolean;
gridConfig?: {
gridWidth: number;
gridDepth: number;
magnetType: 'none' | 'standard' | 'strong';
insertTypes: string[];
};
}>;
}
---
id: GetShipmentsByOrderId
name: Get Shipments by Order ID
version: 0.0.1
schemaPath: schema.ts
summary: |
Synchronous HTTP query from Order Service to Shipping Service to retrieve all shipments for a given order.
badges:
- content: GET
backgroundColor: blue
textColor: blue
- content: Internal HTTP
backgroundColor: orange
textColor: orange
---
Retrieves all shipments associated with a given order from the Shipping Service.
## Endpoint
| Property | Value |
| --- | --- |
| **Method** | `GET` |
| **Route** | `/internal/shipments/order/:orderId` |
| **Channel** | Internal HTTP |
| **Caller** | Order Service |
| **Handler** | Shipping Service |
| **Auth** | `X-Internal-Key: INTERNAL_API_KEY` |
## Raw Schema:schema.ts
export interface GetShipmentsByOrderIdResponse {
shipments: Array<{
id: string;
orderId: string;
sendcloudParcelId: number;
status: string;
trackingNumber: string | null;
trackingUrl: string | null;
carrier: string | null;
labelUrl: string | null;
createdAt: string;
updatedAt: string;
}>;
}
---
id: Gateway
name: API Gateway
version: 0.0.1
summary: |
Single entry point for all external traffic. Handles authentication, HTTP routing to downstream services, WebSocket proxy, and BullMQ monitoring via Bull Board.
badges:
- content: NestJS
backgroundColor: red
textColor: red
- content: Port 3000
backgroundColor: gray
textColor: gray
---
The API Gateway is the single entry point for all external traffic into Forma3D.Connect. It does not publish or consume any BullMQ events — it serves three roles:
1. **HTTP Proxy** — Routes REST requests to downstream services (Order, Print, Shipping, GridFlock)
2. **WebSocket Proxy** — Socket.IO proxy on namespace `/events` with Redis adapter for horizontal scaling
3. **Bull Board Dashboard** — Read-only monitoring of all 11 BullMQ queues at `/admin/queues`
## Technology
| Property | Value |
| --- | --- |
| **Framework** | NestJS |
| **Port** | 3000 |
| **Container** | `forma3d-gateway` |
| **Health** | `GET /health/live` |
## Architecture
See [C4 Component — Gateway](../../c4-model/3-component/) for internal structure.
---
id: GridflockService
name: Grid Service
version: 0.0.1
summary: |
Parametric Gridfinity grid generation service — STL generation via OpenSCAD, slicing via BambuStudio CLI, SimplyPrint upload, and product mapping creation.
sends:
- id: GridflockMappingReady
- id: GridflockPipelineFailed
- id: UploadToSimplyPrint
- id: SliceSTL
- id: GetOrderLineItems
receives:
- id: GenerateForOrder
- id: GetMappingStatus
flows:
- id: GridFlockPipeline
badges:
- content: NestJS
backgroundColor: red
textColor: red
- content: Port 3004
backgroundColor: gray
textColor: gray
- content: Feature-Flagged
backgroundColor: yellow
textColor: yellow
---
The Grid Service handles parametric Gridfinity grid generation. It orchestrates an end-to-end pipeline: STL generation (OpenSCAD) → slicing (BambuStudio CLI) → upload (SimplyPrint) → product mapping creation.
## Technology
| Property | Value |
| --- | --- |
| **Framework** | NestJS |
| **Port** | 3004 |
| **Container** | `forma3d-grid-service` |
| **Health** | `GET /health` |
| **Database** | PostgreSQL via Prisma |
| **Worker** | BullMQ local job queue for CPU-intensive STL generation |
## Responsibilities
- Parametric STL generation via OpenSCAD (baseplates and plate sets)
- Orchestration of the generation → slice → upload → map pipeline
- Communication with the Slicer Container for gcode generation
- Upload of sliced gcode to SimplyPrint via Print Service
- Product mapping creation for generated SKUs
## Architecture
See [C4 Component — Grid Service](../../c4-model/3-component/) for internal structure.
---
id: OrderService
name: Order Service
version: 0.0.1
summary: |
Core service managing the full order lifecycle — Shopify webhook ingestion, orchestration of downstream workflows, fulfillment tracking, and cancellation flows.
sends:
- id: OrderCreated
- id: OrderReadyForFulfillment
- id: OrderCancelled
- id: GenerateForOrder
- id: GetMappingStatus
- id: StockReplenishmentScheduled
receives:
- id: PrintJobCompleted
- id: PrintJobFailed
- id: PrintJobStatusChanged
- id: PrintJobCancelled
- id: ShipmentCreated
- id: ShipmentStatusChanged
- id: GridflockMappingReady
- id: GridflockPipelineFailed
- id: IntegrationSimplyPrintChanged
- id: IntegrationSendcloudChanged
- id: StockReplenishmentScheduled
- id: UpdateTracking
- id: GetOrderDetails
- id: GetOrderLineItems
- id: GetOrderByShopifyId
flows:
- id: OrderFulfillment
- id: OrderCancellation
- id: GridFlockPipeline
- id: ShippingTracking
- id: StockReplenishment
badges:
- content: NestJS
backgroundColor: red
textColor: red
- content: Port 3001
backgroundColor: gray
textColor: gray
- content: Core Service
backgroundColor: blue
textColor: blue
---
The Order Service is the central orchestrator of the Forma3D.Connect platform. It manages the full order lifecycle from Shopify webhook ingestion through fulfillment.
## Technology
| Property | Value |
| --- | --- |
| **Framework** | NestJS |
| **Port** | 3001 |
| **Container** | `forma3d-order-service` |
| **Health** | `GET /health` |
| **Database** | PostgreSQL via Prisma |
## Responsibilities
- Shopify webhook ingestion and order creation
- Product mapping resolution (standard + GridFlock)
- Orchestration: coordinates print jobs (via shared `PrintJobsBaseService` in-process), shipping, and GridFlock pipelines (via `GridServiceClient` HTTP)
- Fulfillment: creates Shopify fulfillments when shipments are confirmed (triggered by BullMQ `shipment.created` event)
- Cancellation: cancels print jobs in-process via SimplyPrint API, publishes `OrderCancelled` event for downstream services
- Inventory tracking: stock levels, adjustments, transaction ledger
- Stock replenishment: scheduled stock building with STOCK-purpose print jobs
- Stock-aware fulfillment: consumes from stock before creating print jobs
- Push notifications and Socket.IO real-time updates
- Integration client re-initialization on settings changes (SimplyPrint, Sendcloud)
## Architecture
See [C4 Component — Order Service](../../c4-model/3-component/) for internal structure.
---
id: PrintService
name: Print Service
version: 0.0.1
summary: |
Manages 3D print job lifecycle and SimplyPrint integration — creating jobs, tracking status via webhooks and polling, handling file uploads.
sends:
- id: PrintJobCompleted
- id: PrintJobFailed
- id: PrintJobStatusChanged
- id: PrintJobCancelled
- id: IntegrationSimplyPrintChanged
receives:
- id: OrderCreated
- id: OrderCancelled
- id: UploadToSimplyPrint
- id: GetJobsByOrderId
- id: GetJobStatusSummary
- id: CreatePrintJobs
- id: CancelJobsForOrder
flows:
- id: OrderFulfillment
- id: OrderCancellation
- id: GridFlockPipeline
badges:
- content: NestJS
backgroundColor: red
textColor: red
- content: Port 3002
backgroundColor: gray
textColor: gray
---
The Print Service manages the lifecycle of 3D print jobs. It integrates with SimplyPrint for printer management, job tracking via webhooks and status polling, and file uploads.
## Technology
| Property | Value |
| --- | --- |
| **Framework** | NestJS |
| **Port** | 3002 |
| **Container** | `forma3d-print-service` |
| **Health** | `GET /health` |
| **Database** | PostgreSQL via Prisma |
## Responsibilities
- Print job creation from order line items
- SimplyPrint API integration (upload files, create jobs, track status)
- **ORDER-over-STOCK queue priority** — ORDER-purpose jobs are automatically positioned before STOCK-purpose jobs in the SimplyPrint queue (ADR-063)
- Webhook handling for SimplyPrint status changes
- Periodic reconciliation polling to catch missed status updates
- Job cancellation and retry
- SimplyPrint integration credential management and live re-initialization
## Architecture
See [C4 Component — Print Service](../../c4-model/3-component/) for internal structure.
---
id: ShippingService
name: Shipping Service
version: 0.0.1
summary: |
Handles shipment creation, label generation, and tracking via Sendcloud. Activates after all print jobs for an order are complete.
sends:
- id: ShipmentCreated
- id: ShipmentStatusChanged
- id: UpdateTracking
- id: IntegrationSendcloudChanged
- id: GetOrderDetails
- id: GetOrderByShopifyId
receives:
- id: OrderReadyForFulfillment
- id: OrderCancelled
- id: CreateShipment
- id: CancelShipment
- id: GetShipmentsByOrderId
flows:
- id: OrderFulfillment
- id: OrderCancellation
- id: ShippingTracking
badges:
- content: NestJS
backgroundColor: red
textColor: red
- content: Port 3003
backgroundColor: gray
textColor: gray
---
The Shipping Service handles shipment creation, label generation, and tracking through the Sendcloud integration. It activates when the Order Service publishes the `order.ready-for-fulfillment` event, indicating all print jobs are complete.
## Technology
| Property | Value |
| --- | --- |
| **Framework** | NestJS |
| **Port** | 3003 |
| **Container** | `forma3d-shipping-service` |
| **Health** | `GET /health` |
| **Database** | PostgreSQL via Prisma |
## Responsibilities
- Shipment creation via Sendcloud API
- Label generation and carrier selection
- Webhook handling for Sendcloud status changes
- Periodic reconciliation polling to catch missed status updates
- Tracking information sync back to Order Service
- Sendcloud integration credential management and live re-initialization
## Architecture
See [C4 Component — Shipping Service](../../c4-model/3-component/) for internal structure.
---
id: SlicerContainer
name: Slicer Container
version: 0.0.1
summary: |
Headless BambuStudio CLI container for STL-to-gcode slicing. Called by the Grid Service via internal HTTP.
receives:
- id: SliceSTL
flows:
- id: GridFlockPipeline
badges:
- content: BambuStudio CLI
backgroundColor: orange
textColor: orange
- content: Port 3010
backgroundColor: gray
textColor: gray
---
The Slicer Container provides headless STL-to-gcode slicing using BambuStudio CLI. It is a standalone Docker container with no database or event bus connections — it exposes a simple HTTP API that the Grid Service calls synchronously.
## Technology
| Property | Value |
| --- | --- |
| **Runtime** | BambuStudio CLI (headless) |
| **Port** | 3010 |
| **Container** | `forma3d-slicer` |
| **Health** | `GET /health` |
## API
| Endpoint | Method | Description |
| --- | --- | --- |
| `POST /slice` | POST | Accepts STL buffer, returns sliced gcode buffer |
| `GET /health` | GET | Health check endpoint |
## Notes
- The Slicer Container does not publish or consume any BullMQ events
- It does not connect to the database
- The Grid Service handles retry logic if the slicer is temporarily unavailable
- CPU-intensive: slicing operations may take 10-60 seconds depending on model complexity
---
id: GridFlock
name: GridFlock
version: 0.0.1
summary: |
Parametric Gridfinity grid generation — CPU-intensive STL generation (OpenSCAD), slicing (BambuStudio CLI), and dynamic product mapping. Feature-flagged per tenant.
services:
- id: GridflockService
- id: SlicerContainer
flows:
- id: GridFlockPipeline
badges:
- content: Generic Domain
backgroundColor: purple
textColor: purple
- content: Feature-Flagged
backgroundColor: yellow
textColor: yellow
---
The GridFlock domain handles parametric Gridfinity grid generation. It provides an automated pipeline that generates STL files using OpenSCAD, slices them with BambuStudio CLI, uploads the gcode to SimplyPrint, and creates product mappings — all triggered by incoming orders with GridFlock-eligible SKUs.
## Subdomains
| Subdomain | Description |
| --- | --- |
| **STL Generation** | Parametric OpenSCAD-based generation of Gridfinity baseplates and plate sets |
| **Slicing** | Headless BambuStudio CLI slicing of STL to gcode |
| **Pipeline Orchestration** | End-to-end pipeline: generate → slice → upload → map |
| **Grid Configuration** | Preset management for baseplate parameters (dimensions, magnets, etc.) |
## Key Flows
- **GridFlock Pipeline** — See [C4_Seq_10_GridFlockPipeline.puml](../../sequences/)
## GridFlock Pipeline Flow
```mermaid
sequenceDiagram
participant OrderService as Order Service
participant GridService as Grid Service
participant Slicer as Slicer Container
participant PrintService as Print Service
participant BullMQ as BullMQ Event Bus
OrderService->>GridService: POST /internal/grid/generate-for-order
GridService->>GridService: Check existing mapping
alt Mapping exists
GridService->>BullMQ: publish grid.mapping-ready
BullMQ->>OrderService: consume grid.mapping-ready
else No mapping — full pipeline
GridService->>GridService: Generate STL (OpenSCAD)
GridService->>Slicer: POST /slice (STL buffer)
Slicer->>GridService: Sliced gcode buffer
GridService->>PrintService: POST /internal/simplyprint/upload (gcode)
PrintService->>GridService: SimplyPrint file ID
GridService->>GridService: Create product mapping
GridService->>BullMQ: publish grid.mapping-ready
BullMQ->>OrderService: consume grid.mapping-ready
end
OrderService->>PrintService: POST /internal/print-jobs (with mapping)
```
## Pipeline Error Flow
```mermaid
sequenceDiagram
participant GridService as Grid Service
participant Slicer as Slicer Container
participant BullMQ as BullMQ Event Bus
participant OrderService as Order Service
GridService->>GridService: Generate STL (OpenSCAD)
alt STL generation fails
GridService->>BullMQ: publish grid.pipeline-failed
(failedStep: stl-generation)
else Slicing fails
GridService->>Slicer: POST /slice
Slicer-->>GridService: HTTP 500
GridService->>BullMQ: publish grid.pipeline-failed
(failedStep: slicing)
else Upload fails
GridService->>BullMQ: publish grid.pipeline-failed
(failedStep: simplyprint-upload)
else Mapping creation fails
GridService->>BullMQ: publish grid.pipeline-failed
(failedStep: mapping-creation)
end
BullMQ->>OrderService: consume grid.pipeline-failed
OrderService->>OrderService: Mark line item FAILED
```
## Ubiquitous Language
| Term | Definition |
| --- | --- |
| **Gridfinity** | An open-source modular storage system based on a 42 mm grid unit. GridFlock generates parametric Gridfinity-compatible baseplates and plate sets. |
| **Grid Unit** | The standard Gridfinity cell size of 42 mm (`GRID_UNIT_MM`). All grid dimensions are multiples of this unit. |
| **Baseplate** | A single Gridfinity base grid, generated as an STL from dimensional parameters (width × depth in grid units). One of two GridFlock job types (`BASEPLATE`). |
| **Plate Set** | A multi-plate Gridfinity configuration that exceeds the printer's build area. The system automatically calculates the optimal tiling of plates. The second GridFlock job type (`PLATE_SET`). Parent jobs spawn child jobs for individual plates. |
| **GridFlock Job** | A unit of work for parametric grid generation. Has a `type` (BASEPLATE or PLATE_SET), JSON `parameters`, generated file metadata, and `progress` tracking. Plate set jobs have parent/child relationships. |
| **GridFlock Job Status** | Lifecycle state: `QUEUED` (awaiting processing), `PROCESSING` (actively generating/slicing), `COMPLETED` (pipeline finished), `FAILED` (error at any step), `EXPIRED` (cleanup after configurable hours). |
| **GridFlock Pipeline** | The end-to-end process: STL generation (OpenSCAD) → slicing (BambuStudio CLI) → upload to SimplyPrint → product mapping creation. Runs buffer-based with sequential plate processing to manage memory. |
| **Failed Step** | The specific pipeline stage where an error occurred: `stl-generation`, `slicing`, `simplyprint-upload`, or `mapping-creation`. Reported in the `grid.pipeline-failed` event. |
| **OpenSCAD** | Open-source script-based CAD engine used to parametrically generate Gridfinity STL geometry from grid dimensions, connector types, and magnet configurations. |
| **Slicer / Slicing** | The process of converting an STL 3D model into gcode machine instructions. Performed by a headless BambuStudio CLI running in a dedicated Docker container (`SlicerContainer`). |
| **Slicer Container** | A standalone HTTP service wrapping BambuStudio CLI. Accepts STL buffers via `POST /slice` and returns gcode buffers. Decoupled from the Grid Service for resource isolation. |
| **Connector Type** | The interlocking mechanism between Gridfinity baseplates: `intersection-puzzle` (IP), `edge-puzzle` (EP), or `none`. Determines the geometry at plate boundaries. |
| **GridFlock Preset** | A saved set of generation parameters (dimensions, connector type, magnet config, etc.). Can be `isPublic` (shared across tenants), `isSystem` (built-in defaults), or tenant-scoped. |
| **Magnet Parameters** | Configuration for optional magnet holes in the baseplate: presence, diameter, depth. Part of the generation parameters. |
| **Slicer Margin / Brim** | Parameters controlling the border area added during slicing for build-plate adhesion. Affects the printable area calculation for plate sets. |
| **Max Dimension** | The configurable maximum grid size (`grid.max_dimension_mm`). Orders exceeding this are rejected. A separate `MAX_SYNC_GRID_SIZE` threshold determines whether generation runs synchronously or is queued. |
| **Printer Profile** | The target printer model specification (e.g. "Bambu Lab A1") used by the slicer to select appropriate settings. Configured per tenant via `grid.print_settings`. |
| **Grid Pricing** | Per-tenant pricing model for custom grids: `grid.basePrice` (fixed fee), `grid.unitPrice` (per grid unit), `grid.unitSizeMm`, and `grid.currency`. Stored in SystemConfig. |
| **Feature Flag** | System configuration key `feature.grid.enabled` that controls whether GridFlock is active for a tenant. Exposed via the gateway's `TenantFeaturesService`. |
| **GRID-CUSTOM SKU** | The Shopify SKU prefix that identifies a line item as a GridFlock custom product. Triggers the GridFlock pipeline during order orchestration. |
---
id: Inventory
name: Inventory
version: 0.0.1
summary: |
Inventory tracking, stock replenishment, and hybrid fulfillment domain — enables pre-printing products to stock and consuming stock before print-to-order.
services:
- id: OrderService
flows:
- id: StockReplenishment
- id: OrderFulfillment
badges:
- content: Supporting Domain
backgroundColor: green
textColor: green
---
The Inventory domain adds stock management capabilities to the Forma3D.Connect platform, enabling a hybrid fulfillment model where products can be fulfilled from pre-built stock or printed on demand.
## Subdomains
| Subdomain | Description |
| --- | --- |
| **Inventory Tracking** | Tracks `currentStock` per product mapping, with configurable `minimumStock` thresholds |
| **Stock Replenishment** | Scheduled Cron job creates `StockBatch` records with `STOCK`-purpose print jobs when stock falls below minimum. Mutex prevents concurrent evaluations. Batches can be cancelled by operators. |
| **Stock-Aware Fulfillment** | Orchestration checks available stock before creating print jobs — consumes from shelf first. Orders fully fulfilled from stock skip printing and go directly to fulfillment. |
| **Transaction Ledger** | Immutable `InventoryTransaction` log records every stock change (PRODUCED, CONSUMED, ADJUSTMENT, SCRAPPED) |
## Key Flows
- **Scheduled Replenishment** — Cron evaluates products with `currentStock < minimumStock` and creates stock print batches
- **Stock Consumption** — When `order.created` fires, the orchestrator tries to consume from stock before creating print jobs. If all units are fulfilled from stock, the order skips printing and goes directly to fulfillment.
- **Batch Completion** — When all print jobs in a `StockBatch` complete, `currentStock` is atomically incremented
- **Batch Cancellation** — Operators can cancel active stock batches via the UI or API, which cancels pending print jobs and marks the batch as `CANCELLED`
## Data Model
```mermaid
erDiagram
ProductMapping ||--o{ StockBatch : "has"
ProductMapping ||--o{ InventoryTransaction : "tracks"
StockBatch ||--o{ PrintJob : "contains"
ProductMapping {
int currentStock "Units on shelf"
int minimumStock "Replenishment trigger"
int maximumStock "Optional cap"
int replenishmentPriority "Higher = first"
int replenishmentBatchSize "Jobs per cycle"
}
StockBatch {
string status "IN_PROGRESS | COMPLETED | FAILED | CANCELLED"
int totalJobs "PrintJobs in batch"
int completedJobs "Progress counter"
}
InventoryTransaction {
string transactionType "PRODUCED | CONSUMED | ADJUSTMENT_IN | ADJUSTMENT_OUT | SCRAPPED"
int quantity "Always positive"
string direction "IN | OUT"
string referenceType "STOCK_BATCH | ORDER | LINE_ITEM | MANUAL"
}
```
## API Endpoints
| Method | Endpoint | Permission | Description |
| --- | --- | --- | --- |
| `GET` | `/api/v1/inventory/stock` | `inventory.read` | List stock levels for all managed products |
| `PUT` | `/api/v1/inventory/stock/:id/config` | `inventory.write` | Update stock configuration (minimumStock, etc.) |
| `POST` | `/api/v1/inventory/stock/:id/adjust` | `inventory.write` | Manual stock adjustment (in or out) |
| `POST` | `/api/v1/inventory/stock/:id/scrap` | `inventory.write` | Record scrapped units |
| `GET` | `/api/v1/inventory/stock/:id/transactions` | `inventory.read` | Transaction history with pagination |
| `GET` | `/api/v1/inventory/replenishment/status` | `inventory.read` | Replenishment scheduler status |
| `GET` | `/api/v1/inventory/batches` | `inventory.read` | List active stock batches |
| `POST` | `/api/v1/inventory/batches/:id/cancel` | `inventory.write` | Cancel an active stock batch |
## Ubiquitous Language
| Term | Definition |
| --- | --- |
| **Current Stock** | The number of pre-printed units of a product currently on the shelf, tracked on the ProductMapping as `currentStock`. Atomically incremented/decremented by inventory transactions. |
| **Minimum Stock** | The `minimumStock` threshold on a ProductMapping. When `currentStock` drops below this value, the replenishment scheduler creates a stock batch to print more units. |
| **Maximum Stock** | An optional `maximumStock` cap on a ProductMapping. Limits how many units the replenishment system will produce. |
| **Replenishment Priority** | A numeric `replenishmentPriority` on ProductMapping. Higher values are evaluated first when the replenishment scheduler runs, ensuring critical products are restocked before others. |
| **Replenishment Batch Size** | The `replenishmentBatchSize` on ProductMapping, specifying how many print jobs to create per replenishment cycle for that product. |
| **Stock Batch** | A group of `STOCK`-purpose print jobs created by a single replenishment cycle. Tracks `totalJobs`, `completedJobs`, and a lifecycle status. When all jobs complete, `currentStock` is atomically incremented. |
| **Stock Batch Status** | Lifecycle state of a StockBatch: `IN_PROGRESS` (jobs printing), `COMPLETED` (all jobs done, stock updated), `FAILED` (jobs failed), `CANCELLED` (operator cancelled the batch). |
| **Inventory Transaction** | An immutable ledger entry recording a stock change. Each transaction has a `transactionType`, `quantity` (always positive), `direction` (IN or OUT), `referenceType`, and `referenceId`. |
| **Transaction Type** | The reason for a stock change: `PRODUCED` (print job completed → stock in), `CONSUMED` (stock allocated to an order → stock out), `ADJUSTMENT_IN` (manual increase), `ADJUSTMENT_OUT` (manual decrease), `SCRAPPED` (damaged/defective units removed). |
| **Stock Direction** | Whether a transaction adds to (`IN`) or removes from (`OUT`) the available stock. |
| **Reference Type** | Links an InventoryTransaction to its source: `STOCK_BATCH` (replenishment), `ORDER` (order consumption), `LINE_ITEM` (line-level consumption), `MANUAL` (operator adjustment or scrap). |
| **Stock-Aware Fulfillment** | The orchestration logic that checks available stock before creating print jobs. If sufficient stock exists, units are consumed from the shelf and the order skips printing entirely, going directly to fulfillment. |
| **Hybrid Fulfillment** | The business model where orders can be fulfilled either from pre-printed stock or via print-on-demand, depending on stock availability at the time of order creation. |
| **Replenishment Scheduler** | A cron-based process that periodically evaluates all managed products and creates stock batches for any whose `currentStock < minimumStock`. Protected by a mutex to prevent concurrent evaluations. |
| **Stock Management Feature Flag** | System configuration key `feature.stock-management.enabled` that controls whether inventory tracking and replenishment are active for a tenant. |
| **Manual Adjustment** | An operator-initiated stock change (increase or decrease) with a required reason. Recorded as an `ADJUSTMENT_IN` or `ADJUSTMENT_OUT` transaction. |
| **Scrap** | Recording that pre-printed units are damaged or defective and should be removed from stock. Creates a `SCRAPPED` transaction with direction `OUT`. |
---
id: Orders
name: Orders
version: 0.0.1
summary: |
The order lifecycle domain — from Shopify webhook ingestion through orchestration and fulfillment. The core business domain; everything starts here.
services:
- id: OrderService
flows:
- id: OrderFulfillment
- id: OrderCancellation
- id: StockReplenishment
badges:
- content: Core Domain
backgroundColor: blue
textColor: blue
---
The Orders domain encompasses the full order lifecycle within Forma3D.Connect. It handles ingestion of orders from Shopify, orchestration of downstream workflows (printing, shipping, GridFlock generation), fulfillment tracking, and cancellation flows.
## Subdomains
| Subdomain | Description |
| --- | --- |
| **Order Management** | CRUD operations, status tracking, and lifecycle management for orders and line items |
| **Shopify Integration** | Webhook ingestion, OAuth flow, order sync, and backfill capabilities |
| **Orchestration** | Coordinates downstream services — determines when print jobs are ready, when to trigger shipping |
| **Fulfillment** | Creates Shopify fulfillments when shipments are confirmed |
| **Cancellation** | Cascading cancellation across print jobs and shipments |
| **Product Catalog** | Product-to-print-file mappings and assembly part configurations |
| **Analytics** | Order metrics and status distribution dashboards |
| **Audit & Event Log** | Structured business event logging to PostgreSQL |
| **Notifications** | Web Push and in-app notifications for order lifecycle events |
| **Inventory & Stock** | Stock tracking, replenishment scheduling, and stock-aware hybrid fulfillment |
| **Retry Queue** | Exponential backoff retry mechanism for failed downstream operations |
## Key Flows
- **Shopify Webhook → Order Created** — See [C4_Seq_01_ShopifyWebhook.puml](../../sequences/)
- **Order → Print Jobs → Fulfillment** — See [C4_Seq_05_Fulfillment.puml](../../sequences/)
- **Order Cancellation** — See [C4_Seq_06_Cancellation.puml](../../sequences/)
- **Stock Replenishment** — See [C4_Seq_11_StockReplenishment.puml](../../sequences/)
- **Stock-Aware Fulfillment** — See [C4_Seq_12_StockAwareFulfillment.puml](../../sequences/)
## Standard Order Lifecycle
```mermaid
sequenceDiagram
participant Shopify
participant OrderService as Order Service
participant PrintService as Print Service
participant ShippingService as Shipping Service
participant BullMQ as BullMQ Event Bus
Shopify->>OrderService: Webhook: orders/create
OrderService->>BullMQ: publish order.created
BullMQ->>PrintService: consume order.created
PrintService->>PrintService: Create print jobs
Note over PrintService: Jobs progress through
QUEUED → PRINTING → COMPLETED
PrintService->>BullMQ: publish print-job.completed (per job)
BullMQ->>OrderService: consume print-job.completed
OrderService->>OrderService: Check all jobs complete
OrderService->>BullMQ: publish order.ready-for-fulfillment
BullMQ->>ShippingService: consume order.ready-for-fulfillment
ShippingService->>ShippingService: Create Sendcloud shipment
ShippingService->>BullMQ: publish shipment.created
BullMQ->>OrderService: consume shipment.created
OrderService->>Shopify: Create fulfillment with tracking
```
## Error / Retry Flow
```mermaid
sequenceDiagram
participant PrintService as Print Service
participant BullMQ as BullMQ Event Bus
participant OrderService as Order Service
PrintService->>BullMQ: publish print-job.failed
BullMQ->>OrderService: consume print-job.failed
alt All jobs failed
OrderService->>OrderService: Mark order FAILED
else Some jobs failed
OrderService->>OrderService: Mark order PARTIALLY_COMPLETED
end
Note over OrderService: Retry queue processes
failed operations with
exponential backoff
(1s, 2s, 4s up to 5 retries)
```
## Order Revival Flow
When a print job is requeued (terminal → active), the order automatically reverts to PROCESSING:
```mermaid
sequenceDiagram
participant Operator
participant PrintService as Print Service
participant BullMQ as BullMQ Event Bus
participant OrderService as Order Service
Note over OrderService: Order is FAILED or
PARTIALLY_COMPLETED
Operator->>PrintService: Requeue failed/cancelled job
PrintService->>BullMQ: publish print-job.status-changed
(CANCELLED → QUEUED)
BullMQ->>OrderService: consume print-job.status-changed
OrderService->>OrderService: Detect terminal → active transition
OrderService->>OrderService: Revert order to PROCESSING
OrderService->>OrderService: Recalculate part counts
OrderService->>OrderService: Log order.revived event
Note over OrderService: Order lifecycle continues
normally from PROCESSING
```
## Ubiquitous Language
| Term | Definition |
| --- | --- |
| **Order** | A tenant-scoped purchase record ingested from Shopify via webhook. Contains customer details, shipping address, pricing, and tracks fulfillment progress through `totalParts` / `completedParts` counters. |
| **Line Item** | A single product line within an Order, identified by `shopifyLineItemId` and `productSku`. Links to a ProductMapping for printing. Carries its own status and part counts independently of the parent Order. |
| **Product Mapping** | The link between a Shopify SKU/variant and the printable file(s) in SimplyPrint. Includes a `defaultPrintProfile` and optional assembly part definitions. Shared with the Printing and Inventory domains. |
| **Assembly Part** | One printable component of a multi-part product. Defined by `partName`, `partNumber`, `quantityPerProduct`, and a `simplyPrintFileId`. A single ProductMapping may have many AssemblyParts. |
| **Orchestration** | The coordination logic that monitors downstream progress (print jobs, GridFlock pipelines) and determines when an order is ready for shipping and Shopify fulfillment. Lives in the `OrchestrationService`. |
| **Fulfillment** | The act of creating a Shopify fulfillment record with tracking information once a shipment is confirmed. Distinct from the physical shipping step. |
| **Order Status** | The lifecycle state of an Order: `PENDING` (received, awaiting processing), `PROCESSING` (print jobs active), `PARTIALLY_COMPLETED` (some jobs done, some failed), `COMPLETED` (all parts fulfilled), `FAILED` (all jobs failed), `CANCELLED` (operator or Shopify cancellation). |
| **Line Item Status** | The lifecycle state of a Line Item: `PENDING`, `PRINTING`, `PARTIALLY_COMPLETED`, `COMPLETED`, `FAILED`. |
| **Order Revival** | Automatic reversion of a `FAILED` or `PARTIALLY_COMPLETED` order back to `PROCESSING` when a terminal print job is requeued by an operator. Part counts are recalculated. |
| **Shopify Webhook** | An HTTP callback from Shopify (e.g. `orders/create`, `orders/updated`) that triggers order ingestion. Deduplicated via `X-Shopify-Webhook-Id` stored in `ProcessedWebhook`. |
| **Processed Webhook** | An idempotency record keyed by `webhookId` and `webhookType` that prevents duplicate processing of the same Shopify event. |
| **Shopify Shop** | A tenant's Shopify store connection, holding the encrypted `accessToken`, granted `scopes`, `webhookSecret`, and install/uninstall timestamps. |
| **Event Log** | A structured business event record with `eventType`, `severity` (INFO, WARNING, ERROR), and optional links to an Order or PrintJob. Used for operational visibility, not security audit. |
| **Retry Queue** | An exponential-backoff retry mechanism for failed downstream operations. Each entry has a `RetryJobType` (FULFILLMENT, PRINT_JOB_CREATION, CANCELLATION, NOTIFICATION, SHIPMENT, GRIDFLOCK_PIPELINE) and a `RetryStatus` (PENDING, PROCESSING, COMPLETED, FAILED). |
| **Service Point Delivery** | An alternative delivery mode where the package is sent to a pickup location instead of the customer's home. Captured by `deliveryType` (`home` vs `service_point`) and Sendcloud service-point metadata on the Order. |
| **GridFlock Custom Product** | A line item whose SKU starts with `GRID-CUSTOM`, indicating it requires parametric Gridfinity grid generation before printing. Triggers the GridFlock pipeline during orchestration. |
| **Part Counts** | `totalParts` and `completedParts` tracked on both Order and LineItem. Orchestration uses these to determine when all printable components are done and the order is ready for fulfillment. |
---
id: Platform
name: Platform
version: 0.0.1
summary: |
Cross-cutting infrastructure: authentication, multi-tenancy, API routing, observability, database access, event bus. Not a business domain — shared capabilities used by all services.
services:
- id: Gateway
flows:
- id: IntegrationReinitialization
badges:
- content: Infrastructure
backgroundColor: gray
textColor: gray
---
The Platform domain provides cross-cutting infrastructure capabilities shared by all business domains. It is not a business domain itself — it provides the foundation on which business services operate.
## Subdomains
| Subdomain | Description |
| --- | --- |
| **Authentication & Authorization** | Session-based auth, RBAC, API key validation |
| **Multi-tenancy** | Tenant isolation and context propagation |
| **API Gateway** | HTTP routing, WebSocket proxy, rate limiting |
| **Observability** | Sentry integration, structured logging, health checks |
| **Configuration** | Environment-based configuration management |
| **Database Access** | Prisma ORM, PostgreSQL connection management |
| **Event Bus** | BullMQ event infrastructure, Bull Board monitoring |
| **Integration Management** | Live re-initialization of third-party API clients on settings changes |
## Ubiquitous Language
| Term | Definition |
| --- | --- |
| **Tenant** | An isolated organizational unit within Forma3D.Connect, identified by a `slug`. Each tenant has its own users, roles, integrations, feature flags, and configuration. The `isDefault` tenant serves as the system default. |
| **User** | An authenticated operator or administrator within a tenant. Assigned one or more Roles that grant Permissions. |
| **Role** | A named set of permissions assigned to users: `admin` (full access), `operator` (day-to-day operations), `viewer` (read-only), `legacy-admin` (API key backward compatibility). |
| **Permission** | A granular access right following the pattern `resource.action` (e.g. `orders.read`, `printJobs.write`, `inventory.write`, `admin.operations`). Assigned to Roles via RolePermission join records. |
| **Session-Based Auth** | The authentication mechanism using `express-session` backed by PostgreSQL. No JWTs — sessions are server-side with cookie-based identity. |
| **API Key** | A legacy authentication mechanism for machine-to-machine access, validated by the gateway. Used by the `legacy-admin` role. |
| **System Config** | Per-tenant key-value configuration stored as JSON in the `SystemConfig` entity. Controls feature flags, integration settings, pricing, and operational parameters (e.g. `feature.grid.enabled`, `stock.replenishment.enabled`). |
| **Feature Flag** | A SystemConfig entry that enables or disables functionality per tenant (e.g. `feature.grid.enabled`, `feature.stock-management.enabled`). Exposed via the gateway's `TenantFeaturesService`. |
| **Gateway** | The API gateway application that handles HTTP routing, WebSocket proxying, authentication, rate limiting, and Swagger aggregation. Proxies requests to downstream services: order-service, print-service, shipping-service, grid-service, and slicer. |
| **BullMQ Event Bus** | The cross-service asynchronous messaging infrastructure built on BullMQ (Redis-backed queues). Each event type corresponds to a named queue. The canonical event names are defined in `SERVICE_EVENTS`. |
| **EventEmitter2** | The in-process event system (NestJS) used for intra-service communication. Bridge services translate between local EventEmitter2 events and cross-service BullMQ events. |
| **Socket.IO** | The real-time WebSocket transport used to push events to the PWA frontend. Operates on the `/events` namespace with `WsApiKeyGuard` authentication. Emits events like `order:created`, `printjob:status-changed`, etc. |
| **Correlation ID** | A unique identifier propagated across service boundaries to trace a single business operation through logs and events. Used by `BusinessObservabilityService`. |
| **Audit Log** | A security-focused record of sensitive actions (e.g. `auth.login.success`, role changes). Captures `actorUserId`, `targetType`, `targetId`, and `metadata`. Distinct from the business EventLog. |
| **Health Check** | Aggregated downstream service health verification exposed by the gateway. Checks connectivity to all proxied services and infrastructure dependencies. |
| **Push Subscription** | A Web Push API subscription stored per user, enabling browser push notifications. Each subscription has toggles for order, print, shipment, and system notification categories. |
| **Integration Reinitialization** | The process of live-reloading third-party API clients (SimplyPrint, Sendcloud) when a tenant's integration settings change, without requiring a service restart. Triggered by `integration.simplyprint-changed` and `integration.sendcloud-changed` events. |
| **Retry Queue** | A platform-level exponential-backoff mechanism for failed operations. Supports job types across all domains (FULFILLMENT, PRINT_JOB_CREATION, CANCELLATION, NOTIFICATION, SHIPMENT, GRIDFLOCK_PIPELINE) with statuses PENDING, PROCESSING, COMPLETED, FAILED. |
| **Bull Board** | A monitoring UI for BullMQ queues, providing visibility into event bus queue depths, failed jobs, and processing rates. |
| **Sentry** | The observability platform integrated for error tracking, performance monitoring, and structured logging across all services. |
---
id: Printing
name: Printing
version: 0.0.1
summary: |
3D print job management and SimplyPrint integration — creating jobs, tracking status, handling webhooks, uploading files.
services:
- id: PrintService
flows:
- id: OrderFulfillment
- id: OrderCancellation
- id: GridFlockPipeline
badges:
- content: Supporting Domain
backgroundColor: green
textColor: green
---
The Printing domain manages the lifecycle of 3D print jobs within Forma3D.Connect. It integrates with SimplyPrint for printer management and job tracking.
## Subdomains
| Subdomain | Description |
| --- | --- |
| **Print Job Management** | Creation, status tracking, cancellation, and retry of print jobs |
| **SimplyPrint Integration** | API client, webhook handling, status polling, reconciliation, and file upload |
## Key Flows
- **Print Job Creation** — See [C4_Seq_03_PrintJobCreation.puml](../../sequences/)
- **Print Job Sync** — See [C4_Seq_04_PrintJobSync.puml](../../sequences/)
## Ubiquitous Language
| Term | Definition |
| --- | --- |
| **Print Job** | A unit of work representing a single 3D print. Linked to a LineItem and optionally an AssemblyPart (for ORDER purpose) or a StockBatch (for STOCK purpose). Identified externally by `simplyPrintJobId` and `simplyPrintQueueItemId`. |
| **Print Job Status** | Lifecycle state of a PrintJob: `QUEUED` (awaiting printer assignment), `ASSIGNED` (printer selected), `PRINTING` (actively printing), `COMPLETED` (finished successfully), `FAILED` (print error), `CANCELLED` (operator or cascade cancellation). |
| **Print Job Purpose** | Distinguishes why a job exists: `ORDER` (fulfilling a customer order) or `STOCK` (pre-printing for inventory replenishment). Drives orchestration and inventory transaction logic. |
| **Copy Number** | When a line item has `quantity > 1`, each PrintJob is assigned a `copyNumber` to track which copy of the product it represents. |
| **SimplyPrint** | Third-party 3D printer management platform. Forma3D.Connect uses its API for file uploads, job creation, printer monitoring, and status synchronization. |
| **SimplyPrint Queue Item ID** | The persistent `created_id` returned by SimplyPrint when a job is added to the queue. Used as the stable reference for job operations, distinct from the transient `simplyPrintJobId`. |
| **SimplyPrint Job Status** | The status reported by the SimplyPrint API: `queued`, `assigned`, `preparing`, `printing`, `completed`, `failed`, `cancelled`. Mapped to the internal `PrintJobStatus` enum. |
| **SimplyPrint Printer Status** | The state of a physical printer as reported by SimplyPrint: `offline`, `operational`, `printing`, `paused`, `error`. Cached locally in the `Printer` entity. |
| **Printer** | A cached representation of a physical 3D printer from SimplyPrint, tracking `simplyPrintId`, `isOnline`, `currentStatus`, and `currentJobId`. |
| **Assembly Part** | A single printable component within a multi-part product. Defined by `partName`, `partNumber`, `simplyPrintFileId`, `printProfile`, estimated print time and filament usage, and `quantityPerProduct`. |
| **Product Mapping** | The bridge between a Shopify SKU/variant and the printable file(s) in SimplyPrint. Contains a `defaultPrintProfile` and zero or more AssemblyParts. |
| **Print Profile** | A JSON configuration specifying slicer/printer settings (layer height, infill, supports, etc.) used when submitting a job to SimplyPrint. Stored on ProductMapping and AssemblyPart. |
| **Gcode** | Machine instructions generated by slicing an STL file. The format uploaded to SimplyPrint for 3D printing. |
| **STL** | Stereolithography file format representing 3D geometry. Source format for printable models before slicing. |
| **File Upload** | The process of sending gcode or STL files to SimplyPrint's file system, returning a `fileId` used to create print jobs. |
| **Status Polling** | Periodic synchronization of print job statuses from SimplyPrint, controlled by `SIMPLYPRINT_POLLING_ENABLED` and `SIMPLYPRINT_POLLING_INTERVAL_MS`. Supplements webhook-based updates. |
| **Reconciliation** | The process of comparing local PrintJob records against SimplyPrint's state to detect and correct drift caused by missed webhooks or polling gaps. |
| **Cancel Reason** | A numeric code from SimplyPrint indicating why a job was cancelled (e.g. print failed, nozzle clog, operator cancellation). |
| **Requeue** | An operator action that moves a `FAILED` or `CANCELLED` print job back to `QUEUED`, triggering an order revival in the Orders domain. |
---
id: Shipping
name: Shipping
version: 0.0.1
summary: |
Shipment creation, label generation, and tracking via Sendcloud. Activates after all print jobs complete.
services:
- id: ShippingService
flows:
- id: OrderFulfillment
- id: OrderCancellation
- id: ShippingTracking
badges:
- content: Supporting Domain
backgroundColor: green
textColor: green
---
The Shipping domain handles shipment creation, label generation, and tracking via the Sendcloud integration. It activates when the Order Service signals that all print jobs for an order are complete (`order.ready-for-fulfillment`).
## Subdomains
| Subdomain | Description |
| --- | --- |
| **Shipment Management** | Creation, status tracking, and label generation for shipments |
| **Sendcloud Integration** | API client, webhook handling, status reconciliation, and carrier management |
## Key Flows
- **Shipping Label Creation** — See [C4_Seq_08_ShippingLabel.puml](../../sequences/)
- **Fulfillment Flow** — See [C4_Seq_05_Fulfillment.puml](../../sequences/)
## Ubiquitous Language
| Term | Definition |
| --- | --- |
| **Shipment** | A one-to-one record linked to an Order, representing a parcel to be shipped. Contains carrier details, tracking info, label URL, weight, and dimensions. Identified externally by `sendcloudParcelId`. |
| **Shipment Status** | Lifecycle state of a Shipment: `PENDING` (awaiting label creation), `LABEL_CREATED` (shipping label generated), `ANNOUNCED` (parcel registered with carrier), `IN_TRANSIT` (picked up and moving), `DELIVERED` (successfully received), `FAILED` (delivery or creation error), `CANCELLED` (shipment voided). |
| **Sendcloud** | Third-party shipping aggregation platform. Forma3D.Connect uses its API for label generation, carrier selection, parcel tracking, and webhook-based status updates. |
| **Sendcloud Connection** | Per-tenant API credentials for Sendcloud, consisting of encrypted `publicKey` and `secretKey`, plus defaults for shipping method and sender address. |
| **Sendcloud Parcel ID** | The external identifier assigned by Sendcloud when a parcel (shipment) is created. Used for all subsequent API operations on that shipment. |
| **Shipping Label** | A carrier-specific document (PDF) generated by Sendcloud, containing barcode, routing info, and sender/recipient addresses. Retrieved via `labelUrl`. |
| **Shipping Method** | A carrier service option in Sendcloud (e.g. PostNL Standard, DPD Express), identified by `shippingMethodId` and `shippingMethodName`. A default is configured per tenant. |
| **Carrier** | The logistics company performing physical delivery (e.g. PostNL, DPD, DHL). Identified by `carrierName` on the Shipment. |
| **Tracking Number** | The carrier-assigned identifier for a parcel, enabling package tracking. Mirrored on both the Shipment and the parent Order. |
| **Tracking URL** | A carrier-provided URL where the recipient can track their shipment's delivery progress. Passed to Shopify during fulfillment creation. |
| **Sendcloud Webhook** | An HTTP callback from Sendcloud triggered by status changes (e.g. `parcel_status_changed`, `integration_connected`). Processed by the `SendcloudWebhookService`. |
| **Sendcloud Status Ranges** | Numeric ID ranges that Sendcloud uses to categorize parcel statuses: label created, announced, in transit, delivered, and exception ranges. Mapped to internal `ShipmentStatus` values. |
| **Sender Address** | The shipper's return address in Sendcloud, identified by `defaultSenderAddressId`. Used when creating parcels. |
| **Service Point** | A pickup location (e.g. parcel shop, locker) where the recipient collects their package instead of home delivery. Captured on the Order with `servicePointId`, `servicePointName`, `servicePointAddress`, and `servicePointPostNumber`. |
| **Weight & Dimensions** | Physical parcel attributes (`weight` in grams, `dimensions` as JSON with length/width/height in cm) required by Sendcloud for label generation and carrier rate calculation. |
---
id: BullMQEventBus
name: BullMQ Event Bus
version: 1.0.0
summary: |
Asynchronous inter-service event bus using BullMQ (Redis). Each event type maps to a dedicated BullMQ queue. Provides at-least-once delivery with configurable retries.
address: redis://redis:6379
protocols:
- redis
badges:
- content: Async
backgroundColor: blue
textColor: blue
- content: At-Least-Once
backgroundColor: green
textColor: green
---
The BullMQ Event Bus is the primary asynchronous communication channel between Forma3D.Connect microservices. Each event type corresponds to a dedicated BullMQ queue backed by Redis.
## Delivery Guarantees
| Property | Value |
| --- | --- |
| **Delivery** | At-least-once |
| **Ordering** | Per-queue FIFO (no cross-queue ordering) |
| **Retries** | 3 attempts with exponential backoff (1s, 2s, 4s) |
| **Concurrency** | 5 workers per queue per service instance |
| **Dead Letter** | Failed events retained (`removeOnFail: 5000`) |
| **Completed Cleanup** | `removeOnComplete: 1000` |
| **Idempotency** | Required for all handlers |
## Infrastructure
- **Technology**: BullMQ on Redis 7
- **Library**: `@forma3d/service-common` `BullMqEventBus`
- **Monitoring**: Bull Board dashboard at `/admin/queues` on the Gateway
## Event Types
All 14 cross-service events flow through this channel:
| Queue Name | Publisher | Subscriber(s) |
| --- | --- | --- |
| `order.created` | Order Service | Print Service |
| `order.ready-for-fulfillment` | Order Service | Shipping Service |
| `order.cancelled` | Order Service | Print Service, Shipping Service |
| `print-job.completed` | Print Service | Order Service |
| `print-job.failed` | Print Service | Order Service |
| `print-job.status-changed` | Print Service | Order Service |
| `print-job.cancelled` | Print Service | Order Service |
| `integration.simplyprint-changed` | Print Service | Order Service |
| `shipment.created` | Shipping Service | Order Service |
| `shipment.status-changed` | Shipping Service | Order Service |
| `integration.sendcloud-changed` | Shipping Service | Order Service |
| `grid.mapping-ready` | Grid Service | Order Service |
| `grid.pipeline-failed` | Grid Service | Order Service |
| `inventory.stock-replenishment-scheduled` | Order Service | Order Service (self-consume) |
---
id: InternalHTTP
name: Internal HTTP
version: 1.0.0
summary: |
Synchronous service-to-service HTTP communication protected by INTERNAL_API_KEY. Used for commands (POST/PATCH) and queries (GET) between microservices.
protocols:
- http
badges:
- content: Sync
backgroundColor: orange
textColor: orange
- content: Internal Only
backgroundColor: red
textColor: red
---
The Internal HTTP channel provides synchronous service-to-service communication for commands and queries. These endpoints are not exposed through the API Gateway — they are only accessible within the Docker network.
## Authentication
All internal HTTP calls are authenticated via the `x-internal-api-key` header, which must match the `INTERNAL_API_KEY` environment variable configured on each service.
## Commands (10)
| Command | Method | Route | Caller → Handler | Status |
| --- | --- | --- | --- | --- |
| CreatePrintJobs | POST | `/internal/print-jobs` | (no runtime caller) → Print | Endpoint exists, no caller |
| CancelJobsForOrder | POST | `/internal/print-jobs/order/:orderId/cancel` | (no runtime caller) → Print | Endpoint exists, no caller |
| UploadToSimplyPrint | POST | `/internal/simplyprint/upload` | Grid → Print | Active |
| CreateShipment | POST | `/internal/shipments` | (no runtime caller) → Shipping | Endpoint exists, no caller |
| CancelShipment | POST | `/internal/shipments/order/:orderId/cancel` | (no runtime caller) → Shipping | Endpoint exists, no caller |
| GenerateForOrder | POST | `/internal/grid/generate-for-order` | Order → Grid | Active |
| UpdateOrderStatus | POST | `/internal/orders/:id/status` | Grid, Shipping → Order | Active |
| UpdateTracking | PATCH | `/internal/orders/:id/tracking` | Shipping → Order | Active |
| SliceSTL | POST | `/slice` | Grid → Slicer | Active |
| CreateProductMapping | POST | `/internal/product-mappings` | Grid → Order | Active |
## Queries (8)
| Query | Method | Route | Caller → Handler | Status |
| --- | --- | --- | --- | --- |
| GetJobsByOrderId | GET | `/internal/print-jobs/order/:orderId` | (no runtime caller) → Print | Endpoint exists, no caller |
| GetJobStatusSummary | GET | `/internal/print-jobs/order/:orderId/status-summary` | (no runtime caller) → Print | Endpoint exists, no caller |
| GetShipmentsByOrderId | GET | `/internal/shipments/order/:orderId` | (no runtime caller) → Shipping | Endpoint exists, no caller |
| GetOrderDetails | GET | `/internal/orders/:id` | Shipping → Order | Active |
| GetOrderLineItems | GET | `/internal/orders/:id/line-items` | Grid → Order | Active |
| GetOrderByShopifyId | GET | `/internal/orders/shopify/:shopifyOrderId` | Shipping → Order | Active |
| GetMappingStatus | GET | `/internal/grid/mapping-status/:sku` | Order → Grid | Active |
| GetProductMappingBySku | GET | `/internal/product-mappings/sku/:sku` | Grid → Order | Active |
---
id: GridFlockPipeline
name: GridFlock Pipeline
version: 0.0.1
summary: |
Parametric Gridfinity grid generation pipeline — from order line items through STL generation, slicing, and upload to SimplyPrint.
badges:
- content: Feature-Flagged
backgroundColor: purple
textColor: purple
steps:
- id: order_service_trigger
title: Order Service
summary: Detects GridFlock-eligible line items and triggers generation
service:
id: OrderService
version: 0.0.1
next_step:
id: generate_for_order_cmd
label: Trigger GridFlock generation
- id: generate_for_order_cmd
title: Generate for Order
message:
id: GenerateForOrder
version: 0.0.1
next_step:
id: gridflock_service
label: Send to Grid Service
- id: gridflock_service
title: Grid Service
summary: Generates parametric Gridfinity STL files based on order configuration
service:
id: GridflockService
version: 0.0.1
next_steps:
- id: get_order_line_items_query
label: Fetch line item config
- id: slice_stl_cmd
label: STL ready for slicing
- id: pipeline_failed_event
label: Generation failed
- id: get_order_line_items_query
title: Get Order Line Items
message:
id: GetOrderLineItems
version: 0.0.1
next_step:
id: gridflock_service
label: Return line item data
- id: slice_stl_cmd
title: Slice STL
message:
id: SliceSTL
version: 0.0.1
next_step:
id: slicer_container
label: Send to Slicer
- id: slicer_container
title: Slicer Container
summary: Headless BambuStudio CLI converts STL to printer-ready gcode
service:
id: SlicerContainer
version: 0.0.1
next_step:
id: upload_to_simplyprint_cmd
label: Gcode ready
- id: upload_to_simplyprint_cmd
title: Upload to SimplyPrint
message:
id: UploadToSimplyPrint
version: 0.0.1
next_step:
id: print_service_upload
label: Send to Print Service
- id: print_service_upload
title: Print Service
summary: Receives the sliced gcode and creates a print job in SimplyPrint
service:
id: PrintService
version: 0.0.1
next_step:
id: mapping_ready_event
label: Upload successful
- id: mapping_ready_event
title: GridFlock Mapping Ready
message:
id: GridflockMappingReady
version: 0.0.1
next_step:
id: order_service_confirm
label: Notify Order Service
- id: pipeline_failed_event
title: GridFlock Pipeline Failed
message:
id: GridflockPipelineFailed
version: 0.0.1
next_step:
id: order_service_confirm
label: Notify Order Service
- id: order_service_confirm
title: Order Service
summary: Records pipeline result and continues order orchestration
service:
id: OrderService
version: 0.0.1
---
## Overview
The GridFlock Pipeline is a feature-flagged flow that generates parametric Gridfinity grid inserts for orders that include customizable 3D-printed organizer parts.
### Pipeline stages
1. **Trigger** — Order Service detects GridFlock-eligible line items during order orchestration
2. **Configuration fetch** — Grid Service queries Order Service for line item configuration (grid dimensions, insert types)
3. **STL generation** — Parametric STL files are generated based on the configuration
4. **Slicing** — STL files are sent to the Slicer Container (headless BambuStudio CLI) to produce gcode
5. **Upload** — Sliced gcode is uploaded to SimplyPrint via the Print Service
6. **Confirmation** — `GridflockMappingReady` event notifies Order Service that print jobs are queued
### Failure handling
- If any stage fails, `GridflockPipelineFailed` is emitted
- Order Service records the failure and may retry depending on the error type
- STL generation and slicing are stateless operations and can be safely retried
### Feature flag
This flow is gated behind the `GRIDFLOCK_ENABLED` feature flag. When disabled, orders with GridFlock-eligible items are processed without grid generation.
---
id: IntegrationReinitialization
name: Integration Re-initialization
version: 0.0.1
summary: |
Live re-initialization flow for third-party integration clients (SimplyPrint, Sendcloud) when settings are updated via the UI, without requiring service restarts.
badges:
- content: Infrastructure
backgroundColor: gray
textColor: gray
steps:
- id: settings_ui
title: Settings UI
summary: User connects or disconnects an integration in Settings > Integrations
externalSystem:
name: Web Application
summary: Forma3D.Connect frontend
- id: owning_service_saves
title: Owning Service
summary: The service that owns the integration saves credentials to the database, then immediately re-initializes its own API client and publishes a change event
service:
id: PrintService
version: 0.0.1
next_steps:
- id: integration_changed_event
label: Publish integration changed event
- id: local_reinit
label: Local client re-initialized
- id: local_reinit
title: Local Re-initialization
summary: The owning service calls initializeWithCredentials() or disable() on its local API client — no restart needed
- id: integration_changed_event
title: Integration Changed Event
summary: Published to BullMQ so other services can react
message:
id: IntegrationSimplyPrintChanged
version: 0.0.1
next_step:
id: subscriber_reinit
label: Notify subscriber services
- id: subscriber_reinit
title: Subscriber Service
summary: The Order Service receives the event and re-initializes or disables its own copy of the API client by loading credentials from the database
service:
id: OrderService
version: 0.0.1
---
## Overview
When a user changes an integration's credentials in the Settings UI, all services that use that integration must update their API client immediately — without a container restart.
### Before this flow existed
API clients were only initialized at container startup via `*StartupService` classes. If credentials were changed at runtime, the services would continue using stale (or missing) credentials until the next restart. This caused issues like print jobs being created locally but never submitted to SimplyPrint.
### How it works now
1. **Settings update** — User connects or disconnects SimplyPrint / Sendcloud in the UI
2. **Owning service** — The `*ConnectionService` in the owning service (Print Service for SimplyPrint, Shipping Service for Sendcloud) saves/deletes credentials and immediately re-initializes its local API client
3. **Cross-service notification** — A BullMQ event (`integration.simplyprint-changed` or `integration.sendcloud-changed`) is published with an `action` field (`connected` | `disconnected`)
4. **Subscriber re-initialization** — The Order Service's `EventSubscriberService` receives the event and calls the appropriate `*InitializerService` to reload credentials from the database and re-initialize the client
### Affected integrations
| Integration | Owning Service | Event | Subscribers |
| --- | --- | --- | --- |
| SimplyPrint | Print Service | `integration.simplyprint-changed` | Order Service |
| Sendcloud | Shipping Service | `integration.sendcloud-changed` | Order Service |
### Key classes
| Class | Service | Role |
| --- | --- | --- |
| `SimplyPrintConnectionService` | Print Service | Saves credentials, publishes event |
| `SimplyPrintInitializerService` | Print Service / Order Service | Loads credentials from DB, initializes API client |
| `SendcloudConnectionService` | Shipping Service | Saves credentials, publishes event |
| `SendcloudInitializerService` | Shipping Service / Order Service | Loads credentials from DB, initializes API client |
| `EventSubscriberService` | Order Service | Listens for integration change events |
---
id: OrderCancellation
name: Order Cancellation
version: 0.0.1
summary: |
Cascading order cancellation flow — propagates cancellation from Order Service to Print Service and Shipping Service, rolling back all downstream work.
badges:
- content: Core Flow
backgroundColor: red
textColor: red
steps:
- id: cancellation_trigger
title: Cancellation Requested
summary: Admin or system triggers order cancellation
actor:
name: Admin
next_step:
id: order_service_cancel
label: Request cancellation
- id: order_service_cancel
title: Order Service
summary: Validates cancellation eligibility, cancels local print jobs via SimplyPrint API, and publishes OrderCancelled event
service:
id: OrderService
version: 0.0.1
next_steps:
- id: order_cancelled_event
label: Emit OrderCancelled via BullMQ
- id: local_print_cancel
label: Cancel print jobs locally
- id: local_print_cancel
title: Local Print Job Cancellation
summary: CancellationService cancels QUEUED/ASSIGNED print jobs directly via SimplyPrint API and updates local database. PRINTING jobs are flagged for operator review.
service:
id: OrderService
version: 0.0.1
- id: order_cancelled_event
title: Order Cancelled
message:
id: OrderCancelled
version: 0.0.1
next_steps:
- id: print_service_cancel
label: Notify Print Service
- id: shipping_service_cancel
label: Notify Shipping Service
- id: print_service_cancel
title: Print Service
summary: Receives order.cancelled event via BullMQ and handles any Print Service-side cleanup
service:
id: PrintService
version: 0.0.1
next_step:
id: print_job_cancelled_event
label: Jobs cancelled
- id: print_job_cancelled_event
title: Print Job Cancelled
message:
id: PrintJobCancelled
version: 0.0.1
next_step:
id: order_service_confirm
label: Confirm cancellation to Order Service
- id: shipping_service_cancel
title: Shipping Service
summary: Receives order.cancelled event via BullMQ and cancels shipment / voids label if not yet shipped
service:
id: ShippingService
version: 0.0.1
- id: order_service_confirm
title: Order Service
summary: Updates order status to fully cancelled after all downstream confirmations
service:
id: OrderService
version: 0.0.1
---
## Overview
The Order Cancellation flow handles the cascading rollback of an order across all downstream services. Cancellation can be triggered by an admin or by the system (e.g., payment failure detected from Shopify).
### Cancellation rules
- Orders can only be cancelled if they are **not yet fulfilled**
- If print jobs are already completed, cancellation still proceeds (physical items are scrapped)
- If a shipment label has already been generated, the label is voided via Sendcloud
- If the shipment is already in transit, cancellation is rejected
### Cascading behavior
1. Order Service's `CancellationService` cancels QUEUED/ASSIGNED print jobs locally via the SimplyPrint API (shared `PrintJobsBaseService`). PRINTING jobs are flagged for operator review.
2. Order Service emits `OrderCancelled` event via BullMQ
3. Print Service and Shipping Service subscribe to `order.cancelled` and handle their respective cleanup
4. Print Service emits `PrintJobCancelled` events for cancelled jobs
5. Shipping Service voids the Sendcloud label if applicable
6. Order Service updates final status after downstream confirmations
> **Note:** Cancellation uses BullMQ events for cross-service coordination. The `CancelJobsForOrder` and `CancelShipment` internal HTTP endpoints exist on Print and Shipping services but are not called by Order Service in the current implementation.
### Idempotency
All cancellation operations are idempotent — calling cancel on an already-cancelled resource is a no-op.
---
id: OrderFulfillment
name: Order Fulfillment
version: 0.0.1
summary: |
End-to-end order fulfillment flow — from Shopify webhook ingestion through print job creation, shipping, and final fulfillment back to Shopify.
badges:
- content: Core Flow
backgroundColor: blue
textColor: blue
steps:
- id: shopify_webhook
title: Shopify Webhook
summary: Customer places an order on the Shopify storefront
externalSystem:
name: Shopify
summary: E-commerce platform
url: https://shopify.dev/docs/api/webhooks
next_step:
id: order_service_ingestion
label: Webhook received
- id: order_service_ingestion
title: Order Service
summary: Ingests webhook payload, persists order, and begins orchestration
service:
id: OrderService
version: 0.0.1
next_steps:
- id: order_created_event
label: Emit OrderCreated
- id: stock_consumption
label: Try stock consumption
- id: create_print_jobs_cmd
label: Create print jobs (remaining)
- id: stock_consumption
title: Stock Consumption
summary: |
OrchestrationService checks if the product has available stock (currentStock > 0).
Consumes from stock first — fully, partially, or not at all — before creating print jobs.
service:
id: OrderService
version: 0.0.1
next_steps:
- id: order_service_orchestration
label: Fully from stock (skip printing)
- id: create_print_jobs_cmd
label: Partial or no stock
- id: order_created_event
title: Order Created
message:
id: OrderCreated
version: 0.0.1
next_step:
id: print_service_receives
label: Notify downstream services
- id: create_print_jobs_cmd
title: Create Print Jobs
message:
id: CreatePrintJobs
version: 0.0.1
next_step:
id: print_service_receives
label: Send to Print Service
- id: print_service_receives
title: Print Service
summary: Creates ORDER-purpose print jobs in SimplyPrint, prioritizes them ahead of any STOCK jobs in the queue (ADR-063), and monitors progress
service:
id: PrintService
version: 0.0.1
next_steps:
- id: simplyprint_integration
label: Submit to SimplyPrint
- id: print_job_completed_event
label: All jobs completed
- id: print_job_failed_event
label: Job failed
- id: simplyprint_integration
title: SimplyPrint
summary: Cloud-based 3D printer management platform
externalSystem:
name: SimplyPrint
summary: 3D printer farm management
url: https://simplyprint.io
next_step:
id: print_service_receives
label: Status webhook callback
- id: print_job_completed_event
title: Print Job Completed
message:
id: PrintJobCompleted
version: 0.0.1
next_step:
id: order_service_orchestration
label: Notify Order Service
- id: print_job_failed_event
title: Print Job Failed
message:
id: PrintJobFailed
version: 0.0.1
next_step:
id: order_service_orchestration
label: Notify Order Service
- id: order_service_orchestration
title: Order Service
summary: Evaluates whether all print jobs are done and the order is ready for shipping
service:
id: OrderService
version: 0.0.1
next_steps:
- id: order_ready_event
label: All items printed
- id: create_shipment_cmd
label: Create shipment
- id: order_ready_event
title: Order Ready for Fulfillment
message:
id: OrderReadyForFulfillment
version: 0.0.1
next_step:
id: create_shipment_cmd
label: Proceed to shipping
- id: create_shipment_cmd
title: Create Shipment
message:
id: CreateShipment
version: 0.0.1
next_step:
id: shipping_service
label: Send to Shipping Service
- id: shipping_service
title: Shipping Service
summary: Creates shipment and generates label via Sendcloud
service:
id: ShippingService
version: 0.0.1
next_steps:
- id: sendcloud_integration
label: Request label from Sendcloud
- id: shipment_created_event
label: Shipment created
- id: sendcloud_integration
title: Sendcloud
summary: Shipping label and tracking provider
externalSystem:
name: Sendcloud
summary: Shipping automation platform
url: https://www.sendcloud.com
next_step:
id: shipping_service
label: Label generated
- id: shipment_created_event
title: Shipment Created
message:
id: ShipmentCreated
version: 0.0.1
next_step:
id: order_service_fulfillment
label: Notify Order Service
- id: order_service_fulfillment
title: Order Service
summary: Creates fulfillment in Shopify to close the order
service:
id: OrderService
version: 0.0.1
next_step:
id: shopify_fulfillment
label: Create Shopify fulfillment
- id: shopify_fulfillment
title: Shopify Fulfillment
summary: Order is marked as fulfilled in Shopify with tracking info
externalSystem:
name: Shopify
summary: E-commerce platform
url: https://shopify.dev/docs/api/admin-rest/2024-01/resources/fulfillment
---
## Overview
The Order Fulfillment flow is the core business process of Forma3D.Connect. It traces the full lifecycle of a customer order from initial placement on Shopify through to final fulfillment.
### Key stages
1. **Ingestion** — Shopify sends an `orders/create` webhook to the Order Service
2. **Stock consumption** — Orchestration checks if items can be fulfilled from pre-built stock (hybrid fulfillment)
3. **Print orchestration** — For remaining units not covered by stock, creates print jobs and dispatches to Print Service
4. **Readiness check** — When all print jobs complete (or all items fulfilled from stock), the Order Service marks the order as ready for fulfillment
5. **Shipping** — Shipping Service generates a label via Sendcloud and creates the shipment
6. **Fulfillment** — Order Service creates a fulfillment record in Shopify with tracking information
### Hybrid fulfillment scenarios
| Scenario | Stock consumed | Print jobs created |
| --- | --- | --- |
| **Full stock** | All units from shelf | None — line item marked complete immediately |
| **Partial stock** | Some units from shelf | Remaining units printed on demand |
| **No stock** | None (stock = 0 or not managed) | All units printed on demand (original behavior) |
### Communication patterns
- **Asynchronous events** (BullMQ): `OrderCreated`, `PrintJobCompleted`, `PrintJobFailed`, `OrderReadyForFulfillment`, `ShipmentCreated`
- **Synchronous commands** (Internal HTTP): `CreatePrintJobs`, `CreateShipment`
- **Internal** (Prisma transactions): Atomic stock consumption with `CONSUMED` transaction recording
### Error handling
- Print job failures trigger the retry queue with exponential backoff
- After max retries, the order is flagged for manual intervention
- Stock consumption uses optimistic locking — if a race condition occurs, the order falls back to print-to-order
- Partial fulfillment is not supported — all items must be printed/fulfilled before shipping
---
id: ShippingTracking
name: Shipping & Tracking
version: 0.0.1
summary: |
Shipment tracking flow — monitors shipping status changes from Sendcloud and propagates tracking updates back to the order.
badges:
- content: Supporting Flow
backgroundColor: green
textColor: green
steps:
- id: sendcloud_webhook
title: Sendcloud
summary: Sendcloud sends tracking status update webhooks
externalSystem:
name: Sendcloud
summary: Shipping automation platform
url: https://www.sendcloud.com
next_step:
id: shipping_service
label: Webhook received
- id: shipping_service
title: Shipping Service
summary: Processes Sendcloud webhook and updates shipment status
service:
id: ShippingService
version: 0.0.1
next_steps:
- id: shipment_status_changed_event
label: Status changed
- id: update_tracking_cmd
label: Push tracking to Order Service
- id: shipment_status_changed_event
title: Shipment Status Changed
message:
id: ShipmentStatusChanged
version: 0.0.1
next_step:
id: order_service_tracking
label: Notify Order Service
- id: update_tracking_cmd
title: Update Tracking
message:
id: UpdateTracking
version: 0.0.1
next_step:
id: order_service_tracking
label: Send tracking data
- id: order_service_tracking
title: Order Service
summary: Updates order with latest tracking info and triggers notifications
service:
id: OrderService
version: 0.0.1
next_step:
id: shopify_tracking
label: Sync tracking to Shopify
- id: shopify_tracking
title: Shopify
summary: Tracking information is synced to the Shopify fulfillment
externalSystem:
name: Shopify
summary: E-commerce platform
url: https://shopify.dev/docs/api/admin-rest/2024-01/resources/fulfillment
---
## Overview
The Shipping & Tracking flow handles the ongoing monitoring of shipment status after a shipment has been created. Sendcloud pushes tracking updates via webhooks, which are processed by the Shipping Service and propagated to the Order Service.
### Tracking lifecycle
1. **Webhook reception** — Sendcloud sends status update webhooks (e.g., `picked_up`, `in_transit`, `delivered`)
2. **Status processing** — Shipping Service validates and persists the status change
3. **Event emission** — `ShipmentStatusChanged` event is published via BullMQ
4. **Command dispatch** — `UpdateTracking` command is sent to Order Service via Internal HTTP
5. **Shopify sync** — Order Service updates the Shopify fulfillment with the latest tracking URL and status
### Status transitions
| Sendcloud Status | Internal Status | Shopify Action |
| --- | --- | --- |
| `ready_to_send` | `label_created` | — |
| `handed_to_carrier` | `picked_up` | Add tracking URL |
| `in_transit` | `in_transit` | Update tracking |
| `delivered` | `delivered` | Mark fulfilled |
| `cancelled` | `cancelled` | — |
### Idempotency
Duplicate webhook deliveries from Sendcloud are handled gracefully — the Shipping Service checks for status progression and ignores out-of-order or duplicate updates.
---
id: StockReplenishment
name: Stock Replenishment
version: 0.0.1
summary: |
Scheduled stock replenishment flow — evaluates inventory deficits, creates stock print batches, and increments stock when batches complete.
badges:
- content: Inventory Flow
backgroundColor: green
textColor: green
steps:
- id: cron_trigger
title: Cron Scheduler
summary: Periodic trigger evaluates whether stock replenishment is needed
service:
id: OrderService
version: 0.0.1
next_step:
id: evaluate_replenishment
label: Check conditions
- id: evaluate_replenishment
title: Evaluate Replenishment
summary: |
StockReplenishmentService checks global config, time windows, order queue depth,
and queries products where currentStock < minimumStock
service:
id: OrderService
version: 0.0.1
next_steps:
- id: create_stock_batch
label: Deficit found
- id: skip_replenishment
label: No action needed
- id: skip_replenishment
title: Skip
summary: No products need replenishment or conditions not met (disabled, busy hours, queue full)
service:
id: OrderService
version: 0.0.1
- id: create_stock_batch
title: Create Stock Batches
summary: |
Creates StockBatch + PrintJob records in the database. Uses an inner loop
per product: creates up to replenishmentBatchSize batches, re-checking deficit
(accounting for pending batches) after each creation.
service:
id: OrderService
version: 0.0.1
next_step:
id: stock_scheduled_event
label: Publish per print job
- id: stock_scheduled_event
title: Stock Replenishment Scheduled
message:
id: StockReplenishmentScheduled
version: 0.0.1
next_step:
id: print_service_stock
label: Send to Print Service
- id: print_service_stock
title: Print Service
summary: Queues the STOCK-purpose print job on SimplyPrint (same flow as ORDER jobs)
service:
id: PrintService
version: 0.0.1
next_steps:
- id: simplyprint_stock
label: Submit to SimplyPrint
- id: stock_job_completed
label: Job completed
- id: simplyprint_stock
title: SimplyPrint
summary: 3D printer farm prints the stock item
externalSystem:
name: SimplyPrint
summary: 3D printer farm management
url: https://simplyprint.io
next_step:
id: print_service_stock
label: Webhook callback
- id: stock_job_completed
title: Print Job Completed
message:
id: PrintJobCompleted
version: 0.0.1
next_step:
id: inventory_routing
label: Route by purpose
- id: inventory_routing
title: Event Subscriber
summary: |
EventSubscriberService checks print job purpose.
STOCK jobs route to InventoryService instead of the normal order orchestration.
service:
id: OrderService
version: 0.0.1
next_step:
id: batch_progress
label: Increment batch progress
- id: batch_progress
title: Batch Progress Check
summary: |
InventoryService increments completedJobs on the StockBatch.
When completedJobs >= totalJobs, the batch is completed.
service:
id: OrderService
version: 0.0.1
next_step:
id: stock_increment
label: All jobs done
- id: stock_increment
title: Stock Increment
summary: |
Atomically increments ProductMapping.currentStock by 1 and records a
PRODUCED InventoryTransaction — all inside a Prisma $transaction.
service:
id: OrderService
version: 0.0.1
---
## Overview
The Stock Replenishment flow enables proactive inventory building. Instead of printing every item on demand, products with `minimumStock > 0` are pre-printed during off-peak hours so they can be immediately shipped when orders arrive.
### Key stages
1. **Evaluation** — A Cron scheduler periodically triggers `StockReplenishmentService.evaluateAndSchedule()`. A mutex (`isRunning`) prevents concurrent executions.
2. **Condition checks** — The service verifies global enable flag, allowed time windows, order queue depth, and concurrent stock job limits
3. **Deficit calculation** — Queries products where `currentStock < minimumStock`, ordered by `replenishmentPriority`
4. **Batch creation** — For each product, creates up to `replenishmentBatchSize` batches in a while loop, re-checking deficit (accounting for pending batches) after each batch. Each `StockBatch` has associated `PrintJob` entries (purpose: `STOCK`)
5. **Print execution** — Print Service queues STOCK jobs in SimplyPrint. ORDER jobs are automatically prioritized ahead of STOCK jobs in the queue (ADR-063)
6. **Completion routing** — When jobs complete, `EventSubscriberService` routes STOCK-purpose jobs to `InventoryService` instead of the normal order flow
7. **Stock increment** — On batch completion, `currentStock` is atomically incremented and a transaction is recorded
### Communication patterns
- **Asynchronous events** (BullMQ): `StockReplenishmentScheduled`, `PrintJobCompleted` (with purpose routing)
- **Internal** (Prisma transactions): Atomic stock increment + transaction recording
### Safeguards
- Replenishment only runs during configured time windows (e.g., overnight)
- Order queue takes priority — stock jobs pause when order queue exceeds threshold
- **Queue priority** — ORDER-purpose jobs are repositioned before STOCK-purpose jobs in SimplyPrint's queue (FIFO within each group, ADR-063)
- Concurrent stock job limit prevents printer farm saturation
- `maximumStock` cap prevents over-production
- **Batch cancellation** — Operators can cancel IN_PROGRESS batches via API (`POST /api/v1/inventory/batches/:id/cancel`), which cancels QUEUED/ASSIGNED print jobs and marks the batch CANCELLED
---
dictionary:
- id: CurrentStock
name: Current Stock
summary: The number of pre-printed units of a product currently on the shelf.
description: |
Tracked on the ProductMapping as `currentStock`. Atomically incremented when a StockBatch completes and decremented when stock is consumed for order fulfillment. Represents the real-time available inventory for a given product.
- id: MinimumStock
name: Minimum Stock
summary: The threshold that triggers automatic replenishment.
description: |
The `minimumStock` value on a ProductMapping. When `currentStock` drops below this value, the replenishment scheduler creates a stock batch to print more units. Setting this to zero effectively disables automatic replenishment for that product.
- id: MaximumStock
name: Maximum Stock
summary: An optional cap on how many units the replenishment system will produce.
description: |
The `maximumStock` value on a ProductMapping. Limits the total stock the system will maintain, preventing overproduction. When omitted, no upper bound is enforced.
- id: ReplenishmentPriority
name: Replenishment Priority
summary: Numeric priority determining which products are restocked first.
description: |
A numeric `replenishmentPriority` on ProductMapping. Higher values are evaluated first when the replenishment scheduler runs, ensuring critical products are restocked before others.
- id: ReplenishmentBatchSize
name: Replenishment Batch Size
summary: The number of print jobs created per replenishment cycle for a product.
description: |
The `replenishmentBatchSize` on ProductMapping, specifying how many print jobs to create per replenishment cycle for that product. Controls the volume of each restocking operation.
- id: StockBatch
name: Stock Batch
summary: A group of STOCK-purpose print jobs created by a single replenishment cycle.
description: |
Tracks `totalJobs`, `completedJobs`, and a lifecycle status. When all jobs complete, `currentStock` is atomically incremented by the number of completed jobs. Can be cancelled by operators via the UI or API.
- id: StockBatchStatus
name: Stock Batch Status
summary: Lifecycle state of a StockBatch.
description: |
`IN_PROGRESS` (jobs printing), `COMPLETED` (all jobs done, stock updated), `FAILED` (jobs failed), `CANCELLED` (operator cancelled the batch). Transitions are driven by print job completion events.
- id: InventoryTransaction
name: Inventory Transaction
summary: An immutable ledger entry recording a stock change.
description: |
Each transaction has a `transactionType`, `quantity` (always positive), `direction` (IN or OUT), `referenceType`, and `referenceId`. Provides a complete audit trail of all stock movements.
- id: TransactionType
name: Transaction Type
summary: The reason for a stock change.
description: |
`PRODUCED` (print job completed → stock in), `CONSUMED` (stock allocated to an order → stock out), `ADJUSTMENT_IN` (manual increase), `ADJUSTMENT_OUT` (manual decrease), `SCRAPPED` (damaged/defective units removed).
- id: StockDirection
name: Stock Direction
summary: Whether a transaction adds to (IN) or removes from (OUT) the available stock.
description: |
Every InventoryTransaction has a direction — `IN` for stock increases and `OUT` for stock decreases. Combined with the always-positive `quantity`, this enables clear ledger accounting.
- id: ReferenceType
name: Reference Type
summary: Links an InventoryTransaction to its source.
description: |
`STOCK_BATCH` (replenishment), `ORDER` (order consumption), `LINE_ITEM` (line-level consumption), `MANUAL` (operator adjustment or scrap). Enables tracing any stock change back to the originating business operation.
- id: StockAwareFulfillment
name: Stock-Aware Fulfillment
summary: Orchestration logic that checks available stock before creating print jobs.
description: |
If sufficient stock exists, units are consumed from the shelf and the order skips printing entirely, going directly to fulfillment. This reduces lead times for products with available inventory.
- id: HybridFulfillment
name: Hybrid Fulfillment
summary: Business model where orders can be fulfilled from pre-printed stock or via print-on-demand.
description: |
Depending on stock availability at the time of order creation, the system either consumes from existing inventory or creates new print jobs. This flexibility allows balancing production efficiency with order responsiveness.
- id: ReplenishmentScheduler
name: Replenishment Scheduler
summary: A cron-based process that evaluates products and creates stock batches when needed.
description: |
Periodically evaluates all managed products and creates stock batches for any whose `currentStock < minimumStock`. Protected by a mutex to prevent concurrent evaluations from creating duplicate batches.
- id: StockManagementFeatureFlag
name: Stock Management Feature Flag
summary: System configuration key that controls whether inventory tracking is active.
description: |
The `feature.stock-management.enabled` configuration key controls whether inventory tracking and replenishment are active for a tenant. When disabled, all orders go through standard print-on-demand fulfillment.
- id: ManualAdjustment
name: Manual Adjustment
summary: An operator-initiated stock change with a required reason.
description: |
An operator can manually increase or decrease stock levels. Recorded as an `ADJUSTMENT_IN` or `ADJUSTMENT_OUT` transaction with an auditable reason. Used for corrections, physical count reconciliation, and other manual interventions.
- id: Scrap
name: Scrap
summary: Recording that pre-printed units are damaged or defective and should be removed from stock.
description: |
Creates a `SCRAPPED` transaction with direction `OUT`. Used when physical units are damaged, defective, or otherwise unusable. Permanently reduces the `currentStock` count.
---
---
dictionary:
- id: PrintJob
name: Print Job
summary: A unit of work representing a single 3D print.
description: |
Linked to a LineItem and optionally an AssemblyPart (for ORDER purpose) or a StockBatch (for STOCK purpose). Identified externally by `simplyPrintJobId` and `simplyPrintQueueItemId`.
- id: PrintJobStatus
name: Print Job Status
summary: Lifecycle state of a PrintJob.
description: |
`QUEUED` (awaiting printer assignment), `ASSIGNED` (printer selected), `PRINTING` (actively printing), `COMPLETED` (finished successfully), `FAILED` (print error), `CANCELLED` (operator or cascade cancellation).
- id: PrintJobPurpose
name: Print Job Purpose
summary: Distinguishes why a print job exists.
description: |
`ORDER` (fulfilling a customer order) or `STOCK` (pre-printing for inventory replenishment). Drives orchestration and inventory transaction logic.
- id: CopyNumber
name: Copy Number
summary: Tracks which copy of a product a PrintJob represents when quantity is greater than one.
description: |
When a line item has `quantity > 1`, each PrintJob is assigned a `copyNumber` to track which copy of the product it represents.
- id: SimplyPrint
name: SimplyPrint
summary: Third-party 3D printer management platform.
description: |
Forma3D.Connect uses the SimplyPrint API for file uploads, job creation, printer monitoring, and status synchronization. Serves as the bridge between the software and physical 3D printers.
- id: SimplyPrintQueueItemId
name: SimplyPrint Queue Item ID
summary: The persistent identifier returned by SimplyPrint when a job is queued.
description: |
The `created_id` returned by SimplyPrint when a job is added to the queue. Used as the stable reference for job operations, distinct from the transient `simplyPrintJobId`.
- id: SimplyPrintJobStatus
name: SimplyPrint Job Status
summary: The status reported by the SimplyPrint API.
description: |
Values include `queued`, `assigned`, `preparing`, `printing`, `completed`, `failed`, `cancelled`. Mapped to the internal `PrintJobStatus` enum by the integration layer.
- id: SimplyPrintPrinterStatus
name: SimplyPrint Printer Status
summary: The state of a physical printer as reported by SimplyPrint.
description: |
Values include `offline`, `operational`, `printing`, `paused`, `error`. Cached locally in the `Printer` entity for quick access without API calls.
- id: Printer
name: Printer
summary: A cached representation of a physical 3D printer from SimplyPrint.
description: |
Tracks `simplyPrintId`, `isOnline`, `currentStatus`, and `currentJobId`. Provides local visibility into printer fleet status without constant API polling.
- id: AssemblyPart
name: Assembly Part
summary: A single printable component within a multi-part product.
description: |
Defined by `partName`, `partNumber`, `simplyPrintFileId`, `printProfile`, estimated print time and filament usage, and `quantityPerProduct`. Determines how many print jobs are created per line item.
- id: ProductMapping
name: Product Mapping
summary: The bridge between a Shopify SKU/variant and the printable file(s) in SimplyPrint.
description: |
Contains a `defaultPrintProfile` and zero or more AssemblyParts. Used by the print service to determine what to print and how for each ordered product.
- id: PrintProfile
name: Print Profile
summary: A JSON configuration specifying slicer/printer settings for a print job.
description: |
Includes layer height, infill, supports, and other settings used when submitting a job to SimplyPrint. Stored on ProductMapping and AssemblyPart.
- id: Gcode
name: Gcode
summary: Machine instructions generated by slicing an STL file.
description: |
The format uploaded to SimplyPrint for 3D printing. Contains the exact movements and extrusion commands for the printer to execute.
- id: STL
name: STL
summary: Stereolithography file format representing 3D geometry.
description: |
Source format for printable models before slicing. Describes the surface geometry of a 3D object as a mesh of triangles.
- id: FileUpload
name: File Upload
summary: The process of sending gcode or STL files to SimplyPrint's file system.
description: |
Returns a `fileId` used to create print jobs. Files are stored in SimplyPrint's cloud storage and referenced when creating new print jobs.
- id: StatusPolling
name: Status Polling
summary: Periodic synchronization of print job statuses from SimplyPrint.
description: |
Controlled by `SIMPLYPRINT_POLLING_ENABLED` and `SIMPLYPRINT_POLLING_INTERVAL_MS`. Supplements webhook-based updates to ensure no status changes are missed.
- id: Reconciliation
name: Reconciliation
summary: Comparing local PrintJob records against SimplyPrint's state to detect drift.
description: |
Corrects discrepancies caused by missed webhooks or polling gaps. Ensures the local database accurately reflects the true state of print jobs in SimplyPrint.
- id: CancelReason
name: Cancel Reason
summary: A numeric code from SimplyPrint indicating why a job was cancelled.
description: |
Examples include print failed, nozzle clog, and operator cancellation. Provides diagnostic context for failed or cancelled print jobs.
- id: Requeue
name: Requeue
summary: An operator action that moves a terminal print job back to QUEUED.
description: |
Moves a `FAILED` or `CANCELLED` print job back to `QUEUED`, triggering an order revival in the Orders domain. Allows operators to retry failed prints without creating new orders.
---
---
dictionary:
- id: Shipment
name: Shipment
summary: A one-to-one record linked to an Order, representing a parcel to be shipped.
description: |
Contains carrier details, tracking info, label URL, weight, and dimensions. Identified externally by `sendcloudParcelId`. Each order has exactly one shipment.
- id: ShipmentStatus
name: Shipment Status
summary: Lifecycle state of a Shipment.
description: |
`PENDING` (awaiting label creation), `LABEL_CREATED` (shipping label generated), `ANNOUNCED` (parcel registered with carrier), `IN_TRANSIT` (picked up and moving), `DELIVERED` (successfully received), `FAILED` (delivery or creation error), `CANCELLED` (shipment voided).
- id: Sendcloud
name: Sendcloud
summary: Third-party shipping aggregation platform used for label generation and parcel tracking.
description: |
Forma3D.Connect uses the Sendcloud API for label generation, carrier selection, parcel tracking, and webhook-based status updates. Abstracts away the complexity of integrating directly with individual carriers.
- id: SendcloudConnection
name: Sendcloud Connection
summary: Per-tenant API credentials for Sendcloud.
description: |
Consists of encrypted `publicKey` and `secretKey`, plus defaults for shipping method and sender address. Each tenant manages their own Sendcloud integration independently.
- id: SendcloudParcelId
name: Sendcloud Parcel ID
summary: The external identifier assigned by Sendcloud when a parcel is created.
description: |
Used for all subsequent API operations on that shipment. Serves as the primary key for interacting with the Sendcloud API after parcel creation.
- id: ShippingLabel
name: Shipping Label
summary: A carrier-specific PDF document containing barcode, routing info, and addresses.
description: |
Generated by Sendcloud and retrieved via `labelUrl`. Contains all information needed for the carrier to process and deliver the parcel.
- id: ShippingMethod
name: Shipping Method
summary: A carrier service option in Sendcloud.
description: |
Examples include PostNL Standard and DPD Express. Identified by `shippingMethodId` and `shippingMethodName`. A default shipping method is configured per tenant.
- id: Carrier
name: Carrier
summary: The logistics company performing physical delivery.
description: |
Examples include PostNL, DPD, and DHL. Identified by `carrierName` on the Shipment. Selected based on the shipping method configured for the tenant.
- id: TrackingNumber
name: Tracking Number
summary: The carrier-assigned identifier for a parcel, enabling package tracking.
description: |
Mirrored on both the Shipment and the parent Order. Passed to Shopify during fulfillment creation for customer visibility.
- id: TrackingUrl
name: Tracking URL
summary: A carrier-provided URL where the recipient can track their shipment.
description: |
Passed to Shopify during fulfillment creation so customers can monitor their delivery progress directly from their Shopify order confirmation.
- id: SendcloudWebhook
name: Sendcloud Webhook
summary: An HTTP callback from Sendcloud triggered by status changes.
description: |
Events like `parcel_status_changed` and `integration_connected` are processed by the `SendcloudWebhookService`. Used to keep shipment statuses synchronized with Sendcloud.
- id: SendcloudStatusRanges
name: Sendcloud Status Ranges
summary: Numeric ID ranges that Sendcloud uses to categorize parcel statuses.
description: |
Ranges cover label created, announced, in transit, delivered, and exception states. Mapped to internal `ShipmentStatus` values by the integration layer.
- id: SenderAddress
name: Sender Address
summary: The shipper's return address in Sendcloud.
description: |
Identified by `defaultSenderAddressId`. Used when creating parcels to specify the return address on shipping labels.
- id: ServicePoint
name: Service Point
summary: A pickup location where the recipient collects their package instead of home delivery.
description: |
Examples include parcel shops and lockers. Captured on the Order with `servicePointId`, `servicePointName`, `servicePointAddress`, and `servicePointPostNumber`.
- id: WeightAndDimensions
name: Weight & Dimensions
summary: Physical parcel attributes required for label generation and carrier rate calculation.
description: |
`weight` in grams and `dimensions` as JSON with length/width/height in centimeters. Required by Sendcloud to generate accurate shipping labels and calculate carrier rates.
---
---
dictionary:
- id: Gridfinity
name: Gridfinity
summary: An open-source modular storage system based on a 42mm grid unit.
description: |
GridFlock generates parametric Gridfinity-compatible baseplates and plate sets. The system is based on a community-driven open standard for modular desktop organization.
- id: GridUnit
name: Grid Unit
summary: The standard Gridfinity cell size of 42mm.
description: |
Defined as `GRID_UNIT_MM`. All grid dimensions are multiples of this unit. Determines the fundamental sizing of all generated baseplates and plate sets.
- id: Baseplate
name: Baseplate
summary: A single Gridfinity base grid, generated as an STL from dimensional parameters.
description: |
Specified as width × depth in grid units. One of two GridFlock job types (`BASEPLATE`). Generated parametrically via OpenSCAD based on the requested dimensions and connector configuration.
- id: PlateSet
name: Plate Set
summary: A multi-plate Gridfinity configuration that exceeds the printer's build area.
description: |
The system automatically calculates the optimal tiling of plates. The second GridFlock job type (`PLATE_SET`). Parent jobs spawn child jobs for individual plates.
- id: GridFlockJob
name: GridFlock Job
summary: A unit of work for parametric grid generation.
description: |
Has a `type` (BASEPLATE or PLATE_SET), JSON `parameters`, generated file metadata, and `progress` tracking. Plate set jobs have parent/child relationships where the parent tracks overall completion.
- id: GridFlockJobStatus
name: GridFlock Job Status
summary: Lifecycle state of a GridFlock Job.
description: |
`QUEUED` (awaiting processing), `PROCESSING` (actively generating/slicing), `COMPLETED` (pipeline finished), `FAILED` (error at any step), `EXPIRED` (cleanup after configurable hours).
- id: GridFlockPipeline
name: GridFlock Pipeline
summary: The end-to-end process from STL generation to product mapping creation.
description: |
STL generation (OpenSCAD) → slicing (BambuStudio CLI) → upload to SimplyPrint → product mapping creation. Runs buffer-based with sequential plate processing to manage memory.
- id: FailedStep
name: Failed Step
summary: The specific pipeline stage where an error occurred.
description: |
One of `stl-generation`, `slicing`, `simplyprint-upload`, or `mapping-creation`. Reported in the `grid.pipeline-failed` event to enable targeted debugging and retry.
- id: OpenSCAD
name: OpenSCAD
summary: Open-source script-based CAD engine used for parametric STL generation.
description: |
Generates Gridfinity STL geometry from grid dimensions, connector types, and magnet configurations. Runs as a native process for automated, on-demand model generation.
- id: Slicer
name: Slicer / Slicing
summary: The process of converting an STL 3D model into gcode machine instructions.
description: |
Performed by a headless BambuStudio CLI running in a dedicated Docker container (`SlicerContainer`). Takes raw 3D geometry and produces printer-ready instructions.
- id: SlicerContainer
name: Slicer Container
summary: A standalone HTTP service wrapping BambuStudio CLI.
description: |
Accepts STL buffers via `POST /slice` and returns gcode buffers. Decoupled from the Grid Service for resource isolation, preventing CPU-intensive slicing from affecting other services.
- id: ConnectorType
name: Connector Type
summary: The interlocking mechanism between Gridfinity baseplates.
description: |
Options include `intersection-puzzle` (IP), `edge-puzzle` (EP), or `none`. Determines the geometry at plate boundaries, enabling plates to physically connect to each other.
- id: GridFlockPreset
name: GridFlock Preset
summary: A saved set of generation parameters for quick reuse.
description: |
Includes dimensions, connector type, magnet configuration, and other parameters. Can be `isPublic` (shared across tenants), `isSystem` (built-in defaults), or tenant-scoped.
- id: MagnetParameters
name: Magnet Parameters
summary: Configuration for optional magnet holes in the baseplate.
description: |
Specifies presence, diameter, and depth of magnet holes. Part of the generation parameters. Allows baseplates to securely attach to metal surfaces.
- id: SlicerMarginBrim
name: Slicer Margin / Brim
summary: Parameters controlling the border area added during slicing for adhesion.
description: |
Affects the printable area calculation for plate sets. Controls how much extra material is added around the base of the print for build-plate adhesion.
- id: MaxDimension
name: Max Dimension
summary: The configurable maximum grid size for GridFlock generation.
description: |
Configured via `grid.max_dimension_mm`. Orders exceeding this are rejected. A separate `MAX_SYNC_GRID_SIZE` threshold determines whether generation runs synchronously or is queued.
- id: PrinterProfile
name: Printer Profile
summary: The target printer model specification used by the slicer.
description: |
Examples include "Bambu Lab A1". Used by the slicer to select appropriate settings for the target hardware. Configured per tenant via `grid.print_settings`.
- id: GridPricing
name: Grid Pricing
summary: Per-tenant pricing model for custom grids.
description: |
Includes `grid.basePrice` (fixed fee), `grid.unitPrice` (per grid unit), `grid.unitSizeMm`, and `grid.currency`. Stored in SystemConfig. Determines the cost charged to customers for custom grid generation.
- id: FeatureFlag
name: Feature Flag
summary: System configuration key that controls whether GridFlock is active for a tenant.
description: |
The `feature.grid.enabled` key. Exposed via the gateway's `TenantFeaturesService`. When disabled, GridFlock SKUs are treated as regular products.
- id: GridCustomSku
name: GRID-CUSTOM SKU
summary: The Shopify SKU prefix that identifies a line item as a GridFlock custom product.
description: |
Any SKU starting with `GRID-CUSTOM` triggers the GridFlock pipeline during order orchestration. The parameters for generation are parsed from the SKU or order metadata.
---
---
dictionary:
- id: Order
name: Order
summary: A tenant-scoped purchase record ingested from Shopify via webhook.
description: |
Contains customer details, shipping address, pricing, and tracks fulfillment progress through `totalParts` / `completedParts` counters. Each order has a lifecycle status and is linked to one or more line items.
- id: LineItem
name: Line Item
summary: A single product line within an Order.
description: |
Identified by `shopifyLineItemId` and `productSku`. Links to a ProductMapping for printing. Carries its own status and part counts independently of the parent Order.
- id: ProductMapping
name: Product Mapping
summary: The link between a Shopify SKU/variant and the printable file(s) in SimplyPrint.
description: |
Includes a `defaultPrintProfile` and optional assembly part definitions. Shared with the Printing and Inventory domains. Serves as the bridge between e-commerce products and 3D printing workflows.
- id: AssemblyPart
name: Assembly Part
summary: One printable component of a multi-part product.
description: |
Defined by `partName`, `partNumber`, `quantityPerProduct`, and a `simplyPrintFileId`. A single ProductMapping may have many AssemblyParts, each representing a separate 3D-printed component.
- id: Orchestration
name: Orchestration
summary: Coordination logic that monitors downstream progress and determines fulfillment readiness.
description: |
Monitors print jobs and GridFlock pipelines, determines when an order is ready for shipping and Shopify fulfillment. Lives in the `OrchestrationService`.
- id: Fulfillment
name: Fulfillment
summary: The act of creating a Shopify fulfillment record with tracking information.
description: |
Triggered once a shipment is confirmed. Distinct from the physical shipping step — fulfillment is the Shopify API call that marks the order as shipped with tracking details.
- id: OrderStatus
name: Order Status
summary: The lifecycle state of an Order.
description: |
`PENDING` (received, awaiting processing), `PROCESSING` (print jobs active), `PARTIALLY_COMPLETED` (some jobs done, some failed), `COMPLETED` (all parts fulfilled), `FAILED` (all jobs failed), `CANCELLED` (operator or Shopify cancellation).
- id: LineItemStatus
name: Line Item Status
summary: The lifecycle state of a Line Item.
description: |
`PENDING`, `PRINTING`, `PARTIALLY_COMPLETED`, `COMPLETED`, `FAILED`. Tracked independently from the parent Order status.
- id: OrderRevival
name: Order Revival
summary: Automatic reversion of a terminal order back to PROCESSING when a print job is requeued.
description: |
When a `FAILED` or `PARTIALLY_COMPLETED` order has a terminal print job requeued by an operator, the order automatically reverts to `PROCESSING` and part counts are recalculated.
- id: ShopifyWebhook
name: Shopify Webhook
summary: An HTTP callback from Shopify that triggers order ingestion.
description: |
Events like `orders/create` and `orders/updated` trigger order processing. Deduplicated via `X-Shopify-Webhook-Id` stored in the `ProcessedWebhook` table.
- id: ProcessedWebhook
name: Processed Webhook
summary: An idempotency record that prevents duplicate webhook processing.
description: |
Keyed by `webhookId` and `webhookType`. Ensures the same Shopify event is not processed more than once, even if Shopify retries delivery.
- id: ShopifyShop
name: Shopify Shop
summary: A tenant's Shopify store connection.
description: |
Holds the encrypted `accessToken`, granted `scopes`, `webhookSecret`, and install/uninstall timestamps. Represents the OAuth-based connection between a tenant and their Shopify store.
- id: EventLog
name: Event Log
summary: A structured business event record for operational visibility.
description: |
Contains `eventType`, `severity` (INFO, WARNING, ERROR), and optional links to an Order or PrintJob. Used for operational visibility, not security audit.
- id: RetryQueue
name: Retry Queue
summary: An exponential-backoff retry mechanism for failed downstream operations.
description: |
Each entry has a `RetryJobType` (FULFILLMENT, PRINT_JOB_CREATION, CANCELLATION, NOTIFICATION, SHIPMENT, GRIDFLOCK_PIPELINE) and a `RetryStatus` (PENDING, PROCESSING, COMPLETED, FAILED).
- id: ServicePointDelivery
name: Service Point Delivery
summary: An alternative delivery mode where the package is sent to a pickup location.
description: |
Captured by `deliveryType` (`home` vs `service_point`) and Sendcloud service-point metadata on the Order. Allows customers to collect packages from convenient pickup points.
- id: GridFlockCustomProduct
name: GridFlock Custom Product
summary: A line item whose SKU starts with GRID-CUSTOM, requiring parametric grid generation.
description: |
Indicates the product requires Gridfinity grid generation before printing. Triggers the GridFlock pipeline during orchestration, which generates the STL, slices it, and creates a product mapping.
- id: PartCounts
name: Part Counts
summary: Counters that track fulfillment progress on Orders and Line Items.
description: |
`totalParts` and `completedParts` tracked on both Order and LineItem. Orchestration uses these to determine when all printable components are done and the order is ready for fulfillment.
---
---
dictionary:
- id: Tenant
name: Tenant
summary: An isolated organizational unit within Forma3D.Connect.
description: |
Identified by a `slug`. Each tenant has its own users, roles, integrations, feature flags, and configuration. The `isDefault` tenant serves as the system default.
- id: User
name: User
summary: An authenticated operator or administrator within a tenant.
description: |
Assigned one or more Roles that grant Permissions. Authenticated via session-based auth with cookie-based identity.
- id: Role
name: Role
summary: A named set of permissions assigned to users.
description: |
`admin` (full access), `operator` (day-to-day operations), `viewer` (read-only), `legacy-admin` (API key backward compatibility). Each role has a specific set of permissions attached.
- id: Permission
name: Permission
summary: A granular access right following the resource.action pattern.
description: |
Examples include `orders.read`, `printJobs.write`, `inventory.write`, `admin.operations`. Assigned to Roles via RolePermission join records. Controls what actions users can perform.
- id: SessionBasedAuth
name: Session-Based Auth
summary: The authentication mechanism using express-session backed by PostgreSQL.
description: |
No JWTs — sessions are server-side with cookie-based identity. The session store is backed by PostgreSQL for persistence across server restarts.
- id: ApiKey
name: API Key
summary: A legacy authentication mechanism for machine-to-machine access.
description: |
Validated by the gateway. Used by the `legacy-admin` role for automated integrations and backward compatibility with older API consumers.
- id: SystemConfig
name: System Config
summary: Per-tenant key-value configuration stored as JSON.
description: |
Controls feature flags, integration settings, pricing, and operational parameters. Examples include `feature.grid.enabled`, `stock.replenishment.enabled`, and grid pricing configuration.
- id: FeatureFlag
name: Feature Flag
summary: A SystemConfig entry that enables or disables functionality per tenant.
description: |
Examples include `feature.grid.enabled` and `feature.stock-management.enabled`. Exposed via the gateway's `TenantFeaturesService`. Allows gradual rollout and per-tenant customization.
- id: Gateway
name: Gateway
summary: The API gateway application that handles HTTP routing and authentication.
description: |
Handles HTTP routing, WebSocket proxying, authentication, rate limiting, and Swagger aggregation. Proxies requests to downstream services: order-service, print-service, shipping-service, grid-service, and slicer.
- id: BullMQEventBus
name: BullMQ Event Bus
summary: The cross-service asynchronous messaging infrastructure built on BullMQ.
description: |
Redis-backed queues where each event type corresponds to a named queue. The canonical event names are defined in `SERVICE_EVENTS`. Provides reliable, persistent message delivery between services.
- id: EventEmitter2
name: EventEmitter2
summary: The in-process event system used for intra-service communication.
description: |
NestJS-based event system. Bridge services translate between local EventEmitter2 events and cross-service BullMQ events. Used for decoupling components within a single service.
- id: SocketIO
name: Socket.IO
summary: The real-time WebSocket transport used to push events to the PWA frontend.
description: |
Operates on the `/events` namespace with `WsApiKeyGuard` authentication. Emits events like `order:created`, `printjob:status-changed`, etc. Enables live dashboard updates.
- id: CorrelationId
name: Correlation ID
summary: A unique identifier propagated across service boundaries to trace business operations.
description: |
Used by `BusinessObservabilityService` to trace a single business operation through logs and events across all services.
- id: AuditLog
name: Audit Log
summary: A security-focused record of sensitive actions.
description: |
Captures `actorUserId`, `targetType`, `targetId`, and `metadata` for actions like `auth.login.success` and role changes. Distinct from the business EventLog used for operational visibility.
- id: HealthCheck
name: Health Check
summary: Aggregated downstream service health verification exposed by the gateway.
description: |
Checks connectivity to all proxied services and infrastructure dependencies. Provides a single endpoint that reports the overall system health status.
- id: PushSubscription
name: Push Subscription
summary: A Web Push API subscription stored per user for browser push notifications.
description: |
Each subscription has toggles for order, print, shipment, and system notification categories. Allows users to receive real-time alerts even when the browser tab is closed.
- id: IntegrationReinitialization
name: Integration Reinitialization
summary: Live-reloading third-party API clients when tenant settings change.
description: |
Allows reloading SimplyPrint and Sendcloud API clients without requiring a service restart. Triggered by `integration.simplyprint-changed` and `integration.sendcloud-changed` events.
- id: RetryQueue
name: Retry Queue
summary: A platform-level exponential-backoff mechanism for failed operations.
description: |
Supports job types across all domains (FULFILLMENT, PRINT_JOB_CREATION, CANCELLATION, NOTIFICATION, SHIPMENT, GRIDFLOCK_PIPELINE) with statuses PENDING, PROCESSING, COMPLETED, FAILED.
- id: BullBoard
name: Bull Board
summary: A monitoring UI for BullMQ queues.
description: |
Provides visibility into event bus queue depths, failed jobs, and processing rates. Used by operators and developers to monitor and troubleshoot the messaging infrastructure.
- id: Sentry
name: Sentry
summary: The observability platform integrated for error tracking and performance monitoring.
description: |
Provides error tracking, performance monitoring, and structured logging across all services. Captures unhandled exceptions, slow transactions, and custom metrics.
---