Skip to content

Services

openwcs-docs-agent edited this page Jun 11, 2026 · 64 revisions

Services

Ports and responsibilities. Status legend: ✅ functional · 🟡 partial · 🟦 scaffold (health/info only). Live detail: docs/DEVELOPMENT-STATUS.md.

Service Lang Port Status Responsibility
gateway Java 8080 API gateway; routes /api/<service>/**; JWT validation (toggleable) + forwards X-Auth-User/X-Auth-Roles. GET /api/system/services — fans out to every service's health probe + /actuator/info in parallel (3 s timeout; unreachable → DOWN) and returns {name, kind, status, version, commit, buildTime, latencyMs}; service list is config-driven (openwcs.system.services). GET /api/system/services/{name}/logs?date= — returns the log for that service on the given date (latest available day if omitted) from the shared openwcs-logs volume; path-traversal-guarded; unknown service → {error}. GET /api/system/services/{name}/log-days — lists available log dates. Every service writes daily rotating files (<service>.<YYYY-MM-DD>.log, 14-day retention) to the shared volume — Java via libs:common logback-spring.xml, Go adapters via a daily writer.
master-data Java 8081 Catalog (SKUs, UoMs, barcodes, locations, equipment, warehouses, handling unit types, barcode types) + outbound config (shippers, fulfillment config — editable from the UI's Settings → Cubing tab: cubing rules + full shipper CRUD with fill rates) + dispatch reference data (shipping-services, routes, label-templates + ZPL/PDF render) + demo mode (GET /api/master-data/demo?warehouseId=, POST /demo/enable?warehouseId=, POST /demo/disable, ADMIN-only): seeds 100 movie-merch–named SKUs (ownerClient=DEMO) + UoMs/EAN-13 barcodes + shippers + storage HU type; enable is blocked unless the catalog is empty and the warehouse already has storage locations; status is warehouse-aware; disable removes all demo catalog data. Hardware emulator mode (GET /api/master-data/emulator, `POST /emulator/enable
inventory Java 8082 Durable stock projection from txlog.stream; SKU- and location-scoped availability/reservations (ATP); handling unit registry (/api/inventory/handling-units): CRUD for HU instances — huTypeId and locationId are fixed at registration and preserved server-side on PUT regardless of the request body (they change only through a controlled process such as maintenance / QA); GET /handling-units/active-count?huTypeId= count of ACTIVE HUs per type (gates HU-type archiving); occupancy check (POST /api/inventory/occupancy {locationIds} — counts stock rows and handling units at a given set of location IDs; used to gate storage-block deletion from the UI); per-location occupancy (POST /api/inventory/locations/occupied {locationIds[]} → {occupiedLocationIds[]} — returns the subset of the given locations that physically hold any stock row or handling unit; consumed by slotting put-away to exclude occupied candidate slots before scoring, and by GTP store-back routing); demo seed/clear (`POST /api/inventory/demo/seed
process-engine Java 8083 🟡 Embedded Flowable BPMN: deploy definitions, start/inspect instances, user-task list/complete; service-task delegates originate WCS work (dispatchDeviceTask, assignRoute, releaseOrder). Sample goods-in / outbound (with a user task) / cycle-count processes.
order-management Java 8084 Orders of all types (INBOUND/OUTBOUND/COUNT/ADJUSTMENT), lifecycle, release management, dispatch service/route + ship-to + label-template, line stock transactions (outbox → txlog); delegates allocation. Demo clear (POST /api/orders/demo/clear?warehouseId=, ADMIN-only): purges all orders for the warehouse (cascading lines + transactions) + order outbox. Demo quick-seed (`POST /api/orders/demo/seed?type=INBOUND
flow-orchestrator Java 8085 🟡 Device-task lifecycle over the uniform device contract; routes to adapters by equipment family. Flag-aware emulator routing (Phase 2): HttpEmulatorModeClient reads HARDWARE_EMULATOR_ENABLED from master-data (TTL-cached 5 s, defaults OFF on error); when ON every family dispatches to the single equipment-emulator service (OPENWCS_EMULATOR_URL, default http://localhost:9097); when OFF to the per-family adapters. Task body now includes family (emulator multiplexes families using it; real adapters ignore the extra field). New property openwcs.flow.master-data-base-url (OPENWCS_MASTER_DATA_BASE_URL, default http://localhost:8081). Async device contract (Phase 3b): HttpDeviceClient includes a callbackUrl (built from openwcs.flow.self-base-url / OPENWCS_FLOW_SELF_BASE_URL, default http://localhost:8085) in every task request body; when the device responds ACCEPTED or DISPATCHED, the task stays DISPATCHED in flow until the terminal result is POSTed back via POST /api/flow/device-tasks/{id}/result (DeviceTaskResultCallback); completeFromCallback is idempotent — an already-terminal task is left unchanged. Real adapters respond COMPLETED/FAILED inline and ignore callbackUrl; the emulator goes async. Automation Topology placement API: warehouse levels, placed equipment (x/y/z, rotation/tilt, envelope), equipment connections, and function points per warehouse (GET/PUT /api/flow/automation/topology?warehouseId=; save remaps client temp-ids). Placed equipment carries a denormalised category (conveyor / asrs / sorter / manual-storage / workstation / other); a workstation placement has a station_id UUID (V10 migration) — soft reference to the GTP station it represents (no FK; gtp lives in a separate service). Physical equipment connections are no longer drawn as lines and the manual Connect button has been removed — links are auto-inferred from geometry by the routing projection (in progress); the Conveyor interactions panel (workstation properties) adds point-level AutomationConnection entries from the workstation to a specific conveyor function point, each tagged with a role (STOCK / ORDER / DECANT). Routing-graph projection (POST /api/flow/automation/topology/project?warehouseId=): generates the full ConveyorNode/Edge graph from the placed topology model in one call — 3D editor Generate routing button. As a best-effort side-effect (after the routing graph is persisted), projects STOCK/ORDER conveyor interactions into each bound GTP station's nodes (GtpClient.syncStationNodes): function-point offsetM is carried as inboundDistanceM for emulator queue timing; the GTP call is bounded by a 2-second connect/read timeout and any failure is swallowed — a slow/unreachable GTP never aborts the projection. See Equipment Integration. Flow-owned induction queue (ADR-0007 Phase 3c-1): flow-orchestrator now owns the REQUESTED → IN_TRANSIT → QUEUED → DONE inbound pipeline for all workplace types (V11 migration: induction_queue_entry + hu_transport_trace). POST /api/flow/induction/requests — callers (counting, other services) submit a single request; flow creates a REQUESTED entry (uncapped backlog), then meters retrievals into the {IN_TRANSIT, QUEUED} cap by dispatching the RETRIEVE device task; the RETRIEVE callback advances the entry to IN_TRANSIT and dispatches the CONVEY leg; the CONVEY arrival callback advances to QUEUED and assigns an arrivalSeq (arrival order, not request order). GET /api/flow/induction/queue?workplaceId= — full {REQUESTED, IN_TRANSIT, QUEUED} pipeline ordered by arrival_seq; DONE excluded. POST /api/flow/induction/entries/{id}/done — operator-driven completion; idempotent; frees a cap slot and re-meters the REQUESTED backlog. GET /api/flow/induction/entries/{id} — single entry read. Workplace in-transit caps are read best-effort from GET /api/gtp/stations/{id} (WorkplaceClient, 2 s timeout, falls back to default 2 per mode class). Per-HU transport trace: GET /api/flow/hu-trace?huId= returns the append-only timeline of every function point an HU passed — REQUESTED → RETRIEVED → INDUCTED → ARRIVED → QUEUED → DONE — each row with ts, point, event, decision, fromPoint, toPoint, workplaceId, correlationId, taskId, inductionEntryId. The click-to-trace dialog in the Transport Overview reads this timeline instead of the coarse correlation-based device-task list; see Transport Overview. Demo clear (POST /api/flow/demo/clear?warehouseId=, ADMIN-only): purges device tasks, HU route plans, topology observations, induction queue entries, and HU transport trace rows; conveyor topology kept.
txlog Java 8086 Append-only event log (system of record) + transactional outbox + relay to txlog.stream; global replay feed.
iam Java 8087 Authorization model: users → roles → coded permissions; effective-permission resolution; per-user warehouse access (allowed warehouses + default; gateway-enforced scope). (Keycloak does authentication.)
notification Java 8088 🟦 Operator alerts / exceptions / andon — planned.
integration-sap Java 8089 🟡 SAP gateway: label-barcode allocation, route feed → master-data, and SAP order/ASN intake translated into the Host API.
integration-manhattan Java 8090 🟡 Manhattan gateway: order/ASN intake translated into the Host API.
allocation Java 8091 Pick-location allocation (UoM breakdown), multi-size cubing into shippers (largest-first, per-line carton traceability) + per-carton dispatch labels, batch picking.
slotting Java 8093 Put-away for automated rack/GTP blocks (weighted scorer: velocity-to-exit · same-SKU lane consolidation · aisle redundancy · fill balance), manual pick-face slotting + min/max replenishment (opportunistic top-off), off-peak re-slotting. See Slotting and Replenishment.
gtp Java 8094 Goods-to-person station execution: configure stations + STOCK/ORDER nodes, present a stock HU → put-to-light put-list across order destinations (one HU serves many orders = batch), confirm puts (incl. short), complete destinations. ORDER_LOCATION (conveyor) + PUT_WALL (lit rack/AMR) modes. Station inbound queue (ADR-0007 Phase 3c-1: flow-owned): the live queue is now read from flow-orchestrator (GET /api/flow/induction/queue?workplaceId=) and operator completion calls POST /api/flow/induction/entries/{id}/done (via flow). The legacy gtp-owned POST/GET /api/gtp/stations/{id}/queue and POST /api/gtp/queue/{id}/complete endpoints remain in place but are deprecated — counting no longer calls them. Deactivate/drain (`POST /stations/{id}/deactivate
counting Java 8095 Cycle / stock counting: count tasks (location/SKU/zone/block scope, blind or variance), ABC-cadence scheduling, capture → variance vs an inventory snapshot → reconcile (auto-approve within tolerance / recount) → StockAdjusted; blind count tasks withhold the Expected-qty column in the capture dialog until reconciled (the operator must not see expected quantities during a blind count). Delete OPEN tasks (DELETE /api/counting/tasks/{taskId}): removes a count task and its lines while still OPEN; returns 409 once counting has begun (any non-OPEN status); a Delete button is shown on OPEN rows in the UI. Seams: GTP STOCK_COUNT station + cycle-count BPMN by id. Count-tote routing (emulator mode only): count tasks for automated-storage cells (SHUTTLE_ASRS, CRANE_ASRS, AUTOSTORE, AMR_GTP) are routed to an active GTP STOCK_COUNT station asynchronously — task creation always returns immediately with routingStatus = PENDING. A background CountRoutingScheduler (ShedLock-protected; one replica per sweep) retries all OPEN tasks whose routing is PENDING or FAILED every minute (configurable via openwcs.counting.routing-retry-ms, default 60 000 ms). The routing outcome is persisted on the task as routingStatus (PENDING
integration-host Java 8092 🟡 Canonical vendor-neutral Host API (/api/host/**): orders + ASNs + SKU sync (upsert — SKUs absent from the batch are left untouched; within each synced SKU the host is authoritative and its nested UoMs/barcodes fully replace what is stored) + inventory adjustments in; confirmations out via pull (cursor) + webhook push; idempotency keys. See Host Integration.
adapters/conveyor Go 9091 🟡 PLC conveyor adapter; POST /tasks real-hardware skeleton — validates command, returns FAILED "hardware not connected" (no live protocol client yet). No emulation code (removed in Phase 2b). When HARDWARE_EMULATOR_ENABLED is ON, flow-orchestrator routes tasks to equipment-emulator; this adapter receives no traffic. /healthz, /readyz, GET / (service info). Version/commit/buildTime injected at build via -ldflags.
adapters/{asrs,amr-geekplus,autostore} Go 9096, 9093, 9094 🟡 Real-hardware skeletons for ASRS (STORE/RETRIEVE/SCAN), AMR (TRANSPORT/MOVE/SCAN), AutoStore (BIN_STORE/BIN_RETRIEVE/SCAN). POST /tasks validates the command and returns FAILED "hardware not connected" (protocol clients pending). No emulation code (removed in Phase 2b); GET /state removed. When HARDWARE_EMULATOR_ENABLED is ON, flow-orchestrator routes tasks to equipment-emulator; these adapters receive no traffic. /healthz, /readyz, GET /. Version/commit/buildTime injected at build via -ldflags.
equipment-emulator Go 9097 🟡 Single emulator for all device families (ASRS, CONVEYOR, AMR, AUTOSTORE) behind the uniform device contract. When HARDWARE_EMULATOR_ENABLED is ON, flow-orchestrator routes every device task here instead of to the per-family adapters. POST /tasks — accepts {taskId, warehouseId, equipmentId, family, command, payload, callbackUrl}. Optional callbackUrl (set by flow from OPENWCS_FLOW_SELF_BASE_URL) switches the task async: acks ACCEPTED immediately, runs the task in a background goroutine, and POSTs the terminal result back to the URL (best-effort; not retried on failure). Without callbackUrl: runs inline and returns the terminal result directly. In both paths: validates family + command, sleeps a realistic per-family/command duration, then returns/posts COMPLETED with simulated:true and durationMs (simulated ms) or FAILED; families: ASRS (STORE/RETRIEVE/SCAN), CONVEYOR (CONVEY/DIVERT/MERGE/SCAN), AMR (TRANSPORT/MOVE/SCAN), AUTOSTORE (BIN_STORE/BIN_RETRIEVE/SCAN). OPENWCS_EMULATOR_LATENCY_MS overrides every command (0 = instant). Fault injection (OPENWCS_EMULATOR_FAULT_RATE=N): 1 in every N tasks returns FAILED deterministically (result carries fault: true; 0/unset = none). Loop recirculation (OPENWCS_EMULATOR_RECIRC_EVERY=N, ADR-0007 Phase 3c-2): every Nth CONVEY task recirculates the loop once before diverting — arrival order diverges from dispatch order (R2); the CONVEY result reports recirculations and decisions (sorter RECIRCULATED/DIVERTED points) which flow writes to the HU transport trace before the ARRIVED row (R4); 0/unset = none. GET/POST /config — reads or updates {latencyOverrideMs, faultEvery, recircEvery} at runtime without a restart; seeded from env at startup. GET /state — real per-family completed/failed tallies from actual task load plus liveness heartbeat; also echoes live config including recircEvery. /healthz, /readyz, GET / — probes + service info. No flag gate inside the service; no DB/Kafka/hardware connection. stdlib only.
ui React/TS 5173 dev / 443 prod 🟡 React/Vite SPA: Keycloak login + app shell + dashboard + screen permission catalog (role/user-gated, overridable per role/user via Access control). Screens: inbound, outbound, counting (in-app confirm dialog for OPEN-task delete), GTP operator console (operating mode persisted per station in localStorage, restored on reload; active-tote panel fills the viewport when no cycle is active — larger SKU image, centred; idle waiting-for-totes state also full-screen; STOCK_COUNT mode: queue entries carrying countTaskId/countLineId switch to a dedicated CountPanel — operator enters their counted qty blind (no expected qty shown); clears on RECOUNT, advances on ACCEPTED/ADJUSTED; falls back to a "Done counting" button when the link is absent) + workplace config, transport overview (HU code column; origin/destination/next-hop resolve UUIDs to location codes via useCatalog or GTP station codes via listWorkplaces; unknown UUIDs fall back to a short id; next-hop falls back to destination for ASRS/AMR/AutoStore direct-delivery tasks; scope filter: "Open + finished today" (default working-set — active + completed today), "Open (active) only", "Completed", "Failed", "All recent" — client-side on a 500-task backend window; click-to-trace: click a row → detail + trace dialog with code-resolved fields + ordered correlation trace from GET /api/flow/device-tasks?correlationId=; see Transport Overview), stock transactions, automation topology (3D/2D-plan toggle: 3D layout editor — place/size equipment on warehouse levels, orbit/pan/zoom with on-screen hint; ▴/▾ fold toggle collapses the page title + level-name/elevation meta for more canvas height (persisted to localStorage); 2D top-down plan editor — SVG, snap-to-grid 0.25/0.5/1 m, drag/place/rotate equipment, draw conveyor sections with direction arrows + auto decision points, draggable waypoints; function-point palette — arm a type (SCAN/DIVERT_LEFT/DIVERT_RIGHT/DWS/etc.) and click the conveyor to drop it at position, with DIVERT drops junction-splitting the path and entering branch-draw mode; function-point markers rendered in 2D colour-coded by type (diverts red); both views share the same model; conveyor routing graph — React Flow), processes, slotting, a dedicated Master data sidebar section (standard collapsible like Operations / Engineering — 7 individually-routed, individually-access-controlled screens: Warehouses / SKUs / Storage blocks / Locations / Equipment / Handling unit types / Label templates, each at /master-data/<entity>; /master-data redirects to Warehouses; full CRUD admin catalogs; HU types: admin archive/restore buttons with "Show archived" toggle — archived types de-emphasised and excluded from the HU type-picker; Storage blocks: admin archive/restore ("Show archived" toggle de-emphasises archived blocks) + delete (cascade-deletes locations, gated on occupancy check) buttons; Guided builder step-through dialog with per-field descriptions + an aisle × levels × positions × sides × lane depth location generator; GTP auto-derived from storage type (automated types locked to GTP, MANUAL_PICK editable); allowed HU types is a chip multi-select of active type names; Storage block dialog: Equipment select links the block to an ASRS-family device; Equipment dialog (ASRS/AUTOSTORE/AMR types): Storage areas chip multi-select links storage blocks (reconciles storage_block.equipment_id on save); Location dialog: optional hardware address field (controller/device address, e.g. ASRS bin address); per-catalog in-app help for each screen; InfoTip hover help on every editable field — a styled "?" that reveals a portalled popover with a plain-English explanation and a concrete example (159 tooltips across 14 screens); each catalog listed and individually gated in the Access control screen), settings (incl. Demo mode tab — ADMIN-only toggle; seeds movie-merch SKUs + handling units + stock into the warehouse's existing locations; switching off performs a full operational reset across all services — purging stock, reservations, HUs, orders, transports, counts, and GTP work — while keeping infrastructure), user management, access control, system info (ADMIN; Administration section: searchable/sortable table of all backend units with a health pill, version, commit, build time and probe latency; unhealthy-first ordering; auto-refresh every 10 s + manual refresh; data from GET /api/system/services; Logs button per row opens a modal with the last N lines of that container's stdout/stderr — tail selector 200–2000, manual refresh, client-side line filter (free-text; "N / M lines" count shown when active), Esc/backdrop close, auto-scroll to newest (suppressed while filtering); "Open as page" button → /system-info/logs/:name, a full-height dedicated log view sharing the same LogViewer (filter + tail + day picker — Latest + each available date — + refresh); logs fetched from GET /api/system/services/{name}/logs?date= + …/log-days (persistent daily files on the shared openwcs-logs volume, 14-day retention)). Warehouse dialog: IANA timezone dropdown + optional address fields (line1/line2/city/region/postal-code/country). SKU search matches code / description / barcode. A shared useCatalog hook fetches location, SKU, and equipment catalogs from master-data on mount and resolves entity ids to human-readable codes across the operations screens — counting (scope column + capture dialog), outbound pick detail, stock-transaction From/To, and transport equipment column all show location codes, SKU codes + descriptions, and equipment codes instead of raw UUIDs; transport origin/destination/next-hop additionally resolve against GTP station codes (listWorkplaces). Served by nginx over HTTPS on :443 (80→443); gateway JWT enforced. Sign in admin/admIn1!.

All Java services: Java 21 / Spring Boot 3.3, PostgreSQL 16 via Flyway + JPA/Hibernate 6 (ddl-auto: validate — migrations own the schema), UUID keys, JSONB via @JdbcTypeCode.

See Architecture for data ownership and the event backbone, and API Reference for gateway routes and OpenAPI specs.

Clone this wiki locally