Decision Management API¶
Referenced Files in This Document - apps/service/routes/decisions.py - apps/shared/schemas/decision.py - apps/shared/models/decision.py - src/database/decisions_db.py - apps/service/core/decision.py - apps/service/app.py - apps/service/deps.py - apps/shared/db.py - alembic/versions/001_initial_schema.py - alembic/versions/002_add_decision_type.py
Table of Contents¶
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
- Appendices
Introduction¶
This document provides comprehensive API documentation for the decision management system within Nexo. It covers CRUD operations for individual decisions, bulk endpoints for batch processing, filtering and search capabilities with advanced query parameters, workflow states and approval processes, audit trail tracking, export functionality, integration patterns, performance considerations, pagination strategies, and real-time updates via Server-Sent Events (SSE).
The decision management subsystem is implemented as a FastAPI service layer backed by a relational database managed through Alembic migrations. The API exposes RESTful endpoints for creating, retrieving, updating, deleting, querying, exporting, and streaming decisions.
Project Structure¶
The decision management feature spans multiple layers: - API routes define HTTP endpoints for decisions. - Schemas define request/response models and validation rules. - Models represent persistent entities and relationships. - Database layer implements persistence logic and queries. - Core business logic encapsulates workflows, approvals, and transformations. - Application wiring configures middleware, dependencies, and lifecycle hooks.
graph TB
Client["Client"] --> Routes["Decision Routes<br/>apps/service/routes/decisions.py"]
Routes --> Core["Decision Core Logic<br/>apps/service/core/decision.py"]
Core --> DBLayer["Database Layer<br/>src/database/decisions_db.py"]
DBLayer --> SharedDB["Shared DB Config<br/>apps/shared/db.py"]
Routes --> Schemas["Request/Response Schemas<br/>apps/shared/schemas/decision.py"]
Core --> Models["Persistent Models<br/>apps/shared/models/decision.py"]
App["FastAPI App<br/>apps/service/app.py"] --> Routes
App --> Deps["Dependencies<br/>apps/service/deps.py"]
Migrations["Alembic Migrations<br/>alembic/versions/*"] --> DBLayer
Diagram sources - apps/service/routes/decisions.py - apps/service/core/decision.py - src/database/decisions_db.py - apps/shared/db.py - apps/shared/schemas/decision.py - apps/shared/models/decision.py - apps/service/app.py - apps/service/deps.py - alembic/versions/001_initial_schema.py - alembic/versions/002_add_decision_type.py
Section sources - apps/service/app.py - apps/service/deps.py - apps/shared/db.py
Core Components¶
- Decision Routes: Expose REST endpoints for single and bulk operations, filtering, export, and SSE streaming.
- Decision Schemas: Define input/output structures for requests and responses, including filters and pagination.
- Decision Models: Represent persisted decision records and related metadata.
- Decision Core: Encapsulate business logic such as state transitions, approvals, and audit logging.
- Database Layer: Implements CRUD and complex queries against the database.
- Migrations: Define schema evolution for decisions and types.
Key responsibilities: - Validation and serialization via schemas. - Business rules and workflow enforcement in core logic. - Efficient data access and indexing via the database layer. - Consistent configuration and dependency injection across the service.
Section sources - apps/service/routes/decisions.py - apps/shared/schemas/decision.py - apps/shared/models/decision.py - apps/service/core/decision.py - src/database/decisions_db.py - alembic/versions/001_initial_schema.py - alembic/versions/002_add_decision_type.py
Architecture Overview¶
The decision management API follows a layered architecture: - Presentation layer: FastAPI routes handle HTTP requests and responses. - Service layer: Core decision logic orchestrates workflows and validations. - Data access layer: Database operations abstracted behind repository-like functions. - Persistence: Relational database with Alembic-managed schema.
sequenceDiagram
participant C as "Client"
participant R as "Routes<br/>decisions.py"
participant S as "Core<br/>decision.py"
participant D as "DB Layer<br/>decisions_db.py"
participant DB as "Database"
C->>R : "POST /api/decisions"
R->>R : "Validate payload via Schemas"
R->>S : "Create decision"
S->>D : "Persist decision"
D->>DB : "INSERT"
DB-->>D : "Row ID"
D-->>S : "Created entity"
S-->>R : "Result"
R-->>C : "201 Created + JSON"
Diagram sources - apps/service/routes/decisions.py - apps/shared/schemas/decision.py - apps/service/core/decision.py - src/database/decisions_db.py
Detailed Component Analysis¶
Decision Endpoints¶
Endpoints cover full CRUD, bulk operations, filtering/search, export, and SSE streaming.
- Create Decision
- Method: POST
- Path: /api/decisions
- Request body: Decision creation schema fields
- Response: Created decision object
-
Notes: Validates inputs; triggers initial workflow state; logs audit entry
-
Get Decision
- Method: GET
- Path: /api/decisions/{id}
-
Response: Decision object or 404 if not found
-
Update Decision
- Method: PATCH
- Path: /api/decisions/{id}
- Request body: Partial update fields
- Response: Updated decision object
-
Notes: Enforces allowed state transitions; records audit log
-
Delete Decision
- Method: DELETE
- Path: /api/decisions/{id}
- Response: 204 No Content on success
-
Notes: Soft delete may be used depending on model design
-
List Decisions (Filtered and Paginated)
- Method: GET
- Path: /api/decisions
- Query parameters:
- page: integer (default 1)
- page_size: integer (default 50)
- sort_by: string (e.g., created_at, updated_at)
- order: asc|desc
- type: filter by decision type
- status: filter by workflow status
- date_from: ISO-8601 datetime
- date_to: ISO-8601 datetime
- q: free-text search across content metadata
- tags: comma-separated list
- author_id: filter by creator
-
Response: Paginated list of decisions
-
Bulk Create
- Method: POST
- Path: /api/decisions/bulk
- Request body: Array of decision objects
-
Response: Summary of successes/failures with per-item results
-
Bulk Update
- Method: PATCH
- Path: /api/decisions/bulk
- Request body: Array of {id, fields}
-
Response: Summary of successes/failures with per-item results
-
Bulk Delete
- Method: DELETE
- Path: /api/decisions/bulk
- Request body: Array of IDs
-
Response: Summary of successes/failures with per-item results
-
Export Decisions
- Method: GET
- Path: /api/decisions/export
- Query parameters: Same as list plus format=json|csv
-
Response: File stream (JSON or CSV)
-
Stream Updates (SSE)
- Method: GET
- Path: /api/decisions/stream
- Query parameters: Optional filters to subscribe to specific events
- Response: Text/event-stream with incremental updates
Notes: - All endpoints return structured JSON unless exporting. - Errors follow consistent error response shape with code and message. - Authentication and authorization are enforced at route level via dependencies.
Section sources - apps/service/routes/decisions.py - apps/shared/schemas/decision.py
Decision Schemas¶
Defines request and response models for decisions and filters.
- DecisionCreate
- Fields: type, status, content metadata, author_id, timestamps
-
Validation: Required fields, enum constraints, date range checks
-
DecisionUpdate
- Fields: Subset of create fields for partial updates
-
Validation: Allowed fields only
-
DecisionFilter
- Fields: page, page_size, sort_by, order, type, status, date_from, date_to, q, tags, author_id
-
Validation: Page bounds, supported sort fields, date ordering
-
DecisionResponse
-
Fields: id, type, status, content metadata, timestamps, audit summary
-
BulkOperationResult
- Fields: total, succeeded, failed, errors (array of item-level errors)
Section sources - apps/shared/schemas/decision.py
Decision Model¶
Represents the persistent decision entity and relationships.
- Decision
- Primary key: id
- Attributes: type, status, content metadata, author_id, timestamps
- Relationships: Audit entries, history records
-
Constraints: Unique indexes on critical fields, foreign keys where applicable
-
DecisionType
- Enumerated values defined in migration
- Used to constrain decision.type
Section sources - apps/shared/models/decision.py - alembic/versions/001_initial_schema.py - alembic/versions/002_add_decision_type.py
Decision Core Logic¶
Encapsulates business rules, workflow transitions, and audit logging.
- create_decision(payload): Validates, sets initial state, persists, logs audit
- get_decision(id): Retrieves decision by ID
- update_decision(id, patch): Applies allowed changes, enforces transitions, logs audit
- delete_decision(id): Performs soft/hard delete based on policy
- list_decisions(filters): Builds query with filters, sorting, pagination
- bulk_create(items): Batch insert with transactional guarantees
- bulk_update(items): Batch update with per-item result aggregation
- bulk_delete(ids): Batch delete with per-item result aggregation
- export_decisions(filters, format): Streams JSON or CSV export
- stream_updates(filters): Emits SSE events for matching decisions
Workflow states and transitions: - States: draft, pending_review, approved, rejected, archived - Transitions: - draft -> pending_review - pending_review -> approved | rejected - approved -> archived - rejected -> draft (rework) - Approval process: Requires authorized approver role; records approver_id and timestamp - Audit trail: Every state change and significant field update creates an audit entry
Error handling: - Invalid transitions raise explicit errors with codes - Duplicate or conflicting updates return conflict errors - Validation failures return detailed messages
Section sources - apps/service/core/decision.py
Database Layer¶
Implements persistence operations and optimized queries.
- create_decision(decision): Insert new record
- get_decision(id): Select by primary key
- update_decision(id, fields): Update with conditional checks
- delete_decision(id): Soft/hard delete
- list_decisions(filters): Filtered query with joins and indexes
- bulk_insert(items): Batch insert using executemany or ORM bulk
- bulk_update(items): Batch update with transaction
- bulk_delete(ids): Batch delete with transaction
- export_query(filters, format): Generate export dataset
- event_stream(filters): Subscribe to changes for SSE
Indexing and performance: - Indexes on type, status, created_at, updated_at, author_id - Composite index for common filter combinations (type, status, date ranges) - Pagination uses offset/limit or cursor-based approaches for large datasets
Section sources - src/database/decisions_db.py - apps/shared/db.py
Application Wiring and Dependencies¶
- FastAPI app initialization and route mounting
- Dependency injection for database sessions and services
- Middleware for logging, CORS, and authentication
- SSE setup for streaming updates
Section sources - apps/service/app.py - apps/service/deps.py
Dependency Analysis¶
The decision management system exhibits clear separation of concerns: - Routes depend on Schemas for validation and Core for business logic. - Core depends on Models for entity definitions and Database Layer for persistence. - Database Layer depends on Shared DB configuration and Alembic migrations.
classDiagram
class DecisionRoutes {
+create()
+get()
+update()
+delete()
+list()
+bulk_create()
+bulk_update()
+bulk_delete()
+export()
+stream()
}
class DecisionCore {
+create_decision()
+get_decision()
+update_decision()
+delete_decision()
+list_decisions()
+bulk_create()
+bulk_update()
+bulk_delete()
+export_decisions()
+stream_updates()
}
class DecisionModel {
+id
+type
+status
+content_metadata
+author_id
+created_at
+updated_at
}
class DecisionDB {
+create_decision()
+get_decision()
+update_decision()
+delete_decision()
+list_decisions()
+bulk_insert()
+bulk_update()
+bulk_delete()
+export_query()
}
DecisionRoutes --> DecisionCore : "uses"
DecisionCore --> DecisionModel : "operates on"
DecisionCore --> DecisionDB : "persists"
Diagram sources - apps/service/routes/decisions.py - apps/service/core/decision.py - apps/shared/models/decision.py - src/database/decisions_db.py
Section sources - apps/service/routes/decisions.py - apps/service/core/decision.py - apps/shared/models/decision.py - src/database/decisions_db.py
Performance Considerations¶
- Pagination: Use page and page_size parameters; prefer cursor-based pagination for very large datasets.
- Filtering: Leverage server-side filters (type, status, date ranges) to reduce payload size.
- Sorting: Restrict sort_by to indexed fields (created_at, updated_at) to avoid expensive sorts.
- Bulk Operations: Use transactions to ensure consistency and reduce round-trips.
- Export: Stream large exports to minimize memory usage; support CSV for tabular analysis.
- SSE: Apply client-side reconnection logic; throttle events if necessary.
- Indexing: Ensure composite indexes for frequent filter combinations.
- Connection Pooling: Configure appropriate pool sizes for high concurrency.
[No sources needed since this section provides general guidance]
Troubleshooting Guide¶
Common issues and resolutions: - Validation errors: Check request payloads against schema requirements; ensure enums and date formats are correct. - State transition errors: Verify current status and allowed transitions before updates. - Duplicate conflicts: Handle unique constraint violations; implement idempotency keys for retries. - Performance degradation: Review query filters and indexes; adjust pagination strategy. - SSE connectivity: Confirm network stability and server SSE endpoint availability; implement exponential backoff.
Section sources - apps/service/routes/decisions.py - apps/service/core/decision.py
Conclusion¶
The decision management API provides robust CRUD, bulk operations, filtering, export, and real-time streaming capabilities. Its layered architecture ensures maintainability and scalability. By adhering to the documented endpoints, schemas, and best practices, integrators can efficiently manage decisions at scale while maintaining data integrity and auditability.
[No sources needed since this section summarizes without analyzing specific files]
Appendices¶
Example Complex Queries¶
- Filter by type and date range with pagination:
- GET /api/decisions?type=review&date_from=2024-01-01T00:00:00Z&date_to=2024-12-31T23:59:59Z&page=1&page_size=100
- Search with free text and tags:
- GET /api/decisions?q=metadata&tags=urgent,priority&sort_by=updated_at&order=desc
- Export filtered dataset as CSV:
- GET /api/decisions/export?format=csv&type=approval&status=approved
Bulk Operation Examples¶
- Bulk create:
- POST /api/decisions/bulk with array of decision objects
- Bulk update:
- PATCH /api/decisions/bulk with array of {id, fields}
- Bulk delete:
- DELETE /api/decisions/bulk with array of IDs
Integration Patterns¶
- External systems should:
- Authenticate via provided auth endpoints
- Use idempotency keys for retries
- Implement retry with backoff for transient errors
- Subscribe to SSE for real-time updates when needed
Real-Time Updates via SSE¶
- Connect to /api/decisions/stream with optional filters
- Handle event streams for create, update, delete events
- Reconnect on connection loss with exponential backoff
[No sources needed since this section provides conceptual examples]