diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml
new file mode 100644
index 00000000..e08594d6
--- /dev/null
+++ b/docs/api/openapi.yaml
@@ -0,0 +1,1621 @@
+openapi: 3.0.3
+info:
+ title: Tractatus Framework API
+ version: 1.0.0
+ description: |
+ REST API for the Tractatus Framework - an architectural AI safety framework implementing structural governance for agentic AI systems.
+
+ **Key Features:**
+ - Instruction persistence and classification
+ - Cross-reference validation (prevents training pattern override)
+ - Boundary enforcement (separates technical from values decisions)
+ - Context pressure monitoring (multi-factor session health)
+ - Metacognitive verification (AI self-checks for scope creep)
+ - Comprehensive audit logging
+
+ **Security:** Most endpoints require JWT authentication with admin role.
+
+ **Rate Limiting:**
+ - Login endpoint: 5 attempts per 15 minutes per IP
+ - General API: 100 requests per 15 minutes per IP
+ contact:
+ name: Tractatus Framework
+ email: john.stroh.nz@pm.me
+ url: https://agenticgovernance.digital
+ license:
+ name: Apache 2.0
+ url: https://www.apache.org/licenses/LICENSE-2.0.html
+
+servers:
+ - url: https://agenticgovernance.digital/api
+ description: Production server
+ - url: http://localhost:9000/api
+ description: Development server
+
+tags:
+ - name: Authentication
+ description: User authentication and session management
+ - name: Documents
+ description: Framework documentation endpoints
+ - name: Governance Services
+ description: Core AI safety framework services (admin only)
+ - name: Audit
+ description: Audit logging and analytics (admin only)
+ - name: Admin
+ description: System administration and moderation (admin only)
+
+paths:
+ # ==================== Authentication ====================
+ /auth/login:
+ post:
+ tags:
+ - Authentication
+ summary: User login
+ description: |
+ Authenticate with email and password to receive a JWT access token.
+
+ **Rate Limiting:** 5 attempts per 15 minutes per IP address.
+ operationId: login
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - email
+ - password
+ properties:
+ email:
+ type: string
+ format: email
+ example: admin@tractatus.local
+ password:
+ type: string
+ format: password
+ example: tractatus2025
+ responses:
+ '200':
+ description: Login successful
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ token:
+ type: string
+ example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
+ user:
+ $ref: '#/components/schemas/User'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ description: Too many login attempts
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ error:
+ type: string
+ example: Too many login attempts from this IP. Please try again in 15 minutes.
+
+ /auth/me:
+ get:
+ tags:
+ - Authentication
+ summary: Get current user
+ description: Retrieve the authenticated user's profile information
+ operationId: getCurrentUser
+ security:
+ - BearerAuth: []
+ responses:
+ '200':
+ description: User profile retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ user:
+ $ref: '#/components/schemas/User'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+
+ /auth/logout:
+ post:
+ tags:
+ - Authentication
+ summary: User logout
+ description: |
+ Logout the current user. This logs the event on the server side.
+ The client should remove the JWT token from storage.
+ operationId: logout
+ security:
+ - BearerAuth: []
+ responses:
+ '200':
+ description: Logout successful
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ message:
+ type: string
+ example: Logged out successfully
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+
+ # ==================== Documents ====================
+ /documents:
+ get:
+ tags:
+ - Documents
+ summary: List all documents
+ description: Retrieve a paginated list of all published framework documents
+ operationId: listDocuments
+ parameters:
+ - name: page
+ in: query
+ schema:
+ type: integer
+ default: 1
+ - name: limit
+ in: query
+ schema:
+ type: integer
+ default: 50
+ - name: quadrant
+ in: query
+ description: Filter by quadrant
+ schema:
+ type: string
+ enum: [STRATEGIC, OPERATIONAL, TACTICAL, SYSTEM, STOCHASTIC]
+ responses:
+ '200':
+ description: Documents retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ documents:
+ type: array
+ items:
+ $ref: '#/components/schemas/Document'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+
+ post:
+ tags:
+ - Documents
+ summary: Create document (admin)
+ description: Create a new framework document
+ operationId: createDocument
+ security:
+ - BearerAuth: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentInput'
+ responses:
+ '201':
+ description: Document created successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ document:
+ $ref: '#/components/schemas/Document'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /documents/search:
+ get:
+ tags:
+ - Documents
+ summary: Search documents
+ description: Full-text search across all framework documents
+ operationId: searchDocuments
+ parameters:
+ - name: q
+ in: query
+ required: true
+ description: Search query
+ schema:
+ type: string
+ example: boundary enforcement
+ responses:
+ '200':
+ description: Search results retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Document'
+ count:
+ type: integer
+ example: 5
+
+ /documents/archived:
+ get:
+ tags:
+ - Documents
+ summary: List archived documents
+ description: Retrieve all archived documents
+ operationId: listArchivedDocuments
+ responses:
+ '200':
+ description: Archived documents retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ documents:
+ type: array
+ items:
+ $ref: '#/components/schemas/Document'
+
+ /documents/{identifier}:
+ get:
+ tags:
+ - Documents
+ summary: Get document by ID or slug
+ description: Retrieve a single document by MongoDB ObjectId or URL slug
+ operationId: getDocument
+ parameters:
+ - name: identifier
+ in: path
+ required: true
+ description: Document ID or slug
+ schema:
+ type: string
+ example: 27027-incident-analysis
+ responses:
+ '200':
+ description: Document retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ document:
+ $ref: '#/components/schemas/Document'
+ '404':
+ $ref: '#/components/responses/NotFound'
+
+ put:
+ tags:
+ - Documents
+ summary: Update document (admin)
+ description: Update an existing document
+ operationId: updateDocument
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: identifier
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentInput'
+ responses:
+ '200':
+ description: Document updated successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ document:
+ $ref: '#/components/schemas/Document'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+
+ delete:
+ tags:
+ - Documents
+ summary: Delete document (admin)
+ description: Delete a document (soft delete - archives it)
+ operationId: deleteDocument
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: identifier
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Document deleted successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ message:
+ type: string
+ example: Document archived successfully
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+
+ # ==================== Governance Services ====================
+ /governance:
+ get:
+ tags:
+ - Governance Services
+ summary: Get framework status
+ description: |
+ Retrieve the current status of all governance framework components.
+
+ **Admin Only** - Contains sensitive runtime data.
+ operationId: getFrameworkStatus
+ security:
+ - BearerAuth: []
+ responses:
+ '200':
+ description: Framework status retrieved successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/FrameworkStatus'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /governance/status:
+ get:
+ tags:
+ - Governance Services
+ summary: Get detailed governance status
+ description: |
+ Retrieve detailed status including component health, instruction counts, and system uptime.
+
+ **Admin Only**
+ operationId: getDetailedGovernanceStatus
+ security:
+ - BearerAuth: []
+ responses:
+ '200':
+ description: Detailed status retrieved successfully
+ content:
+ application/json:
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/FrameworkStatus'
+ - type: object
+ properties:
+ uptime:
+ type: number
+ description: Server uptime in seconds
+ example: 86400.5
+ environment:
+ type: string
+ example: production
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /governance/classify:
+ post:
+ tags:
+ - Governance Services
+ summary: Classify instruction
+ description: |
+ Test the InstructionPersistenceClassifier service by classifying a text instruction.
+
+ Returns: quadrant, persistence level, temporal scope, verification requirements, reasoning, and confidence score.
+
+ **Admin Only**
+ operationId: classifyInstruction
+ security:
+ - BearerAuth: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - text
+ properties:
+ text:
+ type: string
+ example: Always use MongoDB on port 27027
+ context:
+ type: object
+ properties:
+ source:
+ type: string
+ example: user
+ session_id:
+ type: string
+ example: sess_123
+ responses:
+ '200':
+ description: Classification successful
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ classification:
+ $ref: '#/components/schemas/InstructionClassification'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /governance/validate:
+ post:
+ tags:
+ - Governance Services
+ summary: Validate action
+ description: |
+ Test the CrossReferenceValidator service by validating a proposed action against instruction history.
+
+ Detects conflicts, training pattern overrides (27027 failure mode), and provides validation status.
+
+ **Admin Only**
+ operationId: validateAction
+ security:
+ - BearerAuth: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - action
+ properties:
+ action:
+ type: object
+ properties:
+ type:
+ type: string
+ example: database_change
+ description:
+ type: string
+ example: Change MongoDB port from 27027 to 27017
+ impact:
+ type: string
+ example: System configuration change
+ context:
+ type: object
+ properties:
+ messages:
+ type: array
+ items:
+ type: object
+ responses:
+ '200':
+ description: Validation complete
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ validation:
+ $ref: '#/components/schemas/ValidationResult'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /governance/enforce:
+ post:
+ tags:
+ - Governance Services
+ summary: Test boundary enforcement
+ description: |
+ Test the BoundaryEnforcer service by checking if an action crosses into values territory.
+
+ Identifies privacy, ethics, sovereignty, and strategic direction decisions requiring human approval.
+
+ **Admin Only**
+ operationId: enforceBounda ry
+ security:
+ - BearerAuth: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - action
+ properties:
+ action:
+ type: object
+ properties:
+ type:
+ type: string
+ example: content_moderation
+ description:
+ type: string
+ example: Decide which user comments to hide
+ context:
+ type: object
+ responses:
+ '200':
+ description: Boundary enforcement check complete
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ enforcement:
+ $ref: '#/components/schemas/BoundaryEnforcement'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /governance/pressure:
+ post:
+ tags:
+ - Governance Services
+ summary: Analyze context pressure
+ description: |
+ Test the ContextPressureMonitor service by analyzing session health across multiple factors.
+
+ Returns pressure level (NORMAL/ELEVATED/HIGH/CRITICAL/DANGEROUS) and individual factor scores.
+
+ **Admin Only**
+ operationId: analyzePressure
+ security:
+ - BearerAuth: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ context:
+ type: object
+ properties:
+ tokenUsage:
+ type: integer
+ example: 50000
+ tokenBudget:
+ type: integer
+ example: 200000
+ messageCount:
+ type: integer
+ example: 20
+ errorCount:
+ type: integer
+ example: 2
+ complexityScore:
+ type: number
+ example: 0.6
+ responses:
+ '200':
+ description: Pressure analysis complete
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ pressure:
+ $ref: '#/components/schemas/PressureAnalysis'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /governance/verify:
+ post:
+ tags:
+ - Governance Services
+ summary: Metacognitive verification
+ description: |
+ Test the MetacognitiveVerifier service by performing AI self-checks on proposed actions.
+
+ Detects scope creep, misalignment, and provides confidence scoring with alternatives.
+
+ **Admin Only**
+ operationId: verifyAction
+ security:
+ - BearerAuth: []
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - action
+ properties:
+ action:
+ type: object
+ properties:
+ type:
+ type: string
+ example: feature_implementation
+ description:
+ type: string
+ example: Add user authentication system
+ steps:
+ type: array
+ items:
+ type: string
+ reasoning:
+ type: object
+ properties:
+ justification:
+ type: string
+ example: Required for secure user management
+ context:
+ type: object
+ responses:
+ '200':
+ description: Verification complete
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ verification:
+ $ref: '#/components/schemas/MetacognitiveVerification'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ # ==================== Audit ====================
+ /audit/audit-logs:
+ get:
+ tags:
+ - Audit
+ summary: Get audit logs
+ description: |
+ Retrieve audit logs with filtering and pagination.
+
+ **Admin Only**
+ operationId: getAuditLogs
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: page
+ in: query
+ schema:
+ type: integer
+ default: 1
+ - name: limit
+ in: query
+ schema:
+ type: integer
+ default: 50
+ - name: action
+ in: query
+ description: Filter by action type
+ schema:
+ type: string
+ - name: userId
+ in: query
+ description: Filter by user ID
+ schema:
+ type: string
+ - name: startDate
+ in: query
+ description: Filter by start date (ISO 8601)
+ schema:
+ type: string
+ format: date-time
+ - name: endDate
+ in: query
+ description: Filter by end date (ISO 8601)
+ schema:
+ type: string
+ format: date-time
+ responses:
+ '200':
+ description: Audit logs retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ logs:
+ type: array
+ items:
+ $ref: '#/components/schemas/AuditLog'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /audit/audit-analytics:
+ get:
+ tags:
+ - Audit
+ summary: Get audit analytics
+ description: |
+ Retrieve aggregated analytics on audit logs (action counts, user activity, trends).
+
+ **Admin Only**
+ operationId: getAuditAnalytics
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: startDate
+ in: query
+ description: Start date for analytics period (ISO 8601)
+ schema:
+ type: string
+ format: date-time
+ - name: endDate
+ in: query
+ description: End date for analytics period (ISO 8601)
+ schema:
+ type: string
+ format: date-time
+ responses:
+ '200':
+ description: Analytics retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ analytics:
+ type: object
+ properties:
+ totalLogs:
+ type: integer
+ example: 1250
+ actionBreakdown:
+ type: object
+ additionalProperties:
+ type: integer
+ example:
+ login: 450
+ document_create: 120
+ document_update: 380
+ classify: 200
+ validate: 100
+ topUsers:
+ type: array
+ items:
+ type: object
+ properties:
+ userId:
+ type: string
+ email:
+ type: string
+ count:
+ type: integer
+ timeline:
+ type: array
+ items:
+ type: object
+ properties:
+ date:
+ type: string
+ format: date
+ count:
+ type: integer
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ # ==================== Admin ====================
+ /admin/moderation:
+ get:
+ tags:
+ - Admin
+ summary: List moderation queue
+ description: |
+ Retrieve items pending moderation.
+
+ **Admin or Moderator role required**
+ operationId: getModerationQueue
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: status
+ in: query
+ schema:
+ type: string
+ enum: [pending, approved, rejected, escalated]
+ default: pending
+ - name: page
+ in: query
+ schema:
+ type: integer
+ default: 1
+ - name: limit
+ in: query
+ schema:
+ type: integer
+ default: 50
+ responses:
+ '200':
+ description: Moderation queue retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ items:
+ type: array
+ items:
+ $ref: '#/components/schemas/ModerationItem'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /admin/moderation/{id}:
+ get:
+ tags:
+ - Admin
+ summary: Get moderation item
+ description: |
+ Retrieve a single moderation item by ID.
+
+ **Admin or Moderator role required**
+ operationId: getModerationItem
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: Moderation item retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ item:
+ $ref: '#/components/schemas/ModerationItem'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+
+ /admin/moderation/{id}/review:
+ post:
+ tags:
+ - Admin
+ summary: Review moderation item
+ description: |
+ Approve, reject, or escalate a moderation item.
+
+ **Admin or Moderator role required**
+ operationId: reviewModerationItem
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required:
+ - action
+ properties:
+ action:
+ type: string
+ enum: [approve, reject, escalate]
+ example: approve
+ notes:
+ type: string
+ example: Content meets guidelines
+ responses:
+ '200':
+ description: Review completed successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ item:
+ $ref: '#/components/schemas/ModerationItem'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+
+ /admin/stats:
+ get:
+ tags:
+ - Admin
+ summary: Get system statistics
+ description: |
+ Retrieve overall system statistics (users, documents, submissions, moderation queue).
+
+ **Admin or Moderator role required**
+ operationId: getSystemStats
+ security:
+ - BearerAuth: []
+ responses:
+ '200':
+ description: Statistics retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ stats:
+ type: object
+ properties:
+ users:
+ type: object
+ properties:
+ total:
+ type: integer
+ example: 125
+ admins:
+ type: integer
+ example: 3
+ moderators:
+ type: integer
+ example: 5
+ documents:
+ type: object
+ properties:
+ total:
+ type: integer
+ example: 45
+ published:
+ type: integer
+ example: 42
+ archived:
+ type: integer
+ example: 3
+ moderation:
+ type: object
+ properties:
+ pending:
+ type: integer
+ example: 12
+ approved:
+ type: integer
+ example: 380
+ rejected:
+ type: integer
+ example: 45
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+ /admin/activity:
+ get:
+ tags:
+ - Admin
+ summary: Get activity log
+ description: |
+ Retrieve recent admin activity (last 100 actions).
+
+ **Admin role required**
+ operationId: getActivityLog
+ security:
+ - BearerAuth: []
+ parameters:
+ - name: limit
+ in: query
+ schema:
+ type: integer
+ default: 100
+ maximum: 500
+ responses:
+ '200':
+ description: Activity log retrieved successfully
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ success:
+ type: boolean
+ example: true
+ activities:
+ type: array
+ items:
+ type: object
+ properties:
+ timestamp:
+ type: string
+ format: date-time
+ userId:
+ type: string
+ email:
+ type: string
+ action:
+ type: string
+ example: document_update
+ details:
+ type: object
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+
+# ==================== Components ====================
+components:
+ securitySchemes:
+ BearerAuth:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+ description: |
+ JWT token obtained from /api/auth/login endpoint.
+
+ Include in Authorization header: `Authorization: Bearer http://localhost:9000/api
+ 📄 OpenAPI Specification: Download OpenAPI 3.0 YAML +
++ Use this specification with Swagger UI, Postman, or any OpenAPI-compatible tool for interactive API exploration. +
+