4.2 KiB
OpenSpec Change: enterprise-api-plugin-inventory
- Change ID: enterprise-api-plugin-inventory
- Package:
@suaveplan/api-plugin-inventory - Category: api/logistics
- Target path:
api/logistics/api-plugin-inventory - Status: PROPOSED
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/api-plugin-inventory.md
Summary
Deliver @suaveplan/api-plugin-inventory on the genesis branch from scratch at enterprise quality. The main-branch package has 0% test coverage, no tenant isolation, no auth, no idempotency, no audit, and the advertised procurement:grn:completed auto-integration is a log statement only. Genesis delivers the full implementation: item catalog, multi-warehouse stock tracking, stock movements (receive/issue/transfer) with FIFO/LIFO/average/specific-ID costing (corrected and tested), lot + expiry tracking, physical-count adjustment workflow, low-stock/expiring-stock/valuation reports, real procurement:grn:completed subscription that creates stock movements, tenant isolation on every query, and full enterprise cross-cutting (auth/idempotency/audit/rate-limit). Routes under /inventory. Per-table SurrealQL.
Available workspace deps on genesis
| Package | Role |
|---|---|
@suaveplan/api (workspace:^) |
definePlugin |
@suaveplan/api-shared (workspace:^) |
Helpers |
@suaveplan/api-plugin-auth (workspace:^) |
requireAuth, permissions |
@suaveplan/api-plugin-database (workspace:^) |
SurrealDB |
@suaveplan/events (workspace:^) |
Bus; subscribe to procurement:grn:completed |
@suaveplan/error (workspace:^) |
InventoryError hierarchy |
@suaveplan/idempotency (workspace:^) |
Stock movement guard |
@suaveplan/audit-logging (workspace:^) |
Adjustment + disposal audit |
@suaveplan/rate-limiter (workspace:^) |
Rate limits |
decimal.js (catalog) |
Monetary precision |
hono + @hono/zod-openapi + zod |
Routes |
@opentelemetry/api |
OTel |
Public API surface
function createInventoryPlugin(config?: InventoryConfig): PluginDescriptor<InventoryConfig>
// Types (preserved + corrected)
InventoryItem, CreateItemInput, UpdateItemInput, StockMovement, Warehouse
StockLevel, LotInfo, CostingMethod, AdjustmentRecord
// Services: ItemService, WarehouseService, StockService, MovementService,
// AdjustmentService, CostingService, ReportService
// Routes: /inventory/items, /inventory/warehouses, /inventory/stock,
// /inventory/movements, /inventory/adjustments, /inventory/reports
Error codes
type InventoryErrorCode =
| "INVENTORY_ITEM_NOT_FOUND"
| "INVENTORY_WAREHOUSE_NOT_FOUND"
| "INVENTORY_INSUFFICIENT_STOCK"
| "INVENTORY_LOT_EXPIRED"
| "INVENTORY_ADJUSTMENT_CONFLICT"
| "INVENTORY_COSTING_ERROR"
Genesis additions vs main-branch
- 100% test coverage on all costing methods (FIFO/LIFO/average/specific-ID).
- Real
procurement:grn:completedsubscription inonReady— creates stock movements, not just logs. onCloseteardown — detach bus subscription.InventoryConfigSchemaexpanded withbasePath,defaultCostingMethod,lowStockThreshold.- Remove
ctx.eventBus.on("procurement:grn:completed" as never, ...)— proper EventMap declaration. - Per-table SurrealQL — split single
inventory.surqlinto per-entity files. - Auth + tenant isolation on every route and query.
- Idempotency on stock movements.
- Audit logging on adjustments and disposals.
File layout
api/logistics/api-plugin-inventory/
package.json tsconfig.json vitest.config.ts
surql/ (inventory_item, warehouse, stock_level, stock_movement, lot, adjustment tables)
src/
index.ts events.ts types/ errors/
services/item/ services/warehouse/ services/stock/
services/movement/ services/adjustment/ services/costing/ services/report/
routes/inventory/
tests/integration.test.ts
Impact
Prerequisites: @suaveplan/api, @suaveplan/api-plugin-auth, @suaveplan/api-plugin-database, @suaveplan/events, @suaveplan/idempotency, @suaveplan/audit-logging. Downstream: @suaveplan/api-plugin-warehouse-ops (stock queries), @suaveplan/api-plugin-store (stock reservation).