{"openapi":"3.1.0","info":{"title":"JWT Authentication API","description":"This is a sample JWT authentication service.","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0"},"servers":[{"url":"https://awesome.byst.re","description":"Generated server url"}],"tags":[{"name":"Inventory","description":"Administrator inventory management endpoints"},{"name":"ollama","description":"Ollama endpoints"},{"name":"Cart","description":"Shopping cart management endpoints"},{"name":"Products","description":"Product management endpoints"},{"name":"Orders","description":"Order management endpoints"},{"name":"QR","description":"Endpoint for QR code generation"},{"name":"two-factor authentication","description":"TOTP enrollment and two-factor sign-in"},{"name":"users","description":"User management endpoints"},{"name":"password-reset","description":"Password recovery endpoints"},{"name":"email-events","description":"Authenticated email event visibility"},{"name":"Traffic Monitoring","description":"Endpoints for HTTP traffic monitoring"},{"name":"email","description":"Email sending endpoints"}],"paths":{"/api/v1/users/{username}":{"get":{"tags":["users"],"summary":"Get user by username","description":"Returns public account details for the requested username.","operationId":"getByUsername","parameters":[{"name":"username","in":"path","description":"Username","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"User details","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"The user doesn't exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["users"],"summary":"Update user","description":"Updates editable profile fields for an existing user. Users may edit themselves; administrators may edit any user.","operationId":"edit","parameters":[{"name":"username","in":"path","description":"Username","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserEditDto"}}},"required":true},"responses":{"200":{"description":"User was updated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserEntity"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"The user doesn't exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["users"],"summary":"Delete user","description":"Deletes a user account and user-owned data. Requires an administrator role.","operationId":"delete","parameters":[{"name":"username","in":"path","description":"Username","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"User was deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"The user doesn't exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/tool-system-prompt":{"get":{"tags":["users"],"summary":"Get your tool system prompt","description":"Returns the authenticated user's tool-calling prompt override, or the default prompt when no override is stored.","operationId":"getToolSystemPrompt","responses":{"200":{"description":"Tool system prompt retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ToolSystemPromptDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["users"],"summary":"Update your tool system prompt","description":"Stores a new tool-calling prompt override for the authenticated user. Null, an omitted field, or an empty string resets the override; PUT echoes the stored value and GET returns the effective default.","operationId":"updateToolSystemPrompt","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolSystemPromptDto"}}},"required":true},"responses":{"200":{"description":"Tool system prompt was updated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ToolSystemPromptDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/chat-system-prompt":{"get":{"tags":["users"],"summary":"Get your chat system prompt","description":"Returns the authenticated user's chat prompt override, or the default prompt when no override is stored.","operationId":"getChatSystemPrompt","responses":{"200":{"description":"Chat system prompt retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ChatSystemPromptDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["users"],"summary":"Update your chat system prompt","description":"Stores a new chat prompt override for the authenticated user. Null, an omitted field, or an empty string resets the override; PUT echoes the stored value and GET returns the effective default.","operationId":"updateChatSystemPrompt","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatSystemPromptDto"}}},"required":true},"responses":{"200":{"description":"Chat system prompt was updated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ChatSystemPromptDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/products/{id}":{"get":{"tags":["Products"],"summary":"Get product by ID","description":"Returns one product by numeric identifier, or 404 when the product does not exist.","operationId":"getProductById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Successfully retrieved product","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProductDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["Products"],"summary":"Update existing product","description":"Updates supplied non-null product fields; omitted or null fields are unchanged. Empty description and imageUrl are allowed. Requires an administrator role.","operationId":"updateProduct","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductUpdateDto"}}},"required":true},"responses":{"200":{"description":"Product updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProductDto"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Products"],"summary":"Delete product","description":"Deletes an existing product by identifier. Requires an administrator role.","operationId":"deleteProduct","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"204":{"description":"Product deleted successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found; empty response body"}},"security":[{"bearerAuth":[]}]}},"/api/v1/orders/{id}/status":{"put":{"tags":["Orders"],"summary":"Update order status (Admin only)","description":"Sets the supplied status using administrator privileges. CANCELLED is allowed only from PENDING or PAID and restores deducted stock; other status values are assigned directly.","operationId":"updateOrderStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"string","enum":["PENDING","PAID","SHIPPED","DELIVERED","CANCELLED"]}}},"required":true},"responses":{"200":{"description":"Order status updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/OrderDto"}}}},"400":{"description":"Invalid status transition","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/cart/items/{productId}":{"put":{"tags":["Cart"],"summary":"Update item quantity","description":"Sets the quantity for a product already in the authenticated user's cart. Quantity zero removes the item.","operationId":"updateCartItem","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCartItemDto"}}},"required":true},"responses":{"200":{"description":"Item quantity updated successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/CartDto"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Cart item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"Requested quantity exceeds available stock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Cart"],"summary":"Remove item from cart","description":"Removes a product from the authenticated user's cart and returns the updated cart.","operationId":"removeFromCart","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Item removed successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/CartDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Cart item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/sso/exchange":{"post":{"tags":["users"],"summary":"Exchange a valid OIDC ID token for an app JWT token pair","description":"Verifies an external OIDC ID token, provisions or updates the matching user, and returns application tokens.","operationId":"exchange","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SsoExchangeRequestDto"}}},"required":true},"responses":{"200":{"description":"Successfully authenticated with SSO","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponseDto"}}}},"400":{"description":"Field validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Invalid SSO token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"SSO login is disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"SSO identity conflicts with an existing local account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/signup":{"post":{"tags":["users"],"summary":"Create a new user account","description":"Registers a local user account with client privileges after validating the signup payload.","operationId":"signup","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegisterDto"}}},"required":true},"responses":{"201":{"description":"User was successfully created"},"400":{"description":"Field validation failed, or username/email is already in use","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Invalid or expired Bearer token; omit stale Authorization headers on this public endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/signin":{"post":{"tags":["users"],"summary":"Authenticate user and return JWT token","description":"Authenticates local credentials. When mfaRequired is false, returns access and refresh tokens with null challenge fields. When true, returns an MFA challenge and expiration with null tokens; complete POST /api/v1/users/signin/2fa to obtain tokens.","operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}},"required":true},"responses":{"200":{"description":"Successfully authenticated","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponseDto"}}}},"400":{"description":"Field validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Invalid or expired Bearer token; omit stale Authorization headers on this public endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"422":{"description":"Invalid username/password supplied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/signin/2fa":{"post":{"tags":["two-factor authentication"],"summary":"Complete sign-in with a second factor","description":"Consumes a short-lived password challenge and a TOTP or recovery code, then issues tokens.","operationId":"completeSignIn","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaChallengeRequestDto"}}},"required":true},"responses":{"200":{"description":"Sign-in completed","content":{"*/*":{"schema":{"$ref":"#/components/schemas/LoginResponseDto"}}}},"400":{"description":"Field validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Challenge or second factor is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/refresh":{"post":{"tags":["users"],"summary":"Refresh JWT token using refresh token","description":"Rotates a valid refresh token and returns a fresh access token plus replacement refresh token.","operationId":"refresh","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenRequestDto"}}},"required":true},"responses":{"200":{"description":"New JWT and refresh tokens","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TokenRefreshResponseDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Invalid refresh token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/password/reset":{"post":{"tags":["password-reset"],"summary":"Complete password reset with a valid token","description":"Validates a password reset token, updates the user's password, and revokes existing refresh tokens.","operationId":"resetPassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequestDto"}}},"required":true},"responses":{"200":{"description":"Password reset successful"},"400":{"description":"Invalid token or payload","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Invalid or expired Bearer token; omit stale Authorization headers on these public endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/password/forgot":{"post":{"tags":["password-reset"],"summary":"Start password reset flow","description":"Accepts a username or email and queues reset instructions when a matching local account exists.","operationId":"forgotPassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequestDto"}}},"required":true},"responses":{"202":{"description":"Request accepted whether or not a matching account exists","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ForgotPasswordResponseDto"}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Invalid or expired Bearer token; omit stale Authorization headers on these public endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/users/logout":{"post":{"tags":["users"],"summary":"Logout user and revoke refresh token","description":"Revokes all refresh tokens for the authenticated user.","operationId":"logout","responses":{"200":{"description":"Successfully logged out"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/2fa/setup":{"post":{"tags":["two-factor authentication"],"summary":"Start authenticator enrollment","description":"Creates a pending TOTP secret and returns its manual key and QR code.","operationId":"setup","responses":{"200":{"description":"Pending setup created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MfaSetupResponseDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Account no longer exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"MFA is already enabled or provider-managed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/2fa/recovery-codes":{"post":{"tags":["two-factor authentication"],"summary":"Replace recovery codes","description":"Requires the current password and a fresh TOTP, then invalidates all previous recovery codes.","operationId":"replaceRecoveryCodes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaProtectedActionRequestDto"}}},"required":true},"responses":{"200":{"description":"Replacement recovery codes created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MfaRecoveryCodesResponseDto"}}}},"400":{"description":"Field validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Authenticator code or Bearer token is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Account no longer exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"MFA is not enabled or is provider-managed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"422":{"description":"Current password is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/2fa/disable":{"post":{"tags":["two-factor authentication"],"summary":"Disable two-factor authentication","description":"Requires the current password and a TOTP or recovery code, then revokes refresh tokens.","operationId":"disable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaProtectedActionRequestDto"}}},"required":true},"responses":{"200":{"description":"MFA disabled"},"400":{"description":"Field validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Second factor or Bearer token is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Account no longer exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"MFA is not enabled or is provider-managed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"422":{"description":"Current password is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/2fa/confirm":{"post":{"tags":["two-factor authentication"],"summary":"Confirm authenticator enrollment","description":"Verifies the first TOTP, enables MFA, and returns one-time recovery codes.","operationId":"confirm","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaCodeRequestDto"}}},"required":true},"responses":{"200":{"description":"MFA enabled and recovery codes created","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MfaRecoveryCodesResponseDto"}}}},"400":{"description":"Field validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Authenticator code is invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Account no longer exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"Setup is missing, MFA is already enabled, or it is provider-managed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"410":{"description":"Pending setup expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/qr/create":{"post":{"tags":["QR"],"summary":"Generate QR code","description":"Generates a PNG QR code for the supplied text payload.","operationId":"createQrCode","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQrDto"}}},"required":true},"responses":{"200":{"description":"Successfully generated QR code","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/products":{"get":{"tags":["Products"],"summary":"Get all products","description":"Returns the complete product catalog visible to authenticated clients.","operationId":"getAllProducts","responses":{"200":{"description":"Successfully retrieved products","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductDto"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Products"],"summary":"Create new product","description":"Creates a catalog product from the supplied payload. Requires an administrator role.","operationId":"createProduct","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreateDto"}}},"required":true},"responses":{"201":{"description":"Product created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/ProductDto"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/orders":{"get":{"tags":["Orders"],"summary":"Get user's orders","description":"Returns the authenticated user's orders with optional status filtering and pagination.","operationId":"getUserOrders","parameters":[{"name":"page","in":"query","description":"Zero-based page index","required":false,"schema":{"type":"string","minimum":0}},{"name":"size","in":"query","description":"Page size, at least one","required":false,"schema":{"type":"string","minimum":1}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["PENDING","PAID","SHIPPED","DELIVERED","CANCELLED"]}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageDtoOrderDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Orders"],"summary":"Create a new order from cart","description":"Creates an order for the authenticated user from the current cart and clears the cart after success.","operationId":"createOrder","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressDto"}}},"required":true},"responses":{"201":{"description":"Order created successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/OrderDto"}}}},"400":{"description":"Invalid input or empty cart","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"A cart product no longer exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"Insufficient stock to place the order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/orders/{id}/cancel":{"post":{"tags":["Orders"],"summary":"Cancel order","description":"Cancels an order when its current status allows cancellation. Clients may cancel only their own orders. Only PENDING and PAID orders can be cancelled.","operationId":"cancelOrder","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Order cancelled successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/OrderDto"}}}},"400":{"description":"Order cannot be cancelled","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/ollama/generate":{"post":{"tags":["ollama"],"summary":"Generate text using Ollama model","description":"Streams generated text chunks from the configured Ollama backend for a single prompt. Upstream errors before the stream starts preserve their HTTP status and JSON body; failures after streaming begins may terminate the stream.","operationId":"generateText","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamedRequestDto"}}},"required":true},"responses":{"200":{"description":"One JSON GenerateResponseDto per SSE data event","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/GenerateResponseDto"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ModelNotFoundDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelNotFoundDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"Upstream server failure; JSON body is passed through before streaming starts","content":{"application/json":{"schema":{"type":["object","array","string","number","boolean","null"]}}}},"default":{"description":"Other upstream HTTP failures before streaming starts retain their status and JSON body","content":{"application/json":{"schema":{"type":["object","array","string","number","boolean","null"]}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/ollama/chat":{"post":{"tags":["ollama"],"summary":"Chat with Ollama model (stateless endpoint)","description":"Streams responses and expects the caller to manage the entire conversation history client-side.","operationId":"chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequestDto"}}},"required":true},"responses":{"200":{"description":"One JSON ChatResponseDto per SSE data event","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/ChatResponseDto"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ModelNotFoundDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelNotFoundDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"Upstream server failure; JSON body is passed through before streaming starts","content":{"application/json":{"schema":{"type":["object","array","string","number","boolean","null"]}}}},"default":{"description":"Other upstream HTTP failures before streaming starts retain their status and JSON body","content":{"application/json":{"schema":{"type":["object","array","string","number","boolean","null"]}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/ollama/chat/tools":{"post":{"tags":["ollama"],"summary":"Chat with Ollama using backend function calling (legacy stateless endpoint)","description":"Available tools: get_product_snapshot, list_products.\nUse GET /api/v1/ollama/chat/tools/definitions for the full JSON schema.\nThis endpoint requires the caller to resend the full conversation on every request.\nSmall local models stay grounded only when they keep everything in the product lane—always snapshot a SKU first and follow up with list_products if it needs comparisons.","operationId":"chatWithTools","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequestDto"}}},"required":true},"responses":{"200":{"description":"One JSON ChatResponseDto per SSE data event","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/ChatResponseDto"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/ModelNotFoundDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Upstream model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelNotFoundDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"Upstream server failure; JSON body is passed through before streaming starts","content":{"application/json":{"schema":{"type":["object","array","string","number","boolean","null"]}}}},"default":{"description":"Other upstream HTTP failures before streaming starts retain their status and JSON body","content":{"application/json":{"schema":{"type":["object","array","string","number","boolean","null"]}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/email":{"post":{"tags":["email"],"summary":"Send email","description":"Queues an email message for asynchronous delivery through the configured JMS destination.","operationId":"sendEmail","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDto"}}},"required":true},"responses":{"200":{"description":"Email queued; delivery is asynchronous"},"400":{"description":"Invalid email data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/cart/items":{"post":{"tags":["Cart"],"summary":"Add item to cart","description":"Adds a product to the authenticated user's cart or increases the quantity of an existing cart item.","operationId":"addToCart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartItemDto"}}},"required":true},"responses":{"200":{"description":"Item added successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/CartDto"}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"Requested quantity exceeds available stock","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/admin/inventory/{productId}/adjustments":{"post":{"tags":["Inventory"],"summary":"Adjust inventory","description":"Applies a nonzero inventory delta. Repeating requestId with the same product, delta and reason returns the original movement with 201; changing delta or reason returns 409.","operationId":"adjust","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAdjustmentDto"}}},"required":true},"responses":{"201":{"description":"Adjustment recorded","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InventoryMovementDto"}}}},"400":{"description":"Invalid adjustment or product identifier","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"409":{"description":"Insufficient stock, quantity overflow, or requestId reused with different delta/reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users":{"get":{"tags":["users"],"summary":"Get all users","description":"Returns all user accounts visible to the authenticated caller.","operationId":"getAll","responses":{"200":{"description":"List of users","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/me":{"get":{"tags":["users"],"summary":"Get current user information","description":"Returns account details for the authenticated user resolved from the JWT token.","operationId":"whoAmI","responses":{"200":{"description":"Current user details","content":{"*/*":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/me/email-events":{"get":{"tags":["email-events"],"summary":"Get recent email events for the current user","description":"Returns the latest email events recorded for the authenticated user. Statuses reflect handoff to the Mailhog-backed test sink, not real-world inbox delivery.","operationId":"getMyEmailEvents","responses":{"200":{"description":"Recent email events returned successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailEventDto"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/2fa/status":{"get":{"tags":["two-factor authentication"],"summary":"Get two-factor authentication status","description":"Returns enrollment state and the number of unused recovery codes.","operationId":"status","responses":{"200":{"description":"Status returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/MfaStatusResponseDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/traffic/logs":{"get":{"tags":["Traffic Monitoring"],"summary":"Get paginated HTTP traffic logs","description":"Returns captured HTTP traffic logs with optional filters for session, method, status, path, text, and time range.","operationId":"getTrafficLogs","parameters":[{"name":"page","in":"query","description":"Zero-based page index","required":false,"schema":{"type":"string","minimum":0}},{"name":"size","in":"query","description":"Page size, clamped to 1 through the configured app.traffic.max-page-size","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"X-Client-Session-Id","in":"header","description":"Session identifier, trimmed before validation: 16–128 ASCII letters, digits, underscores or hyphens. Required unless legacy public access is enabled.","required":false,"schema":{"type":"string"}},{"name":"method","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"pathContains","in":"query","required":false,"schema":{"type":"string"}},{"name":"text","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","description":"Inclusive lower timestamp bound as an ISO-8601 instant with offset; blank means no lower bound","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"Inclusive upper timestamp bound as an ISO-8601 instant with offset; blank means no upper bound","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully returned traffic logs","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageDtoTrafficLogEntryDto"}}}},"400":{"description":"Invalid session header, pagination or time filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized or invalid Bearer token; authentication is required unless legacy public access is enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[]}},"/api/v1/traffic/logs/{correlationId}":{"get":{"tags":["Traffic Monitoring"],"summary":"Get traffic log by correlation identifier","description":"Returns one captured HTTP traffic log entry using its correlation identifier.","operationId":"getTrafficLog","parameters":[{"name":"correlationId","in":"path","required":true,"schema":{"type":"string"}},{"name":"X-Client-Session-Id","in":"header","description":"Session identifier, trimmed before validation: 16–128 ASCII letters, digits, underscores or hyphens. Required unless legacy public access is enabled.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully returned traffic log","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TrafficLogEntryDto"}}}},"400":{"description":"Invalid session header, pagination or time filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized or invalid Bearer token; authentication is required unless legacy public access is enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Traffic log not found; empty response body"}},"security":[]}},"/api/v1/traffic/info":{"get":{"tags":["Traffic Monitoring"],"summary":"Get traffic monitoring information","description":"Returns WebSocket connection information. X-Client-Session-Id is required unless legacy public access is enabled; after trimming it must contain 16–128 letters, digits, underscores or hyphens.","operationId":"getTrafficInfo","parameters":[{"name":"X-Client-Session-Id","in":"header","description":"Session identifier, trimmed before validation: 16–128 ASCII letters, digits, underscores or hyphens. Required unless legacy public access is enabled.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully returned info","content":{"*/*":{"schema":{"$ref":"#/components/schemas/TrafficInfoDto"}}}},"400":{"description":"Invalid session header, pagination or time filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorsDto"}}}},"401":{"description":"Unauthorized or invalid Bearer token; authentication is required unless legacy public access is enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[]}},"/api/v1/orders/{id}":{"get":{"tags":["Orders"],"summary":"Get order by ID","description":"Returns a single order. Administrators may access any order; clients may access only their own orders.","operationId":"getOrder","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Order retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/OrderDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/orders/admin":{"get":{"tags":["Orders"],"summary":"Get all orders (Admin only)","description":"Returns all orders in the system with optional status filtering and pagination. Requires an administrator role.","operationId":"getAllOrders","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["PENDING","PAID","SHIPPED","DELIVERED","CANCELLED"]}},{"name":"page","in":"query","description":"Zero-based page index","required":false,"schema":{"type":"string","minimum":0}},{"name":"size","in":"query","description":"Page size, at least one","required":false,"schema":{"type":"string","minimum":1}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageDtoOrderDto"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ValidationErrorsDto"},{"$ref":"#/components/schemas/ErrorDto"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/ollama/chat/tools/definitions":{"get":{"tags":["ollama"],"summary":"List tool definitions supported by /api/v1/ollama/chat/tools","description":"Returns the backend function-calling tool schemas that clients can send to the tool-enabled chat endpoint.","operationId":"getToolDefinitions","responses":{"200":{"description":"Available tool definitions returned successfully","content":{"*/*":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OllamaToolDefinitionDto"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/cart":{"get":{"tags":["Cart"],"summary":"Get current user's cart","description":"Returns the authenticated user's cart, including item count and calculated total price.","operationId":"getCart","responses":{"200":{"description":"Successfully retrieved cart","content":{"*/*":{"schema":{"$ref":"#/components/schemas/CartDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Cart"],"summary":"Clear cart","description":"Removes all items from the authenticated user's cart.","operationId":"clearCart","responses":{"204":{"description":"Cart cleared successfully"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/admin/inventory":{"get":{"tags":["Inventory"],"summary":"List inventory","description":"Lists inventory with optional stock and catalog filters. Negative page is clamped to zero; size is clamped to 1–100. lowStockThreshold must be at least 1.","operationId":"list","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"search","in":"query","required":false,"schema":{"type":"string"}},{"name":"category","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["IN_STOCK","LOW_STOCK","OUT_OF_STOCK"]}},{"name":"lowStockThreshold","in":"query","description":"Inclusive upper bound for LOW_STOCK; at least one","required":false,"schema":{"type":"string","minimum":1}}],"responses":{"200":{"description":"Inventory returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageDtoInventoryItemDto"}}}},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/admin/inventory/{productId}":{"get":{"tags":["Inventory"],"summary":"Get inventory item","description":"Returns the available quantity for one product.","operationId":"get","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"lowStockThreshold","in":"query","description":"Inclusive upper bound for LOW_STOCK; at least one","required":false,"schema":{"type":"string","minimum":1}}],"responses":{"200":{"description":"Inventory item returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/InventoryItemDto"}}}},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/admin/inventory/{productId}/movements":{"get":{"tags":["Inventory"],"summary":"List inventory movements","description":"Lists an inventory item's movement history newest first. Negative page is clamped to zero; size is clamped to 1–100.","operationId":"movements","parameters":[{"name":"productId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"Movement history returned","content":{"*/*":{"schema":{"$ref":"#/components/schemas/PageDtoInventoryMovementDto"}}}},"400":{"description":"Invalid parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}},"/api/v1/users/{username}/right-to-be-forgotten":{"delete":{"tags":["users"],"summary":"Delete user account and all user-owned data","description":"Deletes the user account together with refresh tokens, reset tokens, email events, cart items, and orders.","operationId":"forget","parameters":[{"name":"username","in":"path","description":"Username","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"User account and user-owned data were deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"The user doesn't exist","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}},"security":[{"bearerAuth":[]}]}}},"components":{"schemas":{"UserEditDto":{"type":"object","description":"User details","properties":{"email":{"type":"string","format":"email","description":"Email address","example":"john.doe@example.com","minLength":1,"pattern":"\\S"},"firstName":{"type":["string","null"],"description":"First name","example":"John","maxLength":255,"minLength":4},"lastName":{"type":["string","null"],"description":"Last name","example":"Boyd","maxLength":255,"minLength":4}},"required":["email"]},"ValidationErrorsDto":{"type":"object","additionalProperties":{"type":"string","description":"Validation messages keyed by field name; invalid arguments use the error key","example":{"email":"Email should be valid"}},"description":"Validation messages keyed by field name; invalid arguments use the error key","example":{"email":"Email should be valid"},"properties":{"empty":{"type":"boolean"}}},"ErrorDto":{"type":"object","additionalProperties":false,"properties":{"message":{"type":"string","description":"Error message","example":"Error message"}},"required":["message"]},"UserEntity":{"type":"object","properties":{"id":{"type":"integer","format":"int32"},"username":{"type":"string","maxLength":255,"minLength":4},"email":{"type":"string"},"authProvider":{"type":["string","null"],"maxLength":100,"minLength":0},"providerSubject":{"type":["string","null"],"maxLength":255,"minLength":0},"emailVerified":{"type":["boolean","null"]},"roles":{"type":"array","items":{"type":"string","enum":["ROLE_ADMIN","ROLE_CLIENT"]}},"firstName":{"type":["string","null"],"maxLength":255,"minLength":0},"lastName":{"type":["string","null"],"maxLength":255,"minLength":0},"chatSystemPrompt":{"type":["string","null"],"maxLength":5000,"minLength":0},"toolSystemPrompt":{"type":["string","null"],"maxLength":5000,"minLength":0}}},"ToolSystemPromptDto":{"type":"object","description":"Tool system prompt","properties":{"toolSystemPrompt":{"type":["string","null"],"description":"Null, omitted, or empty resets the override. Tool-specific system prompt for function calling","example":"Always call get_product_snapshot before answering.","maxLength":5000,"minLength":0}}},"ChatSystemPromptDto":{"type":"object","description":"Chat system prompt","properties":{"chatSystemPrompt":{"type":["string","null"],"description":"Null, omitted, or empty resets the override. General chat system prompt","example":"You are a helpful assistant.","maxLength":5000,"minLength":0}}},"ProductUpdateDto":{"type":"object","description":"Update product data transfer object","properties":{"name":{"type":["string","null"],"description":"Product name","example":"iPhone 13","maxLength":100,"minLength":3},"description":{"type":["string","null"],"description":"Product description","example":"Latest iPhone model with A15 Bionic chip","maxLength":1000,"minLength":0},"price":{"type":["number","null"],"description":"Product price with at most 8 integer digits and 2 fractional digits","example":999.99,"maximum":99999999.99,"minimum":0.01,"multipleOf":0.01},"stockQuantity":{"type":["integer","null"],"format":"int32","description":"Available stock quantity","example":100,"minimum":0},"category":{"type":["string","null"],"description":"Product category","example":"Electronics"},"imageUrl":{"type":["string","null"],"description":"Product image URL","example":"https://example.com/iphone13.jpg","pattern":"^(https?://.*|)$"}}},"ProductDto":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string"},"price":{"type":"number"},"stockQuantity":{"type":"integer","format":"int32"},"category":{"type":"string"},"imageUrl":{"type":["string","null"]},"createdAt":{"type":"string","format":"local-date-time","description":"Server local date and time without an offset. The server timezone is deployment-dependent; this value does not identify an absolute instant.","example":"2026-09-10T10:30:02.809462"},"updatedAt":{"type":"string","format":"local-date-time","description":"Server local date and time without an offset. The server timezone is deployment-dependent; this value does not identify an absolute instant.","example":"2026-09-10T10:30:02.809462"}}},"AddressDto":{"type":"object","description":"Address data transfer object","properties":{"street":{"type":"string","description":"Street address","example":"123 Main St","minLength":1,"pattern":"\\S"},"city":{"type":"string","description":"City","example":"New York","minLength":1,"pattern":"\\S"},"state":{"type":"string","description":"State","example":"NY","minLength":1,"pattern":"\\S"},"zipCode":{"type":"string","description":"Postal/ZIP code","example":"35-119","minLength":1,"pattern":"^[0-9]{2}(-[0-9]{3})?|[0-9]{5}(-[0-9]{4})?$"},"country":{"type":"string","description":"Country","example":"Poland","minLength":1,"pattern":"\\S"}},"required":["city","country","state","street","zipCode"]},"OrderDto":{"type":"object","description":"Order data transfer object","properties":{"id":{"type":"integer","format":"int64","description":"Order ID","example":1},"username":{"type":"string","description":"Username","example":"john.doe"},"items":{"type":"array","description":"Order items","items":{"$ref":"#/components/schemas/OrderItemDto"}},"totalAmount":{"type":"number","description":"Total amount","example":1999.98},"status":{"type":"string","description":"Order status","enum":["PENDING","PAID","SHIPPED","DELIVERED","CANCELLED"],"example":"PENDING"},"shippingAddress":{"$ref":"#/components/schemas/AddressDto","description":"Shipping address"},"createdAt":{"type":"string","format":"local-date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"local-date-time","description":"Last update timestamp"}},"required":["shippingAddress"]},"OrderItemDto":{"type":"object","description":"Order item data transfer object","properties":{"id":{"type":"integer","format":"int64","description":"Order item ID","example":1},"productId":{"type":"integer","format":"int64","description":"Product ID","example":1},"quantity":{"type":"integer","format":"int32","description":"Quantity","example":2,"minimum":1},"productName":{"type":"string","description":"Product name","example":"iPhone 13 Pro"},"unitPrice":{"type":"number","description":"Unit price","example":999.99},"totalPrice":{"type":"number","description":"Total price","example":1999.98}},"required":["productId","quantity"]},"UpdateCartItemDto":{"type":"object","properties":{"quantity":{"type":"integer","format":"int32","description":"Product quantity","example":1,"minimum":0}},"required":["quantity"]},"CartDto":{"type":"object","properties":{"username":{"type":"string","description":"Cart owner","example":"admin"},"items":{"type":"array","items":{"$ref":"#/components/schemas/CartItemDto"}},"totalPrice":{"type":"number","description":"Total Cart price","example":199.56},"totalItems":{"type":"integer","format":"int32","description":"Total number of items","example":7}}},"CartItemDto":{"type":"object","properties":{"productId":{"type":"integer","format":"int64","description":"Product id","example":13},"quantity":{"type":"integer","format":"int32","description":"Product quantity","example":1,"minimum":1}},"required":["productId","quantity"]},"SsoExchangeRequestDto":{"type":"object","description":"SSO exchange request","properties":{"idToken":{"type":"string","description":"OIDC ID token returned by the configured identity provider","minLength":1,"pattern":"\\S"}},"required":["idToken"]},"LoginResponseDto":{"type":"object","properties":{"token":{"type":["string","null"],"description":"JWT token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"refreshToken":{"type":["string","null"],"description":"Refresh token"},"username":{"type":"string","description":"Username","example":"johndoe"},"email":{"type":"string","description":"Email address","example":"john.doe@example.com"},"firstName":{"type":["string","null"],"description":"First name","example":"John"},"lastName":{"type":["string","null"],"description":"Last name","example":"Doe"},"roles":{"type":"array","description":"User roles","example":["ROLE_CLIENT"],"items":{"type":"string","enum":["ROLE_ADMIN","ROLE_CLIENT"]}},"mfaRequired":{"type":"boolean","description":"Whether a second factor is required before tokens can be issued"},"challengeToken":{"type":["string","null"],"description":"Short-lived, single-use MFA challenge token"},"challengeExpiresAt":{"type":["string","null"],"format":"date-time","description":"MFA challenge expiration time"}}},"UserRegisterDto":{"type":"object","description":"Signup User","properties":{"username":{"type":"string","description":"Username","example":"johndoe","maxLength":255,"minLength":4},"email":{"type":"string","format":"email","description":"Email address","example":"john.doe@example.com"},"password":{"type":"string","description":"Password","example":"password123","maxLength":255,"minLength":8},"firstName":{"type":"string","description":"First name","example":"John","maxLength":255,"minLength":4},"lastName":{"type":"string","description":"Last name","example":"Boyd","maxLength":255,"minLength":4}},"required":["email","firstName","lastName","password","username"]},"LoginDto":{"type":"object","description":"Login details","properties":{"username":{"type":"string","description":"Username","example":"admin","maxLength":255,"minLength":4},"password":{"type":"string","description":"Password","example":"admin","maxLength":255,"minLength":4}}},"MfaChallengeRequestDto":{"type":"object","properties":{"challengeToken":{"type":"string","description":"Short-lived challenge returned after password verification","maxLength":255,"minLength":1,"pattern":"\\S"},"code":{"type":"string","description":"Six-digit authenticator code or one-time recovery code","maxLength":32,"minLength":6,"pattern":"\\S"}},"required":["challengeToken","code"]},"RefreshTokenRequestDto":{"type":"object","properties":{"refreshToken":{"type":"string","description":"Refresh token obtained during login","minLength":1,"pattern":"\\S"}},"required":["refreshToken"]},"TokenRefreshResponseDto":{"type":"object","properties":{"token":{"type":"string","description":"Fresh JWT access token"},"refreshToken":{"type":"string","description":"Rotated refresh token"}}},"ResetPasswordRequestDto":{"type":"object","properties":{"token":{"type":"string","description":"Password reset token received via email","minLength":1,"pattern":"\\S"},"newPassword":{"type":"string","description":"New password","example":"password123","maxLength":2147483647,"minLength":8,"pattern":"\\S"},"confirmPassword":{"type":"string","description":"Confirmation of the new password","example":"password123","minLength":1,"pattern":"\\S"}},"required":["confirmPassword","newPassword","token"]},"ForgotPasswordRequestDto":{"type":"object","properties":{"identifier":{"type":"string","description":"Username or email address associated with the account","example":"client","minLength":1,"pattern":"\\S"}},"required":["identifier"]},"ForgotPasswordResponseDto":{"type":"object","properties":{"message":{"type":"string","description":"Human readable status message"},"token":{"type":["string","null"],"description":"Raw password reset token only when password-reset.expose-token-in-response is enabled and a local account matches; otherwise null"}}},"MfaSetupResponseDto":{"type":"object","properties":{"secret":{"type":"string","description":"Manual Base32 setup key"},"otpAuthUri":{"type":"string","description":"Standard OTPAuth URI"},"qrCodeDataUri":{"type":"string","description":"PNG QR code encoded as a data URI"},"expiresAt":{"type":"string","format":"date-time","description":"Time at which this unconfirmed setup expires"}}},"MfaProtectedActionRequestDto":{"type":"object","properties":{"password":{"type":"string","description":"Current account password","maxLength":255,"minLength":1,"pattern":"\\S"},"code":{"type":"string","description":"Six-digit authenticator code or one-time recovery code","maxLength":32,"minLength":6,"pattern":"\\S"}},"required":["code","password"]},"MfaRecoveryCodesResponseDto":{"type":"object","properties":{"recoveryCodes":{"type":"array","description":"One-time recovery codes. These are returned only when created.","items":{"type":"string"}}}},"MfaCodeRequestDto":{"type":"object","properties":{"code":{"type":"string","description":"Six-digit code from an authenticator app","example":"123456","minLength":1,"pattern":"\\d{6}"}},"required":["code"]},"CreateQrDto":{"type":"object","description":"QR link","properties":{"text":{"type":"string","description":"Text to use in QR code","example":"https://awesome-testing.com","minLength":1,"pattern":"\\S"}},"required":["text"]},"ProductCreateDto":{"type":"object","description":"Create product data transfer object","properties":{"name":{"type":"string","description":"Product name","example":"iPhone 13","maxLength":100,"minLength":3,"pattern":"\\S"},"description":{"type":"string","description":"Nonblank product description required on creation; updates may use an empty description","example":"Latest iPhone model with A15 Bionic chip","maxLength":1000,"minLength":1,"pattern":"\\S"},"price":{"type":"number","description":"Product price with at most 8 integer digits and 2 fractional digits","example":999.99,"maximum":99999999.99,"minimum":0.01,"multipleOf":0.01},"stockQuantity":{"type":"integer","format":"int32","description":"Available stock quantity","example":100,"minimum":0},"category":{"type":"string","description":"Product category","example":"Electronics","minLength":1,"pattern":"\\S"},"imageUrl":{"type":["string","null"],"description":"Product image URL","example":"https://example.com/iphone13.jpg","pattern":"^(https?://.*|)$"}},"required":["category","description","name","price","stockQuantity"]},"StreamedRequestDto":{"type":"object","properties":{"model":{"type":"string","description":"Model to use, needs to be available on the Ollama server.","example":"qwen3.5:2b","minLength":1,"pattern":"\\S"},"prompt":{"type":"string","description":"Prompt","example":"Hello, how are you?","minLength":1,"pattern":"\\S"},"options":{"type":"object","additionalProperties":{},"description":"Options","example":{"temperature":0.5}},"think":{"type":"boolean","description":"Should the model think before responding?","example":false}},"required":["model","prompt"]},"GenerateResponseDto":{"type":"object","properties":{"model":{"type":["string","null"]},"response":{"type":["string","null"]},"thinking":{"type":["string","null"]},"done":{"type":"boolean"},"context":{"type":["array","null"],"items":{"type":"integer","format":"int64"}},"created_at":{"type":["string","null"]},"total_duration":{"type":["integer","null"],"format":"int64"}}},"ErrorResponse":{"type":"object","properties":{"status":{"type":"integer","format":"int32"},"message":{"type":"string"},"timestamp":{"type":"string"}}},"ModelNotFoundDto":{"type":"object","properties":{"error":{"type":"string","description":"Missing model error. You need to pull it","example":"model 'X' not found"}}},"ChatMessageDto":{"type":"object","properties":{"role":{"type":"string","minLength":1,"pattern":"^(system|user|assistant|tool)$"},"content":{"type":["string","null"]},"thinking":{"type":["string","null"]},"contentOrThinkingOrToolCallPresent":{"type":"boolean","description":"Computed validation: nonblank content or thinking, or nonempty tool_calls is required","readOnly":true},"toolNamePresentForToolRole":{"type":"boolean","description":"Computed validation: role tool requires a nonblank tool_name","readOnly":true},"tool_calls":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ToolCallDto"}},"tool_name":{"type":["string","null"]}},"required":["role"]},"ChatRequestDto":{"type":"object","properties":{"model":{"type":"string","description":"Model to use. Must be available on the Ollama server. Clients can override it per request.","example":"qwen3.5:2b","minLength":1,"pattern":"\\S"},"messages":{"type":"array","description":"Complete conversation history in chronological order.","example":[{"role":"system","content":"You are a helpful AI assistant. You must use the conversation history to answer questions."},{"role":"user","content":"I love programming in Python."},{"role":"assistant","content":"That's great! Python is a versatile and popular programming language. What do you enjoy most about Python programming?"},{"role":"user","content":"What programming language did I say I love?"}],"items":{"$ref":"#/components/schemas/ChatMessageDto"},"minItems":1},"options":{"type":"object","additionalProperties":{},"description":"Options","example":{"temperature":0.7}},"tools":{"type":"array","description":"Function/tool definitions available to the model.","items":{"$ref":"#/components/schemas/OllamaToolDefinitionDto"}},"think":{"type":"boolean","description":"Should the model think before responding?","example":false}},"required":["messages","model"]},"OllamaToolDefinitionDto":{"type":"object","properties":{"type":{"type":"string","description":"Type of the tool. Only 'function' is supported currently.","example":"function","minLength":1},"function":{"$ref":"#/components/schemas/OllamaToolFunctionDto","description":"Function metadata describing how Ollama should call the backend."}},"required":["function","type"]},"OllamaToolFunctionDto":{"type":"object","properties":{"name":{"type":"string","description":"Function name exposed to the model","example":"get_product_snapshot","minLength":1,"pattern":"\\S"},"description":{"type":"string","description":"Short human-readable description","example":"Return catalog metadata for a product"},"parameters":{"$ref":"#/components/schemas/OllamaToolParametersDto","description":"JSON schema describing the function arguments"}},"required":["name","parameters"]},"OllamaToolParametersDto":{"type":"object","properties":{"type":{"type":"string","description":"JSON schema type. Usually 'object'.","example":"object","minLength":1,"pattern":"\\S"},"properties":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/OllamaToolSchemaPropertyDto"},"description":"JSON schema properties describing the arguments.","minProperties":1},"required":{"type":["array","null"],"description":"List of required properties for this schema.","items":{"type":"string"}},"oneOf":{"type":["array","null"],"description":"Optional oneOf blocks to express alternative required sets.","items":{"$ref":"#/components/schemas/OllamaToolParametersRequirementDto"}}},"required":["properties","type"]},"OllamaToolParametersRequirementDto":{"type":"object","properties":{"required":{"type":"array","description":"Required keys under this oneOf branch.","items":{"type":"string"},"minItems":1}},"required":["required"]},"OllamaToolSchemaPropertyDto":{"type":"object","properties":{"type":{"type":"string","description":"Property type","example":"string"},"description":{"type":"string","description":"Human friendly explanation","example":"Numeric id of the product"},"enum":{"type":["array","null"],"description":"Enum values, when applicable","items":{"type":"string"}}}},"ToolCallDto":{"type":"object","properties":{"id":{"type":["string","null"]},"function":{"$ref":"#/components/schemas/ToolCallFunctionDto"}},"required":["function"]},"ToolCallFunctionDto":{"type":"object","properties":{"name":{"type":"string","minLength":1,"pattern":"\\S"},"arguments":{"type":"object","additionalProperties":{}}},"required":["name"]},"ChatResponseDto":{"type":"object","properties":{"model":{"type":["string","null"]},"message":{"type":["object","null"],"anyOf":[{"$ref":"#/components/schemas/ChatMessageDto"},{"type":"null"}],"description":"Message chunk; may be null when an upstream event contains no message"},"done":{"type":"boolean"},"created_at":{"type":["string","null"]}}},"EmailDto":{"type":"object","properties":{"to":{"type":"string","format":"email","description":"Email recipient","example":"user@example.com"},"subject":{"type":"string","description":"Email subject","example":"Important message","minLength":1,"pattern":"\\S"},"message":{"type":"string","description":"Email content","example":"Please read this message carefully","minLength":1,"pattern":"\\S"},"template":{"type":["string","null"],"description":"Optional template identifier used by downstream consumers; may be null in local outbox payloads","enum":["GENERIC","PASSWORD_RESET_REQUESTED","PASSWORD_RESET_CONFIRMED",null]},"properties":{"type":"object","additionalProperties":{"type":"string"},"description":"Template properties that help the consumer render the message"}},"required":["message","subject"]},"InventoryAdjustmentDto":{"type":"object","properties":{"delta":{"type":"integer","format":"int32","description":"Nonzero change in stock; positive adds and negative subtracts","not":{"type":"integer","format":"int32","enum":[0]}},"reason":{"type":"string","maxLength":500,"minLength":1,"pattern":"\\S"},"requestId":{"type":"string","format":"uuid"},"deltaNonZero":{"type":"boolean","description":"Computed validation result; supply a nonzero delta","readOnly":true}},"required":["delta","reason","requestId"]},"InventoryMovementDto":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"productId":{"type":"integer","format":"int64"},"orderId":{"type":["integer","null"],"format":"int64"},"type":{"type":"string","enum":["INITIAL_STOCK","ADMIN_ADJUSTMENT","ORDER_DEDUCTED","ORDER_RESTORED"]},"delta":{"type":"integer","format":"int32"},"quantityAfter":{"type":"integer","format":"int32"},"actor":{"type":"string"},"reason":{"type":"string"},"requestId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"local-date-time","description":"Server local date and time without an offset; timezone is deployment-dependent, not an absolute instant"}}},"UserResponseDto":{"type":"object","properties":{"id":{"type":"integer","format":"int32","description":"User ID","example":1},"username":{"type":"string","description":"Username","example":"johndoe"},"email":{"type":"string","description":"Email address","example":"john.doe@example.com"},"roles":{"type":"array","description":"User roles","example":["ROLE_CLIENT"],"items":{"type":"string","enum":["ROLE_ADMIN","ROLE_CLIENT"]}},"firstName":{"type":["string","null"],"description":"First name","example":"John"},"lastName":{"type":["string","null"],"description":"Last name","example":"Boyd"}}},"EmailEventDto":{"type":"object","properties":{"type":{"type":"string","description":"Email template or event type","enum":["GENERIC","PASSWORD_RESET_REQUESTED","PASSWORD_RESET_CONFIRMED"]},"status":{"type":"string","description":"Delivery status recorded by the application for the Mailhog-backed test sink","enum":["QUEUED","SENT_TO_SMTP_SINK","FAILED"]},"recipientMasked":{"type":"string","description":"Masked recipient email address","example":"j***@example.com"},"createdAt":{"type":"string","format":"date-time","description":"When the email event was first recorded"},"updatedAt":{"type":"string","format":"date-time","description":"When the email event status was last updated"},"failureReason":{"type":["string","null"],"description":"Failure detail when the test mail sink handoff did not succeed"}}},"MfaStatusResponseDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether application-owned TOTP is enabled"},"unusedRecoveryCodes":{"type":"integer","format":"int64","description":"Number of unused one-time recovery codes"}}},"PageDtoTrafficLogEntryDto":{"type":"object","properties":{"content":{"type":"array","items":{"$ref":"#/components/schemas/TrafficLogEntryDto"}},"pageNumber":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"}}},"TrafficLogEntryDto":{"type":"object","description":"Persisted HTTP traffic log entry","properties":{"correlationId":{"type":"string","description":"Traffic correlation identifier"},"timestamp":{"type":"string","format":"date-time","description":"Request timestamp"},"clientSessionId":{"type":["string","null"],"description":"Client-provided session identifier"},"method":{"type":"string","description":"HTTP method"},"path":{"type":"string","description":"Request path"},"queryString":{"type":["string","null"],"description":"Request query string"},"status":{"type":"integer","format":"int32","description":"Response status code"},"durationMs":{"type":"integer","format":"int64","description":"Request duration in milliseconds"},"requestHeaders":{"additionalProperties":true,"description":"Request headers as a JSON object"},"requestContentType":{"type":["string","null"],"description":"Request content type"},"requestBody":{"type":["object","array","string","number","boolean","null"],"description":"Sanitized request body: parsed JSON of any type, or a text preview for non-JSON/truncated content"},"requestBodyTruncated":{"type":"boolean","description":"Whether the request body was truncated"},"requestBodyOriginalLength":{"type":"integer","format":"int32","description":"Sanitized request body length before truncation"},"requestBodyStoredLength":{"type":"integer","format":"int32","description":"Stored request body length"},"responseHeaders":{"additionalProperties":true,"description":"Response headers as a JSON object"},"responseContentType":{"type":["string","null"],"description":"Response content type"},"responseBody":{"type":["object","array","string","number","boolean","null"],"description":"Sanitized response body: parsed JSON of any type, or a text preview for non-JSON/truncated content"},"responseBodyTruncated":{"type":"boolean","description":"Whether the response body was truncated"},"responseBodyOriginalLength":{"type":"integer","format":"int32","description":"Sanitized response body length before truncation"},"responseBodyStoredLength":{"type":"integer","format":"int32","description":"Stored response body length"}}},"TrafficInfoDto":{"type":"object","description":"Traffic info web websockets connection","properties":{"webSocketEndpoint":{"type":"string","description":"Websocket endpoint","example":"/api/v1/ws-traffic"},"topic":{"type":"string","description":"Websocket topic","example":"/topic/traffic"},"description":{"type":"string","description":"Websocket description","example":"Connect to the WebSocket endpoint and subscribe to the topic to receive real-time HTTP traffic events"}}},"PageDtoOrderDto":{"type":"object","properties":{"content":{"type":"array","items":{"$ref":"#/components/schemas/OrderDto"}},"pageNumber":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"}}},"InventoryItemDto":{"type":"object","properties":{"productId":{"type":"integer","format":"int64"},"name":{"type":"string"},"category":{"type":"string"},"availableQuantity":{"type":"integer","format":"int32"},"stockStatus":{"type":"string","enum":["IN_STOCK","LOW_STOCK","OUT_OF_STOCK"]},"lastChangedAt":{"type":"string","format":"local-date-time","description":"Server local date and time without an offset; timezone is deployment-dependent, not an absolute instant"}}},"PageDtoInventoryItemDto":{"type":"object","properties":{"content":{"type":"array","items":{"$ref":"#/components/schemas/InventoryItemDto"}},"pageNumber":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"}}},"PageDtoInventoryMovementDto":{"type":"object","properties":{"content":{"type":"array","items":{"$ref":"#/components/schemas/InventoryMovementDto"}},"pageNumber":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"}}}},"securitySchemes":{"bearerAuth":{"type":"http","name":"bearerAuth","scheme":"bearer","bearerFormat":"JWT"}}}}