openapi: 3.0.3 info: title: Internal next-root bounded quantity diagnostics version: 2.0.0 description: Explicit arm only; no automatic rearm. Bind next normal automatic historical OUTBOUND_QUERY root within 6h. Sampling expires 4h after first LIST observedAt, never later than armedAt+10h. Lastleg session lock is receiver acceptance. Source root creation may predate arm. LOCATE, manual/validation roots, current excluded root and different bound root are rejected/ignored. At most 100 distinct LIST candidates total, 2000 retained SKU rows across both sides, 2MiB canonical evidence plus promotion overhead. Pending-to-final never refunds quota. First unknown or SKU mismatch persists INCONCLUSIVE and stops; any known inequality among list/forecast/actual persists QUANTITY_DIFFERENCE and stops. Original side timestamps/attempts are immutable; exact replay returns stored receipt even after termination, changed same-side evidence is rejected. Root termination drains only accepted candidates via an explicit Integration FIFO boundary without extending expiry. Fewer than 100 complete pairs is ROOT_ENDED_INSUFFICIENT; unpaired/lost tail is INCOMPLETE. Producer restart retains persisted candidates but marks delivery uncertain. Every request/response is stream-bounded to 262144 bytes. Never exposed through Gateway, never creates supplier requests or changes business facts. paths: /internal/lastleg/self-operated-analytics/quantity-diagnostics/arm: post: operationId: quantityDiagnosticArm security: - internalServiceToken: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Arm' responses: '200': description: ApiResponse code 200. status data is null if no grant exists. content: application/json: schema: type: object additionalProperties: false properties: code: type: string message: type: string nullable: true data: $ref: '#/components/schemas/View' nullable: true required: - code - data '400': description: Invalid scope, changed frozen evidence, invalid observation or disabled feature. '401': description: Missing or invalid internal service token. '503': description: Diagnostic admission, dedicated connection or storage unavailable; collection is unaffected. /internal/lastleg/self-operated-analytics/quantity-diagnostics/status: post: operationId: quantityDiagnosticStatus security: - internalServiceToken: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Status' responses: '200': description: ApiResponse code 200. status data is null if no grant exists. content: application/json: schema: type: object additionalProperties: false properties: code: type: string message: type: string nullable: true data: $ref: '#/components/schemas/View' nullable: true required: - code - data '400': description: Invalid scope, changed frozen evidence, invalid observation or disabled feature. '401': description: Missing or invalid internal service token. '503': description: Diagnostic admission, dedicated connection or storage unavailable; collection is unaffected. /internal/lastleg/self-operated-analytics/quantity-diagnostics/observe: post: operationId: quantityDiagnosticObserve security: - internalServiceToken: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Event' responses: '200': description: ApiResponse code 200. status data is null if no grant exists. content: application/json: schema: type: object additionalProperties: false properties: code: type: string message: type: string nullable: true data: $ref: '#/components/schemas/Receipt' nullable: true required: - code - data '400': description: Invalid scope, changed frozen evidence, invalid observation or disabled feature. '401': description: Missing or invalid internal service token. '503': description: Diagnostic admission, dedicated connection or storage unavailable; collection is unaffected. /internal/lastleg/self-operated-analytics/quantity-diagnostics/stop: post: operationId: quantityDiagnosticStop security: - internalServiceToken: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Stop' responses: '200': description: ApiResponse code 200. status data is null if no grant exists. content: application/json: schema: type: object additionalProperties: false properties: code: type: string message: type: string nullable: true data: $ref: '#/components/schemas/View' nullable: true required: - code - data '400': description: Invalid scope, changed frozen evidence, invalid observation or disabled feature. '401': description: Missing or invalid internal service token. '503': description: Diagnostic admission, dedicated connection or storage unavailable; collection is unaffected. components: securitySchemes: internalServiceToken: type: apiKey in: header name: X-Internal-Service-Token schemas: Arm: type: object additionalProperties: false properties: diagnosticSessionId: type: string maxLength: 128 minLength: 1 sourceAccount: type: string maxLength: 64 minLength: 1 warehouseCodes: type: array minItems: 1 maxItems: 8 uniqueItems: true items: type: string maxLength: 64 minLength: 1 ownerCode: type: string maxLength: 128 minLength: 1 description: Explicit owner code, or * for all allowed owners. excludedRootTaskId: type: string maxLength: 128 minLength: 1 nullable: true description: Must match the actual started, unfinished automatic root at arm; null only when none exists. required: - diagnosticSessionId - sourceAccount - warehouseCodes - ownerCode Status: type: object additionalProperties: false properties: sourceAccount: type: string maxLength: 64 minLength: 1 producerId: type: string maxLength: 128 minLength: 1 attach: type: boolean description: True only on Integration process attachment; replacement marks delivery uncertain and fences prior producer. drained: type: boolean description: Only after observing DRAINING, closing intake and draining previously queued callbacks. required: - sourceAccount - producerId - attach - drained Stop: type: object additionalProperties: false properties: diagnosticSessionId: type: string maxLength: 128 minLength: 1 sourceAccount: type: string maxLength: 64 minLength: 1 producerId: type: string maxLength: 128 minLength: 1 reason: type: string enum: - INCOMPLETE - QUEUE_FULL - OBSERVER_FAILED - SHUTDOWN required: - diagnosticSessionId - sourceAccount - producerId - reason Observation: type: object additionalProperties: false properties: status: type: string maxLength: 32 minLength: 1 nullable: true outboundTime: type: string maxLength: 64 minLength: 1 nullable: true observedAt: type: string format: date-time attemptId: type: string maxLength: 128 minLength: 1 skuSetComplete: type: boolean required: - status - outboundTime - observedAt - attemptId - skuSetComplete Sku: type: object additionalProperties: false properties: sku: type: string maxLength: 128 minLength: 1 listQty: type: number nullable: true minimum: 0 description: Up to 32 integer digits, at most 6 decimal places; unknown stays null. forecastQty: type: number nullable: true minimum: 0 description: Up to 32 integer digits, at most 6 decimal places; unknown stays null. actualQty: type: number nullable: true minimum: 0 description: Up to 32 integer digits, at most 6 decimal places; unknown stays null. required: - sku - listQty - forecastQty - actualQty Key: type: object additionalProperties: false properties: warehouseCode: type: string maxLength: 64 minLength: 1 ownerCode: type: string maxLength: 128 minLength: 1 orderNo: type: string maxLength: 128 minLength: 1 paired: type: boolean required: - warehouseCode - ownerCode - orderNo - paired Event: type: object additionalProperties: false properties: diagnosticSessionId: type: string maxLength: 128 minLength: 1 sourceAccount: type: string maxLength: 64 minLength: 1 producerId: type: string maxLength: 128 minLength: 1 rootTaskId: type: string maxLength: 128 minLength: 1 collectionSessionId: type: string maxLength: 128 minLength: 1 operation: type: string enum: - OUTBOUND_QUERY - OUTBOUND_DETAIL warehouseCode: type: string maxLength: 64 minLength: 1 ownerCode: type: string maxLength: 128 minLength: 1 orderNo: type: string maxLength: 128 minLength: 1 side: type: string enum: - LIST - DETAIL observation: $ref: '#/components/schemas/Observation' skus: type: array maxItems: 200 items: $ref: '#/components/schemas/Sku' description: Empty allowed only when skuSetComplete=false; persists inconclusive evidence. required: - diagnosticSessionId - sourceAccount - producerId - rootTaskId - collectionSessionId - operation - warehouseCode - ownerCode - orderNo - side - observation - skus View: type: object additionalProperties: false properties: diagnosticSessionId: type: string maxLength: 128 minLength: 1 sourceAccount: type: string maxLength: 64 minLength: 1 rootTaskId: type: string maxLength: 128 minLength: 1 nullable: true collectionSessionId: type: string maxLength: 128 minLength: 1 nullable: true state: type: string enum: - ARMED - BOUND - DRAINING - TERMINAL stopReason: type: string nullable: true startsAt: type: string format: date-time nullable: true expiresAt: type: string format: date-time nullable: true bindBefore: type: string format: date-time nullable: true warehouseCodes: type: array maxItems: 8 items: type: string maxLength: 64 minLength: 1 ownerCode: type: string maxLength: 128 minLength: 1 excludedRootTaskId: type: string maxLength: 128 minLength: 1 nullable: true candidates: type: integer minimum: 0 maximum: 100 pairedOrders: type: integer minimum: 0 maximum: 100 retainedRows: type: integer minimum: 0 maximum: 2000 retainedBytes: type: integer minimum: 0 maximum: 2097152 deliveryUncertain: type: boolean selected: type: array maxItems: 100 items: $ref: '#/components/schemas/Key' required: - diagnosticSessionId - sourceAccount - rootTaskId - collectionSessionId - state - stopReason - startsAt - expiresAt - bindBefore - warehouseCodes - ownerCode - excludedRootTaskId - candidates - pairedOrders - retainedRows - retainedBytes - deliveryUncertain - selected Receipt: type: object additionalProperties: false properties: outcome: type: string enum: - ACCEPTED - IGNORED - DUPLICATE - STOPPED comparison: type: string nullable: true enum: - ALL_EQUAL - QUANTITY_DIFFERENCE - INCONCLUSIVE session: $ref: '#/components/schemas/View' required: - outcome - comparison - session