-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopenapi.json
More file actions
1 lines (1 loc) · 266 KB
/
Copy pathopenapi.json
File metadata and controls
1 lines (1 loc) · 266 KB
1
{"openapi":"3.1.0","info":{"title":"Backcast","version":"0.1.0"},"paths":{"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Root Get"}}}}}}},"/api/v1/auth/register":{"post":{"tags":["authentication"],"summary":"Register","description":"Register a new user.","operationId":"register","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegister"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/login":{"post":{"tags":["authentication"],"summary":"Login","description":"OAuth2 compatible token login, get an access token and refresh token for future requests.","operationId":"login","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_login"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["authentication"],"summary":"Read Users Me","description":"Get current user profile with RBAC permissions.\n\nReturns user data including their role-based permissions for use\nin frontend authorization checks.","operationId":"get_current_user","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPublic"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/auth/refresh":{"post":{"tags":["authentication"],"summary":"Refresh Token","description":"Refresh access token using a valid refresh token.\n\nReturns a new access token if the refresh token is valid, not expired,\nand not revoked.","operationId":"refresh_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/logout":{"post":{"tags":["authentication"],"summary":"Logout","description":"Logout user by revoking their refresh token.\n\nThe access token will still be valid until it expires, but the\nrefresh token cannot be used to get new access tokens.","operationId":"logout","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Logout"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users":{"get":{"tags":["Users"],"summary":"Read Users","description":"Retrieve users.\nOnly Admins can list all users.","operationId":"get_users","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserPublic"},"title":"Response Get Users"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Users"],"summary":"Create User","description":"Create a new user.\nAdmin only.","operationId":"create_user","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRegister"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/me/preferences":{"get":{"tags":["Users"],"summary":"Get My Preferences","description":"Get current user's preferences.\nRequires read permission.","operationId":"get_my_preferences","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPreferenceResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]}]},"put":{"tags":["Users"],"summary":"Update My Preferences","description":"Update current user's preferences.\nRequires update permission.","operationId":"update_my_preferences","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPreferenceUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPreferenceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/users/{user_id}":{"get":{"tags":["Users"],"summary":"Read User","description":"Get a specific user by id.\nAdmin can get any user. Users can only get themselves.\nRequires read permission.","operationId":"get_user","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Users"],"summary":"Update User","description":"Update a user.\nAdmin can update any user. Users can only update themselves.\nRequires update permission.","operationId":"update_user","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Users"],"summary":"Delete User","description":"Soft delete a user.\nAdmin only.","operationId":"delete_user","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}/history":{"get":{"tags":["Users"],"summary":"Get User History","description":"Get version history for a user.\nAdmin can view any user's history. Users can only view their own.\nRequires read permission.","operationId":"get_user_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserHistory"},"title":"Response Get User History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/departments":{"get":{"tags":["Departments"],"summary":"Read Departments","description":"Retrieve departments with server-side features. Requires read permission.","operationId":"get_departments","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (code, name)","title":"Search"},"description":"Search term (code, name)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Departments"],"summary":"Create Department","description":"Create a new department. Admin only.","operationId":"create_department","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepartmentCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepartmentRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/departments/{department_id}":{"get":{"tags":["Departments"],"summary":"Read Department","description":"Get a specific department by id. Requires read permission.","operationId":"get_department","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"department_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Department Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepartmentRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Departments"],"summary":"Update Department","description":"Update a department. Admin only.","operationId":"update_department","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"department_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Department Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepartmentUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepartmentRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Departments"],"summary":"Delete Department","description":"Soft delete a department. Admin only.","operationId":"delete_department","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"department_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Department Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/departments/{department_id}/history":{"get":{"tags":["Departments"],"summary":"Get Department History","description":"Get version history for a department. Requires read permission.","operationId":"get_department_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"department_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Department Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DepartmentRead"},"title":"Response Get Department History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects":{"get":{"tags":["Projects"],"summary":"Read Projects","description":"Retrieve projects with server-side search, filtering, and sorting.\n\nSupports:\n- **Search**: Case-insensitive search across code and name\n- **Filters**: Filter by status, code, name (format: \"column:value;column:value1,value2\")\n- **Sorting**: Sort by any field (asc/desc)\n- **Pagination**: Returns total count for proper pagination UI\n- **Mode**: Branch mode - \"merged\" (combine with main) or \"isolated\" (current branch only)\n\nRequires read permission. Non-admin users only see projects they are members of.","operationId":"get_projects","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (code, name)","title":"Search"},"description":"Search term (code, name)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get Projects as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get Projects as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Projects"],"summary":"Create Project","description":"Create a new project. Requires create permission.","operationId":"create_project","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}":{"get":{"tags":["Projects"],"summary":"Read Project","description":"Get a specific project by id. Requires read permission.\n\nSupports time-travel queries via the as_of parameter to view\nthe project's state at any historical point in time.","operationId":"get_project","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get project state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get project state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Projects"],"summary":"Update Project","description":"Update a project. Requires update permission.","operationId":"update_project","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Projects"],"summary":"Delete Project","description":"Soft delete a project. Requires delete permission.","operationId":"delete_project","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/history":{"get":{"tags":["Projects"],"summary":"Read Project History","description":"Get version history for a project. Requires read permission.","operationId":"get_project_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectRead"},"title":"Response Get Project History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/branches":{"get":{"tags":["Projects"],"summary":"Read Project Branches","description":"Get all branches for a project.\n\nReturns the main branch plus any change order branches (BR-{code})\nthat exist for this project.\n\nRequires read permission.","operationId":"get_project_branches","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get branches as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get branches as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchPublic"},"title":"Response Get Project Branches"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/gantt-data":{"get":{"tags":["Gantt"],"summary":"Get Gantt Data","description":"Get aggregated Gantt chart data for a project.\n\nReturns WBE hierarchy with cost elements and their schedule baselines,\nfiltered by branch, mode, and optional time-travel timestamp.","operationId":"get_project_gantt_data","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged or isolated","default":"merged","title":"Mode"},"description":"Branch mode: merged or isolated"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get data as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get data as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GanttDataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/members":{"get":{"tags":["Project Members"],"summary":"List Project Members","description":"List all members of a project.\n\nRequires project-read permission for the project.","operationId":"get_project_members","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectMemberRead"},"title":"Response Get Project Members"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Project Members"],"summary":"Add Project Member","description":"Add a member to a project.\n\nRequires project-admin permission for the project.","operationId":"add_project_member","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectMemberCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectMemberRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/members/{user_id}":{"delete":{"tags":["Project Members"],"summary":"Remove Project Member","description":"Remove a member from a project.\n\nRequires project-admin permission for the project.","operationId":"remove_project_member","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Project Members"],"summary":"Update Project Member Role","description":"Update a project member's role.\n\nRequires project-admin permission for the project.","operationId":"update_project_member_role","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectMemberUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectMemberRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projects/{project_id}/budget-settings":{"get":{"tags":["Project Budget Settings"],"summary":"Get Project Budget Settings","description":"Get budget settings for a project.\n\nReturns the project's budget warning threshold and admin override settings.\nIf no custom settings exist, returns default values (80% threshold, override allowed).","operationId":"get_project_budget_settings","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectBudgetSettingsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Project Budget Settings"],"summary":"Update Project Budget Settings","description":"Create or update budget settings for a project.\n\nCreates new settings if none exist, or updates existing settings.\nOnly users with project-budget-settings-write permission can modify settings.","operationId":"update_project_budget_settings","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectBudgetSettingsCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectBudgetSettingsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wbes":{"get":{"tags":["WBEs"],"summary":"Read Wbes","description":"Retrieve WBEs with server-side search, filtering, and sorting.\n\nSupports two modes:\n1. **Hierarchical filtering** (project_id/parent_wbe_id): Returns list without pagination\n2. **General listing** (no hierarchical filters): Returns paginated response with search/filter/sort\n\nHierarchical Filtering:\n- project_id only: All WBEs in project\n- project_id + parent_wbe_id: Child WBEs of specified parent\n- parent_wbe_id='null': Root WBEs (parent_wbe_id IS NULL)\n\nGeneral Listing (when no hierarchical filters):\n- **Search**: Case-insensitive search across code and name\n- **Filters**: Filter by level, code, name (format: \"column:value;column:value1,value2\")\n- **Sorting**: Sort by any field (asc/desc)\n- **Pagination**: Returns total count for proper pagination UI\n- **Mode**: Branch mode - \"merged\" (combine with main) or \"isolated\" (current branch only)\n\nRequires read permission.","operationId":"get_wbes","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by project ID","title":"Project Id"},"description":"Filter by project ID"},{"name":"parent_wbe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by parent WBE ID (use 'null' string for root WBEs)","title":"Parent Wbe Id"},"description":"Filter by parent WBE ID (use 'null' string for root WBEs)"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (code, name)","title":"Search"},"description":"Search term (code, name)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get WBEs as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get WBEs as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["WBEs"],"summary":"Create Wbe","description":"Create a new WBE. Requires create permission.","operationId":"create_wbe","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WBECreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WBERead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wbes/{wbe_id}":{"get":{"tags":["WBEs"],"summary":"Read Wbe","description":"Get a specific WBE by id. Requires read permission.\n\nSupports time-travel queries via the as_of parameter to view\nthe WBE's state at any historical point in time.","operationId":"get_wbe","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"wbe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Wbe Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get WBE state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get WBE state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WBERead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["WBEs"],"summary":"Update Wbe","description":"Update a WBE. Requires update permission.","operationId":"update_wbe","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"wbe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Wbe Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WBEUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WBERead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["WBEs"],"summary":"Delete Wbe","description":"Soft delete a WBE. Requires delete permission.","operationId":"delete_wbe","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"wbe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Wbe Id"}},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wbes/{wbe_id}/breadcrumb":{"get":{"tags":["WBEs"],"summary":"Read Wbe Breadcrumb","description":"Get breadcrumb trail for a WBE (project + ancestor path). Requires read permission.","operationId":"get_wbe_breadcrumb","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"wbe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Wbe Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get breadcrumb as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get breadcrumb as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WBEBreadcrumb"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/wbes/{wbe_id}/history":{"get":{"tags":["WBEs"],"summary":"Read Wbe History","description":"Get version history for a WBE. Requires read permission.","operationId":"get_wbe_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"wbe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Wbe Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WBERead"},"title":"Response Get Wbe History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-element-types":{"get":{"tags":["Cost Element Types"],"summary":"Read Cost Element Types","description":"Retrieve cost element types with server-side features.","operationId":"get_cost_element_types","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"department_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Department ID","title":"Department Id"},"description":"Filter by Department ID"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (code, name)","title":"Search"},"description":"Search term (code, name)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Cost Element Types"],"summary":"Create Cost Element Type","description":"Create a new cost element type.","operationId":"create_cost_element_type","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementTypeCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementTypeRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-element-types/{cost_element_type_id}":{"get":{"tags":["Cost Element Types"],"summary":"Read Cost Element Type","description":"Get a specific cost element type by id.","operationId":"get_cost_element_type","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_type_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Type Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementTypeRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Cost Element Types"],"summary":"Update Cost Element Type","description":"Update a cost element type.","operationId":"update_cost_element_type","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_type_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Type Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementTypeUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementTypeRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Cost Element Types"],"summary":"Delete Cost Element Type","description":"Soft delete a cost element type.","operationId":"delete_cost_element_type","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_type_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Type Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-element-types/{cost_element_type_id}/history":{"get":{"tags":["Cost Element Types"],"summary":"Get Cost Element Type History","description":"Get version history for a cost element type.","operationId":"get_cost_element_type_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_type_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Type Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CostElementTypeRead"},"title":"Response Get Cost Element Type History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements":{"get":{"tags":["Cost Elements"],"summary":"Read Cost Elements","description":"Retrieve cost elements with server-side search, filtering, and sorting.","operationId":"get_cost_elements","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"wbe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by WBE ID","title":"Wbe Id"},"description":"Filter by WBE ID"},{"name":"cost_element_type_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Cost Element Type ID","title":"Cost Element Type Id"},"description":"Filter by Cost Element Type ID"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (code, name)","title":"Search"},"description":"Search term (code, name)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get Cost Elements as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get Cost Elements as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Cost Elements"],"summary":"Create Cost Element","description":"Create a new cost element in specified branch.","operationId":"create_cost_element","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}":{"get":{"tags":["Cost Elements"],"summary":"Read Cost Element","description":"Get a specific cost element by id and branch.\n\nSupports time-travel queries via the as_of parameter to view\nthe cost element's state at any historical point in time.","operationId":"get_cost_element","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get cost element state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get cost element state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Cost Elements"],"summary":"Update Cost Element","description":"Update a cost element. Creates new version or forks.","operationId":"update_cost_element","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostElementRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Cost Elements"],"summary":"Delete Cost Element","description":"Soft delete a cost element in a branch.","operationId":"delete_cost_element","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to delete from","default":"main","title":"Branch"},"description":"Branch to delete from"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/history":{"get":{"tags":["Cost Elements"],"summary":"Get Cost Element History","description":"Get full version history for a cost element in a specific branch.\n\nReturns all versions of the cost element in the specified branch,\nordered by transaction_time descending (most recent first).","operationId":"get_cost_element_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query history from","default":"main","title":"Branch"},"description":"Branch to query history from"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CostElementRead"},"title":"Response Get Cost Element History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/breadcrumb":{"get":{"tags":["Cost Elements"],"summary":"Get Cost Element Breadcrumb","description":"Get breadcrumb trail for a Cost Element (project + WBE + cost element).","operationId":"get_cost_element_breadcrumb","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Cost Element Breadcrumb"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/schedule-baseline":{"get":{"tags":["Cost Elements"],"summary":"Get Cost Element Schedule Baseline","description":"Get the schedule baseline for a specific cost element.\n\nReturns the single schedule baseline associated with this cost element\nin the specified branch. Returns 404 if no baseline exists.","operationId":"get_cost_element_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Cost Element Schedule Baseline"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Cost Elements"],"summary":"Create Cost Element Schedule Baseline","description":"Create a schedule baseline for a cost element.\n\nCreates a new schedule baseline and associates it with the cost element.\nEach cost element can have only one schedule baseline per branch.\n\nRaises 400 if a baseline already exists for this cost element.","operationId":"create_cost_element_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Baseline In"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Cost Element Schedule Baseline"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/schedule-baseline/{baseline_id}":{"put":{"tags":["Cost Elements"],"summary":"Update Cost Element Schedule Baseline","description":"Update the schedule baseline for a cost element.\n\nUpdates the specified baseline. Creates a new version with the changes.\nOnly the fields provided in the request body are updated.","operationId":"update_cost_element_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Baseline Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Baseline In"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Cost Element Schedule Baseline"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Cost Elements"],"summary":"Delete Cost Element Schedule Baseline","description":"Soft delete the schedule baseline for a cost element.\n\nSoft deletes the specified baseline. The baseline is marked as deleted\nbut remains in the database for audit purposes.","operationId":"delete_cost_element_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Baseline Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to delete from","default":"main","title":"Branch"},"description":"Branch to delete from"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/evm":{"get":{"tags":["Cost Elements"],"summary":"Read Evm Metrics","description":"Calculate EVM (Earned Value Management) metrics for a cost element.\n\nReturns comprehensive EVM analysis including:\n- BAC: Budget at Completion (total planned budget)\n- PV: Planned Value (budgeted cost of work scheduled)\n- AC: Actual Cost (cost incurred to date)\n- EV: Earned Value (budgeted cost of work performed)\n- CV: Cost Variance (EV - AC, negative = over budget)\n- SV: Schedule Variance (EV - PV, negative = behind schedule)\n- CPI: Cost Performance Index (EV / AC, < 1.0 = over budget)\n- SPI: Schedule Performance Index (EV / PV, < 1.0 = behind schedule)\n\nTime-Travel & Branching:\n- All metrics respect time-travel: entities are fetched as they were at control_date\n- Cost elements and schedule baselines are fetched at the correct valid_time\n- Branch mode (ISOLATED/MERGE) controls parent branch fallback behavior\n- Cost registrations and progress entries are global facts (not branchable)\n\nWarning: Returns EV = 0 with warning message if no progress has been reported.","operationId":"get_evm_metrics","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for time-travel query (ISO 8601, defaults to now). All entities are fetched as they were at this valid_time.","title":"Control Date"},"description":"Control date for time-travel query (ISO 8601, defaults to now). All entities are fetched as they were at this valid_time."},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"branch_mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/BranchMode","description":"Branch mode: ISOLATED (only this branch) or MERGE (fall back to parent branches)","default":"merge"},"description":"Branch mode: ISOLATED (only this branch) or MERGE (fall back to parent branches)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/evm-history":{"get":{"tags":["Cost Elements"],"summary":"Read Evm History","description":"Get historical EVM metrics (PV/EV/AC) for a cost element.","operationId":"get_evm_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"granularity","in":"query","required":false,"schema":{"type":"string","pattern":"^(day|week|month)$","description":"Time granularity","default":"week","title":"Granularity"},"description":"Time granularity"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for time-travel query. ","title":"Control Date"},"description":"Control date for time-travel query. "},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"branch_mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/BranchMode","description":"Branch mode","default":"merge"},"description":"Branch mode"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-elements/{cost_element_id}/forecast":{"get":{"tags":["Cost Elements"],"summary":"Get Cost Element Forecast","description":"Get the forecast for a specific cost element.\n\nReturns the single forecast associated with this cost element\nin the specified branch. Returns 404 if no forecast exists.\n\nSupports time-travel queries via the as_of parameter to view\nthe forecast's state at any historical point in time.\n\nThis endpoint follows the inverted FK pattern, querying via\ncost_element.forecast_id instead of forecast.cost_element_id.","operationId":"get_cost_element_forecast","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get forecast state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get forecast state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Cost Element Forecast"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Cost Elements"],"summary":"Update Cost Element Forecast","description":"Update the forecast for a cost element.\n\nUpdates the existing forecast or creates a new one if none exists.\nCreates a new version with the changes.\nOnly the fields provided in the request body are updated.\n\nRaises 400 if a forecast already exists (when creating new).","operationId":"update_cost_element_forecast","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForecastUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Cost Element Forecast"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Cost Elements"],"summary":"Delete Cost Element Forecast","description":"Delete the forecast for a cost element.\n\nSoft deletes the forecast associated with this cost element.\nThe forecast remains in the database for audit/history but is marked as deleted.\n\nNote: This does NOT cascade to delete the cost element. The cost element\nremains, but without an associated forecast. A new forecast can be created later.","operationId":"delete_cost_element_forecast","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to delete from","default":"main","title":"Branch"},"description":"Branch to delete from"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-registrations":{"get":{"tags":["Cost Registrations"],"summary":"Read Cost Registrations","description":"Retrieve cost registrations with server-side search, filtering, and sorting.\n\nCost registrations track actual expenditures against cost elements.\nThey are versionable but NOT branchable (costs are global facts).\nBranch and mode parameters are provided for API consistency and context,\nthough cost registrations themselves are not branch-specific.\n\nFiltering hierarchy: cost_element_id > wbe_id > project_id.\nWhen multiple are provided, all applicable filters are applied (AND).","operationId":"get_cost_registrations","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query (for context)","default":"main","title":"Branch"},"description":"Branch to query (for context)"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"cost_element_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Cost Element ID","title":"Cost Element Id"},"description":"Filter by Cost Element ID"},{"name":"wbe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by WBE ID (returns all registrations under this WBE)","title":"Wbe Id"},"description":"Filter by WBE ID (returns all registrations under this WBE)"},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Project ID (returns all registrations under this project)","title":"Project Id"},"description":"Filter by Project ID (returns all registrations under this project)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (description, invoice, vendor)","title":"Search"},"description":"Search term (description, invoice, vendor)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get Cost Registrations as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get Cost Registrations as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Cost Registrations"],"summary":"Create Cost Registration","description":"Create a new cost registration.\n\nValidates budget status and includes warning if threshold exceeded.\nRegistration succeeds even when over budget (non-blocking validation).\n\nThe control_date parameter allows setting the valid_time start date,\nuseful for backdated cost registrations or testing time-travel scenarios.","operationId":"create_cost_registration","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to check budget against","default":"main","title":"Branch"},"description":"Branch to check budget against"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostRegistrationCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Cost Registration"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-registrations/budget-status/{cost_element_id}":{"get":{"tags":["Cost Registrations"],"summary":"Get Budget Status","description":"Get budget status for a cost element with time-travel support.\n\nReturns the budget amount, used amount, remaining amount, and percentage used.\nUseful for displaying budget progress bars and warnings.\n\nThe as_of parameter allows viewing the budget status at any historical point in time,\nshowing only cost registrations that were valid as of that timestamp.","operationId":"get_budget_status","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get budget status as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get budget status as of this timestamp (ISO 8601)"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch context to resolve Cost Element budget","default":"main","title":"Branch"},"description":"Branch context to resolve Cost Element budget"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Budget Status"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-registrations/aggregated":{"get":{"tags":["Cost Registrations"],"summary":"Get Aggregated Costs","description":"Get cost aggregations by time period.\n\nReturns costs aggregated by day, week, or month for a cost element.\nUseful for generating cost charts and trend analysis.\n\nExample:\n - period=daily: One row per day with total costs\n - period=weekly: One row per week (starts Monday) with total costs\n - period=monthly: One row per month (starts 1st) with total costs\n\nAll costs respect time-travel queries via the as_of parameter.","operationId":"get_aggregated_costs","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Cost Element ID to aggregate costs for","title":"Cost Element Id"},"description":"Cost Element ID to aggregate costs for"},{"name":"period","in":"query","required":true,"schema":{"type":"string","pattern":"^(daily|weekly|monthly)$","description":"Aggregation period (daily, weekly, or monthly)","title":"Period"},"description":"Aggregation period (daily, weekly, or monthly)"},{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date-time","description":"Start date for aggregation (ISO 8601)","title":"Start Date"},"description":"Start date for aggregation (ISO 8601)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"End date for aggregation (ISO 8601, defaults to now)","title":"End Date"},"description":"End date for aggregation (ISO 8601, defaults to now)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get costs as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get costs as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Aggregated Costs"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-registrations/cumulative":{"get":{"tags":["Cost Registrations"],"summary":"Get Cumulative Costs","description":"Get cumulative costs over time.\n\nReturns a time series of costs with running cumulative totals.\nUseful for S-curve charts and cumulative cost tracking.\n\nEach entry includes:\n- registration_date: Date of the cost registration\n- amount: Cost amount for that registration\n- cumulative_amount: Running total of all costs to date\n\nAll costs respect time-travel queries via the as_of parameter.","operationId":"get_cumulative_costs","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Cost Element ID to get cumulative costs for","title":"Cost Element Id"},"description":"Cost Element ID to get cumulative costs for"},{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date-time","description":"Start date for calculation (ISO 8601)","title":"Start Date"},"description":"Start date for calculation (ISO 8601)"},{"name":"end_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"End date for calculation (ISO 8601, defaults to now)","title":"End Date"},"description":"End date for calculation (ISO 8601, defaults to now)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get costs as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get costs as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Cumulative Costs"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-registrations/{cost_registration_id}":{"get":{"tags":["Cost Registrations"],"summary":"Read Cost Registration","description":"Get a specific cost registration by id.\n\nSupports time-travel queries via the as_of parameter to view\nthe cost registration's state at any historical point in time.","operationId":"get_cost_registration","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_registration_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Registration Id"}},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get cost registration state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get cost registration state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostRegistrationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Cost Registrations"],"summary":"Update Cost Registration","description":"Update a cost registration.\n\nCreates a new version of the cost registration with the updated values.\nPrevious versions are preserved in the history.\n\nThe control_date parameter allows setting the valid_time start date for\nthe new version, useful for backdating updates or testing time-travel.","operationId":"update_cost_registration","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_registration_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Registration Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostRegistrationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CostRegistrationRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Cost Registrations"],"summary":"Delete Cost Registration","description":"Soft delete a cost registration.\n\nMarks the cost registration as deleted but preserves it in the history.","operationId":"delete_cost_registration","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_registration_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Registration Id"}},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cost-registrations/{cost_registration_id}/history":{"get":{"tags":["Cost Registrations"],"summary":"Get Cost Registration History","description":"Get full version history for a cost registration.\n\nReturns all versions of the cost registration, ordered by transaction time.\nIncludes both current and historical versions.","operationId":"get_cost_registration_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_registration_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Registration Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CostRegistrationRead"},"title":"Response Get Cost Registration History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/stats":{"get":{"tags":["Change Orders"],"summary":"Get Change Order Stats","description":"Get aggregated statistics for change orders in a project.\n\nReturns comprehensive analytics including:\n- Summary KPIs (total count, cost exposure, pending/approved values)\n- Distribution by status and impact level\n- Cumulative cost trend over time\n- Approval workload by approver\n- Aging items (stuck/overdue change orders)\n\nRequires change-order-read permission.","operationId":"get_change_order_stats","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Project ID","title":"Project Id"},"description":"Project ID"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel timestamp","title":"As Of"},"description":"Time travel timestamp"},{"name":"aging_threshold_days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Aging threshold in days","default":7,"title":"Aging Threshold Days"},"description":"Aging threshold in days"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderStatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders":{"get":{"tags":["Change Orders"],"summary":"Read Change Orders","description":"Retrieve change orders for a project with pagination.\n\nChange Orders are always scoped to a specific project.\nThe auto-created branch for each CO is named `BR-{code}`.\n\nRequires read permission.","operationId":"get_change_orders","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Filter by project ID","title":"Project Id"},"description":"Filter by project ID"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search term (code, title)","title":"Search"},"description":"Search term (code, title)"},{"name":"filters","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filters in format 'column:value;column:value1,value2'","examples":["status:Draft"],"title":"Filters"},"description":"Filters in format 'column:value;column:value1,value2'"},{"name":"sort_field","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort Field"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string","pattern":"^(asc|desc)$","description":"Sort order (asc or desc)","default":"asc","title":"Sort Order"},"description":"Sort order (asc or desc)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get Change Orders as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get Change Orders as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Change Orders"],"summary":"Create Change Order","description":"Create a new change order with automatic branch creation.\n\nThis endpoint:\n1. Creates the Change Order on the main branch\n2. Automatically creates a `BR-{code}` branch for isolated work\n3. Returns the created Change Order\n\nThe auto-created branch allows changes to be developed in isolation\nbefore merging to main when approved.\n\nRequires create permission.","operationId":"create_change_order","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/next-code":{"get":{"tags":["Change Orders"],"summary":"Get Next Change Order Code","description":"Get the next available change order code.\n\nReturns the next sequential code in format CO-YYYY-NNN.\nCodes are scoped to the project and year.\n\nRequires read permission.","operationId":"get_next_change_order_code","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Project ID to scope the code","title":"Project Id"},"description":"Project ID to scope the code"},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Year for the code (defaults to current year)","title":"Year"},"description":"Year for the code (defaults to current year)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Get Next Change Order Code"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}":{"get":{"tags":["Change Orders"],"summary":"Read Change Order","description":"Get a specific change order by change_order_id (UUID root identifier).\n\nSupports time-travel queries via the as_of parameter to view\nthe change order's state at any historical point in time.\n\nRequires read permission.","operationId":"get_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get change order state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get change order state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Change Orders"],"summary":"Update Change Order","description":"Update a change order's metadata.\n\nCreates a new version with the updated metadata. Optionally specify a branch\nto update on a specific branch (will auto-fork from main if no version exists\non the target branch).\n\nRequires update permission.","operationId":"update_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Change Orders"],"summary":"Delete Change Order","description":"Soft delete a change order.\n\nMarks the current version as deleted.\n\nRequires delete permission.","operationId":"delete_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/by-code/{code}":{"get":{"tags":["Change Orders"],"summary":"Read Change Order By Code","description":"Get a change order by business code (e.g., \"CO-2026-001\").\n\nReturns the current active version on the specified branch.\n\nRequires read permission.","operationId":"get_change_order_by_code","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/history":{"get":{"tags":["Change Orders"],"summary":"Read Change Order History","description":"Get version history for a change order.\n\nReturns all versions across all branches, showing the complete\naudit trail of changes.\n\nRequires read permission.","operationId":"get_change_order_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ChangeOrderPublic"},"title":"Response Get Change Order History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/merge-conflicts":{"get":{"tags":["Change Orders"],"summary":"Get Merge Conflicts","description":"Check for merge conflicts between source and target branches.\n\nReturns a list of conflict details if conflicts exist, or an empty list if no conflicts.\n\nRequires read permission.","operationId":"get_merge_conflicts","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"source_branch","in":"query","required":true,"schema":{"type":"string","description":"Source branch name (e.g., 'BR-123')","title":"Source Branch"},"description":"Source branch name (e.g., 'BR-123')"},{"name":"target_branch","in":"query","required":false,"schema":{"type":"string","description":"Target branch name (default: 'main')","default":"main","title":"Target Branch"},"description":"Target branch name (default: 'main')"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Merge Conflicts"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/merge":{"post":{"tags":["Change Orders"],"summary":"Merge Change Order","description":"Merge a Change Order's branch into the target branch.\n\nInfers the source branch from the Change Order code (e.g., `BR-{code}`).\n\nChecks for merge conflicts before proceeding. If conflicts exist,\nreturns 409 with conflict details.\n\nRequires update permission.","operationId":"merge_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/revert":{"post":{"tags":["Change Orders"],"summary":"Revert Change Order","description":"Revert a Change Order to its previous version.\n\nRequires update permission.","operationId":"revert_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to revert on","default":"main","title":"Branch"},"description":"Branch to revert on"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/impact":{"get":{"tags":["Change Orders"],"summary":"Get Change Order Impact","description":"Get impact analysis for a change order by comparing branches.\n\nAnalyzes the financial and schedule impact of a change order by comparing\ndata between the main branch and the specified change branch.\n\nModes:\n- merged: Shows merged result (main + change delta) - most intuitive for users\n- isolated: Shows isolated comparison (delta only) - for detailed analysis\n\nReturns:\n - KPI Scorecard: BAC, Budget Delta, Gross Margin comparison\n - Entity Changes: Added/Modified/Removed WBEs and Cost Elements\n - Waterfall Chart: Cost bridge visualization\n - Time Series: Weekly S-curve budget comparison\n\nRequires read permission.","operationId":"get_change_order_impact","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch_name","in":"query","required":true,"schema":{"type":"string","description":"Branch name to compare (e.g., 'BR-CO-2026-001')","title":"Branch Name"},"description":"Branch name to compare (e.g., 'BR-CO-2026-001')"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Comparison mode: merged (main+change) or isolated (change only)","default":"merged","title":"Mode"},"description":"Comparison mode: merged (main+change) or isolated (change only)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get impact analysis as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get impact analysis as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImpactAnalysisResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/submit-for-approval":{"put":{"tags":["Change Orders"],"summary":"Submit Change Order For Approval","description":"Submit a change order for approval with impact calculation and approver assignment.\n\nThis endpoint:\n1. Calculates financial impact by comparing branches\n2. Determines impact level (LOW/MEDIUM/HIGH/CRITICAL)\n3. Assigns appropriate approver based on impact level\n4. Sets SLA deadline based on impact level\n5. Locks the branch to prevent further modifications\n6. Transitions status to \"Submitted for Approval\"\n\nRequires update permission.","operationId":"submit_change_order_for_approval","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"comment","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional comment for audit log","title":"Comment"},"description":"Optional comment for audit log"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for the operation (defaults to now)","title":"Control Date"},"description":"Control date for the operation (defaults to now)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/approve":{"put":{"tags":["Change Orders"],"summary":"Approve Change Order","description":"Approve a change order and transition to Approved status.\n\nValidates that the current user has sufficient authority to approve\nthis change order based on its impact level. Records approval with\noptional comments in the audit log.\n\nRequires approve permission.","operationId":"approve_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for the operation (defaults to now)","title":"Control Date"},"description":"Control date for the operation (defaults to now)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderApproval"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/reject":{"put":{"tags":["Change Orders"],"summary":"Reject Change Order","description":"Reject a change order and transition to Rejected status.\n\nValidates that the current user has sufficient authority to reject\nthis change order based on its impact level. Records rejection with\noptional comments in the audit log and unlocks the branch.\n\nRequires approve permission.","operationId":"reject_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for the operation (defaults to now)","title":"Control Date"},"description":"Control date for the operation (defaults to now)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderApproval"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/archive":{"post":{"tags":["Change Orders"],"summary":"Archive Change Order Branch","description":"Archive (soft-delete) a Change Order's branch.\n\nOnly allowed for Change Orders in \"Implemented\" or \"Rejected\" status.\nHides the branch from active lists while preserving history for\ntime-travel queries.\n\nRequires update permission.\n\nArgs:\n change_order_id: UUID of the change order\n\nReturns:\n Updated ChangeOrderPublic with current state\n\nRaises:\n HTTPException: 400 if status is not Implemented/Rejected, 404 if not found","operationId":"archive_change_order_branch","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/recover":{"post":{"tags":["Change Orders"],"summary":"Recover Change Order","description":"Recover a stuck change order workflow (admin only).\n\nAdmin-only endpoint to recover stuck workflows when impact analysis\nfails or the change order gets stuck in an intermediate state.\nAllows manual override of impact level and approver assignment.\n\nRequires change-order-recover permission (admin only).\n\nArgs:\n change_order_id: UUID of the stuck change order\n recovery_data: Recovery request with impact level, approver, and reason\n control_date: Optional control date for the operation (defaults to now)\n\nReturns:\n Updated ChangeOrder with recovered workflow state\n\nRaises:\n HTTPException: If change order not stuck, invalid data, or not authorized","operationId":"recover_change_order","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for the operation (defaults to now)","title":"Control Date"},"description":"Control date for the operation (defaults to now)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderRecoveryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeOrderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/{change_order_id}/approval-info":{"get":{"tags":["Change Orders"],"summary":"Get Change Order Approval Info","description":"Get approval information for a change order.\n\nReturns comprehensive approval information including:\n- Impact level and financial impact details\n- Assigned approver details\n- SLA tracking (assigned date, due date, status, business days remaining)\n- Whether the current user can approve this change order\n- Current user's authority level\n\nRequires read permission.","operationId":"get_change_order_approval_info","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"change_order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Change Order Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get approval info as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get approval info as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalInfoPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/change-orders/pending-approvals":{"get":{"tags":["Change Orders"],"summary":"Get Pending Approvals","description":"Get change orders pending approval for the current user.\n\nFilters change orders by:\n- assigned_approver_id = current_user.user_id\n- status in (\"Submitted for Approval\", \"Under Review\")\n- branch name (default: \"main\")\n\nReturns paginated list of change orders awaiting the user's approval.\n\nRequires read permission.","operationId":"get_pending_approvals","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch name","default":"main","title":"Branch"},"description":"Branch name"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forecasts":{"get":{"tags":["Forecasts"],"summary":"Read Forecasts","description":"Retrieve forecasts with pagination.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nForecasts now have a 1:1 relationship with Cost Elements.\nUse the cost element endpoints instead:\n- GET /api/v1/cost-elements/{cost_element_id}/forecast\n- PUT /api/v1/cost-elements/{cost_element_id}/forecast\n- DELETE /api/v1/cost-elements/{cost_element_id}/forecast","operationId":"get_forecasts","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"cost_element_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Cost Element ID","title":"Cost Element Id"},"description":"Filter by Cost Element ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Forecasts"],"summary":"Create Forecast","description":"Create a new forecast in specified branch.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nForecasts now have a 1:1 relationship with Cost Elements.\nUse: PUT /api/v1/cost-elements/{cost_element_id}/forecast","operationId":"create_forecast","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForecastCreate"}}}},"responses":{"410":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forecasts/{forecast_id}":{"get":{"tags":["Forecasts"],"summary":"Read Forecast","description":"Get a specific forecast by id and branch.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nForecasts now have a 1:1 relationship with Cost Elements.\nUse: GET /api/v1/cost-elements/{cost_element_id}/forecast","operationId":"get_forecast","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"forecast_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Forecast Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get forecast state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get forecast state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Forecasts"],"summary":"Update Forecast","description":"Update a forecast. Creates new version or forks.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nForecasts now have a 1:1 relationship with Cost Elements.\nUse: PUT /api/v1/cost-elements/{cost_element_id}/forecast","operationId":"update_forecast","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"forecast_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Forecast Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForecastUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Forecasts"],"summary":"Delete Forecast","description":"Soft delete a forecast in a branch.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nForecasts now have a 1:1 relationship with Cost Elements.\nUse: DELETE /api/v1/cost-elements/{cost_element_id}/forecast","operationId":"delete_forecast","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"forecast_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Forecast Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to delete from","default":"main","title":"Branch"},"description":"Branch to delete from"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"410":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forecasts/{forecast_id}/history":{"get":{"tags":["Forecasts"],"summary":"Get Forecast History","description":"Get full version history for a forecast across all branches.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nForecast history is still available via the cost element history endpoint.\nUse: GET /api/v1/cost-elements/{cost_element_id}/history","operationId":"get_forecast_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"forecast_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Forecast Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forecasts/{forecast_id}/comparison":{"get":{"tags":["Forecasts"],"summary":"Get Forecast Comparison","description":"Get EVM comparison metrics for a forecast.\n\n**DEPRECATED**: This endpoint is deprecated as of 2026-01-18.\n\nEVM metrics are now calculated via the cost element EVM endpoint.\nUse: GET /api/v1/cost-elements/{cost_element_id}/evm-metrics","operationId":"get_forecast_comparison","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"forecast_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Forecast Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schedule-baselines":{"get":{"tags":["Schedule Baselines"],"summary":"Read Schedule Baselines","description":"Retrieve schedule baselines with pagination.\n\nSupports time-travel queries and branch mode filtering.\nIn MERGE mode, combines results from current branch and main branch.","operationId":"get_schedule_baselines","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get schedule baselines as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get schedule baselines as of this timestamp (ISO 8601)"},{"name":"cost_element_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Cost Element ID","title":"Cost Element Id"},"description":"Filter by Cost Element ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Schedule Baselines"],"summary":"Create Schedule Baseline","description":"Create a new schedule baseline in specified branch.","operationId":"create_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBaselineCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBaselineRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schedule-baselines/{schedule_baseline_id}":{"get":{"tags":["Schedule Baselines"],"summary":"Read Schedule Baseline","description":"Get a specific schedule baseline by id and branch.\n\nSupports time-travel queries via the as_of parameter to view\nthe baseline's state at any historical point in time.","operationId":"get_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"schedule_baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Baseline Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get baseline state as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get baseline state as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBaselineRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Schedule Baselines"],"summary":"Update Schedule Baseline","description":"Update a schedule baseline. Creates new version or forks.","operationId":"update_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"schedule_baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Baseline Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBaselineUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleBaselineRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Schedule Baselines"],"summary":"Delete Schedule Baseline","description":"Soft delete a schedule baseline in a branch.","operationId":"delete_schedule_baseline","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"schedule_baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Baseline Id"}},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to delete from","default":"main","title":"Branch"},"description":"Branch to delete from"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Optional control date for deletion","title":"Control Date"},"description":"Optional control date for deletion"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schedule-baselines/{schedule_baseline_id}/history":{"get":{"tags":["Schedule Baselines"],"summary":"Get Schedule Baseline History","description":"Get full version history for a schedule baseline across all branches.","operationId":"get_schedule_baseline_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"schedule_baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Baseline Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleBaselineRead"},"title":"Response Get Schedule Baseline History"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/schedule-baselines/{schedule_baseline_id}/pv":{"get":{"tags":["Schedule Baselines"],"summary":"Calculate Planned Value","description":"Calculate Planned Value (PV) for a schedule baseline.\n\nPV = BAC × Progress\n\nWhere Progress is calculated based on the baseline's progression type\n(LINEAR, GAUSSIAN, or LOGARITHMIC) and the current date relative to\nthe baseline's start and end dates.\n\nArgs:\n schedule_baseline_id: The baseline to calculate PV for\n current_date: The date to calculate progress for\n bac: Budget at Completion (total planned budget)\n branch: Branch to query (default: \"main\")\n\nReturns:\n Dictionary with:\n - schedule_baseline_id: The baseline ID\n - current_date: The date used for calculation\n - bac: Budget at Completion\n - progress: Progress value (0.0 to 1.0)\n - pv: Planned Value (BAC × Progress)\n - progression_type: Type of progression used","operationId":"calculate_planned_value","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"schedule_baseline_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Baseline Id"}},{"name":"current_date","in":"query","required":true,"schema":{"type":"string","format":"date-time","description":"Date to calculate PV for (ISO 8601)","title":"Current Date"},"description":"Date to calculate PV for (ISO 8601)"},{"name":"bac","in":"query","required":true,"schema":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"description":"Budget at Completion (BAC) amount","title":"Bac"},"description":"Budget at Completion (BAC) amount"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Calculate Planned Value"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/progress-entries":{"get":{"tags":["Progress Entries"],"summary":"Read Progress Entries","description":"Retrieve progress entries with filtering and pagination.\n\nProgress entries track work completion percentage for cost elements.\nThey are versionable but NOT branchable (progress is global facts).\nBranch and mode parameters are provided for API consistency and context,\nthough progress entries themselves are not branch-specific.\n\nFiltering priority: cost_element_id > wbe_id > project_id.\nAt least one filter is recommended for scoped queries.","operationId":"get_progress_entries","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query (for context)","default":"main","title":"Branch"},"description":"Branch to query (for context)"},{"name":"mode","in":"query","required":false,"schema":{"type":"string","pattern":"^(merged|isolated)$","description":"Branch mode: merged (combine with main) or isolated (current branch only)","default":"merged","title":"Mode"},"description":"Branch mode: merged (combine with main) or isolated (current branch only)"},{"name":"cost_element_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Cost Element ID","title":"Cost Element Id"},"description":"Filter by Cost Element ID"},{"name":"wbe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by WBE ID (aggregates across all cost elements)","title":"Wbe Id"},"description":"Filter by WBE ID (aggregates across all cost elements)"},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by Project ID (aggregates across all WBEs and cost elements)","title":"Project Id"},"description":"Filter by Project ID (aggregates across all WBEs and cost elements)"},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get Progress Entries as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get Progress Entries as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Progress Entries"],"summary":"Create Progress Entry","description":"Create a new progress entry.\n\nProgress entries track work completion percentage (0-100%) for cost elements.\nThis enables Earned Value Management (EVM) calculations.\n\nValidation:\n- progress_percentage must be between 0 and 100\n- cost_element_id must reference an existing cost element\n- control_date determines when the progress was measured (defaults to now)","operationId":"create_progress_entry","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressEntryCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressEntryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/progress-entries/{progress_entry_id}":{"get":{"tags":["Progress Entries"],"summary":"Read Progress Entry","description":"Retrieve a specific progress entry by ID.\n\nSupports time-travel queries via the as_of parameter.","operationId":"get_progress_entry","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"progress_entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Progress Entry Id"}},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get Progress Entry as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get Progress Entry as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressEntryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Progress Entries"],"summary":"Update Progress Entry","description":"Update a progress entry.\n\nCreates a new version of the progress entry with the updated values.\nProgress can be increased or decreased (decreases should include justification in notes).\n\nThe system will maintain full version history for audit trails.","operationId":"update_progress_entry","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"progress_entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Progress Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressEntryUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProgressEntryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Progress Entries"],"summary":"Delete Progress Entry","description":"Soft delete a progress entry.\n\nMarks the progress entry as deleted but preserves it in the database\nfor audit purposes. The entry can be restored if needed.","operationId":"delete_progress_entry","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"progress_entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Progress Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/progress-entries/cost-element/{cost_element_id}/latest":{"get":{"tags":["Progress Entries"],"summary":"Read Latest Progress","description":"Retrieve the latest progress entry for a cost element.\n\nReturns the most recent progress entry based on valid_time.\nSupports time-travel queries via the as_of parameter.\n\nReturns None if no progress has been reported for the cost element.","operationId":"get_latest_progress","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Time travel: get latest progress as of this timestamp (ISO 8601)","title":"As Of"},"description":"Time travel: get latest progress as of this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ProgressEntryRead"},{"type":"null"}],"title":"Response Get Latest Progress"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/progress-entries/cost-element/{cost_element_id}/history":{"get":{"tags":["Progress Entries"],"summary":"Read Progress History","description":"Retrieve progress history for a cost element.\n\nReturns all progress entries for the specified cost element,\nordered by valid_time descending (most recent first).\n\nUseful for generating progress charts and historical analysis.","operationId":"get_progress_history","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"cost_element_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cost Element Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evm/{entity_type}/{entity_id}/metrics":{"get":{"tags":["EVM"],"summary":"Get Evm Metrics","description":"Get EVM metrics for any entity type.\n\nReturns comprehensive EVM analysis including:\n- BAC: Budget at Completion (total planned budget)\n- PV: Planned Value (budgeted cost of work scheduled)\n- AC: Actual Cost (cost incurred to date)\n- EV: Earned Value (budgeted cost of work performed)\n- CV: Cost Variance (EV - AC, negative = over budget)\n- SV: Schedule Variance (EV - PV, negative = behind schedule)\n- CPI: Cost Performance Index (EV / AC, < 1.0 = over budget)\n- SPI: Schedule Performance Index (EV / PV, < 1.0 = behind schedule)\n- EAC: Estimate at Completion (from forecast)\n- VAC: Variance at Completion (BAC - EAC)\n- ETC: Estimate to Complete (EAC - AC)\n\nTime-Travel & Branching:\n- All metrics respect time-travel: entities are fetched as they were at control_date\n- Branch mode (STRICT/MERGE) controls parent branch fallback behavior\n- Cost registrations and progress entries are global facts (not branchable)\n\nSupports entity types:\n- cost_element: Individual cost element metrics\n- wbe: Work Breakdown Element (aggregated from child cost elements)\n- project: Project-level metrics (aggregated from all child elements)\n\nWarning: Returns EV = 0 with warning message if no progress has been reported.","operationId":"get_generic_evm_metrics","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"entity_type","in":"path","required":true,"schema":{"$ref":"#/components/schemas/EntityType"}},{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for time-travel query (ISO 8601, defaults to now). All entities are fetched as they were at this valid_time.","title":"Control Date"},"description":"Control date for time-travel query (ISO 8601, defaults to now). All entities are fetched as they were at this valid_time."},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"branch_mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/BranchMode","description":"Branch mode: STRICT (only this branch) or MERGE (fall back to parent branches)","default":"merge"},"description":"Branch mode: STRICT (only this branch) or MERGE (fall back to parent branches)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EVMMetricsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evm/{entity_type}/{entity_id}/timeseries":{"get":{"tags":["EVM"],"summary":"Get Evm Timeseries","description":"Get historical EVM metrics as time-series data for charts.\n\nGenerates a time-series of EVM metrics (PV, EV, AC) over a date range\nwith server-side aggregation at the specified granularity (day, week, month).\n\nThe date range is context-dependent:\n- Cost element: Uses its schedule baseline date range\n- Project: From project start to max(project end, control_date)\n\nTime-Travel & Branching:\n- All metrics respect time-travel: entities are fetched as they were at control_date\n- Branch mode (ISOLATED/MERGE) controls parent branch fallback behavior\n\nSupports entity types:\n- cost_element: Individual cost element time-series\n- wbe: Work Breakdown Element (aggregated from children)\n- project: Project-level time-series\n\nReturns:\n EVMTimeSeriesResponse with aggregated time-series data","operationId":"get_generic_evm_timeseries","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"entity_type","in":"path","required":true,"schema":{"$ref":"#/components/schemas/EntityType"}},{"name":"entity_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entity Id"}},{"name":"granularity","in":"query","required":false,"schema":{"$ref":"#/components/schemas/EVMTimeSeriesGranularity","description":"Time granularity for aggregation (day, week, month)","default":"week"},"description":"Time granularity for aggregation (day, week, month)"},{"name":"control_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Control date for time-travel query (ISO 8601, defaults to now).","title":"Control Date"},"description":"Control date for time-travel query (ISO 8601, defaults to now)."},{"name":"branch","in":"query","required":false,"schema":{"type":"string","description":"Branch to query","default":"main","title":"Branch"},"description":"Branch to query"},{"name":"branch_mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/BranchMode","description":"Branch mode: STRICT (only this branch) or MERGE (fall back to parent branches)","default":"merge"},"description":"Branch mode: STRICT (only this branch) or MERGE (fall back to parent branches)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EVMTimeSeriesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evm/batch":{"post":{"tags":["EVM"],"summary":"Get Evm Batch","description":"Get aggregated EVM metrics for multiple entities.\n\nCalculates EVM metrics for each entity individually, then aggregates them:\n- Sums amount fields (BAC, PV, AC, EV, CV, SV, EAC, VAC, ETC)\n- Calculates BAC-weighted average for indices (CPI, SPI)\n\nRequest body:\n entity_type: Type of entities (cost_element, wbe, project)\n entity_ids: List of entity IDs to calculate metrics for\n control_date: Optional control date for time-travel (defaults to now)\n branch: Branch name (defaults to \"main\")\n branch_mode: Branch isolation mode (defaults to \"merge\")\n\nSupports entity types:\n- cost_element: Aggregate multiple cost elements\n- wbe: Aggregate multiple WBEs (not yet implemented)\n- project: Aggregate multiple projects (not yet implemented)\n\nReturns:\n EVMMetricsResponse with aggregated metrics","operationId":"get_evm_batch_metrics","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Request Data"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EVMMetricsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/ai/config/providers":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"List Providers","description":"List all AI providers.","operationId":"list_ai_providers","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIProviderPublic"},"title":"Response List Ai Providers"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AI Configuration","AI Configuration"],"summary":"Create Provider","description":"Create a new AI provider.","operationId":"create_ai_provider","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/providers/{provider_id}":{"put":{"tags":["AI Configuration","AI Configuration"],"summary":"Update Provider","description":"Update an AI provider.","operationId":"update_ai_provider","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["AI Configuration","AI Configuration"],"summary":"Delete Provider","description":"Delete an AI provider.","operationId":"delete_ai_provider","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/providers/{provider_id}/configs":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"List Provider Configs","description":"List all configs for a provider.","operationId":"list_provider_configs","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIProviderConfigPublic"},"title":"Response List Provider Configs"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AI Configuration","AI Configuration"],"summary":"Set Provider Config","description":"Set a provider config value.","operationId":"set_provider_config","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderConfigCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderConfigPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/providers/{provider_id}/configs/{key}":{"delete":{"tags":["AI Configuration","AI Configuration"],"summary":"Delete Provider Config","description":"Delete a provider config.","operationId":"delete_provider_config","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/models":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"List All Models","description":"List all AI models across all providers.","operationId":"list_all_models","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIModelPublic"},"title":"Response List All Models"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/providers/{provider_id}/models":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"List Provider Models","description":"List all models for a provider.","operationId":"list_provider_models","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}},{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIModelPublic"},"title":"Response List Provider Models"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AI Configuration","AI Configuration"],"summary":"Create Model","description":"Create a new AI model for a provider.","operationId":"create_ai_model","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIModelCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIModelPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/providers/{provider_id}/models/{model_id}":{"put":{"tags":["AI Configuration","AI Configuration"],"summary":"Update Model","description":"Update an AI model.","operationId":"update_ai_model","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}},{"name":"model_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Model Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIModelUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIModelPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["AI Configuration","AI Configuration"],"summary":"Delete Model","description":"Delete an AI model.","operationId":"delete_ai_model","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}},{"name":"model_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Model Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/assistants":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"List Assistant Configs","description":"List all assistant configurations.","operationId":"list_assistant_configs","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIAssistantConfigPublic"},"title":"Response List Assistant Configs"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AI Configuration","AI Configuration"],"summary":"Create Assistant Config","description":"Create a new assistant configuration.","operationId":"create_assistant_config","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIAssistantConfigCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIAssistantConfigPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/assistants/{assistant_config_id}":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"Get Assistant Config","description":"Get a specific assistant configuration.","operationId":"get_assistant_config","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"assistant_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Assistant Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIAssistantConfigPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["AI Configuration","AI Configuration"],"summary":"Update Assistant Config","description":"Update an assistant configuration.","operationId":"update_assistant_config","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"assistant_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Assistant Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIAssistantConfigUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIAssistantConfigPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["AI Configuration","AI Configuration"],"summary":"Delete Assistant Config","description":"Delete an assistant configuration.","operationId":"delete_assistant_config","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"assistant_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Assistant Config Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/config/tools":{"get":{"tags":["AI Configuration","AI Configuration"],"summary":"List Ai Tools","description":"List all available AI tools.\n\nImports and registers all tool templates before querying the registry.","operationId":"list_ai_tools","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AIToolPublic"},"type":"array","title":"Response List Ai Tools"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/ai/chat/sessions":{"get":{"tags":["AI Chat","AI Chat"],"summary":"List Sessions","description":"List conversation sessions for the current user.\n\nIncludes active agent execution status for each session, allowing\nthe frontend to display running indicators in the session list.\n\nArgs:\n context_type: Optional context type filter (general, project, wbe, cost_element)\n context_id: Optional entity ID filter for scoped context","operationId":"list_ai_sessions","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"context_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by context type (general, project, wbe, cost_element)","title":"Context Type"},"description":"Filter by context type (general, project, wbe, cost_element)"},{"name":"context_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by specific entity ID (e.g., project UUID, WBE ID)","title":"Context Id"},"description":"Filter by specific entity ID (e.g., project UUID, WBE ID)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIConversationSessionPublic"},"title":"Response List Ai Sessions"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/sessions/paginated":{"get":{"tags":["AI Chat","AI Chat"],"summary":"List Sessions Paginated","description":"List chat sessions with pagination.\n\nArgs:\n skip: Number of sessions to skip (default: 0)\n limit: Sessions per page (default: 10, max: 50)\n context_type: Optional context type filter (general, project, wbe, cost_element)\n context_id: Optional entity ID filter for scoped context\n current_user: Authenticated user (injected)\n config_service: AI config service (injected)\n\nReturns:\n Paginated response with sessions, has_more flag, and total_count","operationId":"list_ai_sessions_paginated","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"context_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by context type (general, project, wbe, cost_element)","title":"Context Type"},"description":"Filter by context type (general, project, wbe, cost_element)"},{"name":"context_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by specific entity ID (e.g., project UUID, WBE ID)","title":"Context Id"},"description":"Filter by specific entity ID (e.g., project UUID, WBE ID)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIConversationSessionPaginated"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/sessions/{session_id}/messages":{"get":{"tags":["AI Chat","AI Chat"],"summary":"Get Session Messages","description":"Get messages for a conversation session.","operationId":"list_ai_session_messages","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AIConversationMessagePublic"},"title":"Response List Ai Session Messages"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/sessions/{session_id}":{"delete":{"tags":["AI Chat","AI Chat"],"summary":"Delete Session","description":"Delete a conversation session.","operationId":"delete_ai_session","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/sessions/{session_id}/invoke":{"post":{"tags":["AI Chat","AI Chat"],"summary":"Invoke Agent","description":"Invoke an agent execution for a conversation session.\n\nDerives the assistant_config_id from the session's relationship.\nStarts a background agent run that can be polled via the status endpoint.","operationId":"invoke_agent","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvokeAgentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentExecutionPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/sessions/{session_id}/executions":{"get":{"tags":["AI Chat","AI Chat"],"summary":"List Session Executions","description":"List agent executions for a conversation session.","operationId":"list_session_executions","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentExecutionPublic"},"title":"Response List Session Executions"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/executions/{execution_id}/status":{"get":{"tags":["AI Chat","AI Chat"],"summary":"Get Execution Status","description":"Get the status of an agent execution.\n\nVerifies ownership by checking the execution's session belongs to\nthe current user.","operationId":"get_execution_status","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"execution_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Execution Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentExecutionPublic"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/executions/{execution_id}/approve":{"post":{"tags":["AI Chat","AI Chat"],"summary":"Approve Execution","description":"Approve or reject a tool execution via REST.\n\nAllows approving/rejecting a pending tool execution without an active\nWebSocket connection. Looks up the InterruptNode for the execution's\nsession and registers the approval response.\n\nArgs:\n execution_id: UUID of the execution to approve.\n body: ApprovalRequest with approval_id and approved flag.\n current_user: Authenticated user (injected).\n db: Database session (injected).\n\nReturns:\n Dict with status and approved flag.\n\nRaises:\n HTTPException: 404 if execution not found, 400 if approval registration fails.","operationId":"approve_execution","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"execution_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Execution Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApprovalRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Approve Execution"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/chat/upload-image":{"post":{"tags":["AI Upload","AI Upload"],"summary":"Upload Image","description":"Upload an image for AI chat.\n\nReads the image bytes, base64-encodes them, and returns the encoded\ncontent for inline use in chat messages. No disk storage is used.\n\nArgs:\n file: Image file to upload (PNG, JPG, JPEG)\n current_user: Authenticated user\n\nReturns:\n ImageUploadResponse with base64-encoded content and metadata\n\nRaises:\n HTTPException 400: Invalid file type or size","operationId":"upload_ai_image","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_ai_image"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/ai/chat/upload-file":{"post":{"tags":["AI Upload","AI Upload"],"summary":"Upload File","description":"Upload a file attachment for AI chat.\n\nReads the file bytes, extracts text content using the appropriate\nextractor, and returns it for inline use in chat messages.\nNo disk storage is used.\n\nArgs:\n file: Document file to upload\n current_user: Authenticated user\n\nReturns:\n FileUploadResponse with extracted text content and metadata\n\nRaises:\n HTTPException 400: Invalid file type, size, or extraction failure","operationId":"upload_ai_file","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_ai_file"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/dashboard/recent-activity":{"get":{"tags":["Dashboard"],"summary":"Get Dashboard Recent Activity","description":"Get dashboard data with recent activity and project spotlight.\n\nReturns aggregated dashboard data including:\n- Last edited project with metrics (budget, WBEs, cost elements, change orders)\n- Recent activity across Projects, WBEs, Cost Elements, and Change Orders\n\nThe activity_limit parameter controls how many recent items to return per\nentity type (default: 10, max: 50).\n\nRequires authentication.","operationId":"get_dashboard_recent_activity","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"activity_limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"description":"Maximum number of activities per entity type (1-50)","default":10,"title":"Activity Limit"},"description":"Maximum number of activities per entity type (1-50)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardData"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard-layouts":{"get":{"tags":["Dashboard Layouts"],"summary":"List Dashboard Layouts","description":"List dashboard layouts for the current user, optionally filtered by project.","operationId":"list_dashboard_layouts","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DashboardLayoutRead"},"title":"Response List Dashboard Layouts"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Dashboard Layouts"],"summary":"Create Dashboard Layout","description":"Create a new dashboard layout.","operationId":"create_dashboard_layout","security":[{"OAuth2PasswordBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard-layouts/templates":{"get":{"tags":["Dashboard Layouts"],"summary":"List Dashboard Layout Templates","description":"List all template dashboard layouts.","operationId":"list_dashboard_layout_templates","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DashboardLayoutRead"},"type":"array","title":"Response List Dashboard Layout Templates"}}}}},"security":[{"OAuth2PasswordBearer":[]}]}},"/api/v1/dashboard-layouts/{layout_id}":{"get":{"tags":["Dashboard Layouts"],"summary":"Get Dashboard Layout","description":"Get a specific dashboard layout by ID.","operationId":"get_dashboard_layout","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"layout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layout Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Dashboard Layouts"],"summary":"Update Dashboard Layout","description":"Update an existing dashboard layout.","operationId":"update_dashboard_layout","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"layout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layout Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Dashboard Layouts"],"summary":"Delete Dashboard Layout","description":"Delete a dashboard layout.","operationId":"delete_dashboard_layout","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"layout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layout Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard-layouts/{layout_id}/clone":{"post":{"tags":["Dashboard Layouts"],"summary":"Clone Dashboard Layout Template","description":"Clone a template dashboard layout for the current user.","operationId":"clone_dashboard_layout_template","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"layout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layout Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneTemplateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard-layouts/templates/{layout_id}":{"put":{"tags":["Dashboard Layouts"],"summary":"Update Dashboard Layout Template","description":"Update a template dashboard layout (admin only).\n\nAllows administrators to modify template layouts. Non-admin users\nreceive a 403 response from the RoleChecker dependency.","operationId":"update_dashboard_layout_template","security":[{"OAuth2PasswordBearer":[]}],"parameters":[{"name":"layout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layout Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardLayoutRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AIAssistantConfigCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"model_id":{"type":"string","format":"uuid","title":"Model Id"},"system_prompt":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"System Prompt"},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature"},"max_tokens":{"anyOf":[{"type":"integer","maximum":200000.0,"minimum":1.0},{"type":"null"}],"title":"Max Tokens"},"recursion_limit":{"anyOf":[{"type":"integer","maximum":500.0,"minimum":1.0},{"type":"null"}],"title":"Recursion Limit","description":"LangGraph recursion limit (maximum steps in agent execution loop)"},"allowed_tools":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Tools","description":"List of tool names this assistant can use"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["name","model_id"],"title":"AIAssistantConfigCreate","description":"Schema for creating an assistant config."},"AIAssistantConfigPublic":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"model_id":{"type":"string","format":"uuid","title":"Model Id"},"system_prompt":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"System Prompt"},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature"},"max_tokens":{"anyOf":[{"type":"integer","maximum":200000.0,"minimum":1.0},{"type":"null"}],"title":"Max Tokens"},"recursion_limit":{"anyOf":[{"type":"integer","maximum":500.0,"minimum":1.0},{"type":"null"}],"title":"Recursion Limit","description":"LangGraph recursion limit (maximum steps in agent execution loop)"},"allowed_tools":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Tools","description":"List of tool names this assistant can use"},"is_active":{"type":"boolean","title":"Is Active","default":true},"id":{"type":"string","format":"uuid","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["name","model_id","id","created_at","updated_at"],"title":"AIAssistantConfigPublic","description":"Schema for reading assistant config."},"AIAssistantConfigUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"system_prompt":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"System Prompt"},"temperature":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Temperature"},"max_tokens":{"anyOf":[{"type":"integer","maximum":200000.0,"minimum":1.0},{"type":"null"}],"title":"Max Tokens"},"recursion_limit":{"anyOf":[{"type":"integer","maximum":500.0,"minimum":1.0},{"type":"null"}],"title":"Recursion Limit"},"allowed_tools":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Tools"},"model_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Model Id"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"AIAssistantConfigUpdate","description":"Schema for updating an assistant config."},"AIConversationMessagePublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"role":{"type":"string","title":"Role"},"content":{"type":"string","title":"Content"},"content_format":{"type":"string","enum":["text","markdown","mermaid","code"],"title":"Content Format","description":"Format of the content","default":"text"},"tool_calls":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Tool Calls"},"tool_results":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Tool Results"},"attachments":{"items":{"$ref":"#/components/schemas/FileAttachment"},"type":"array","title":"Attachments","description":"File attachments"},"images":{"items":{"type":"string"},"type":"array","title":"Images","description":"Image URLs"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","description":"Additional message metadata"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","session_id","role","content","created_at"],"title":"AIConversationMessagePublic","description":"Schema for reading conversation message."},"AIConversationSessionPaginated":{"properties":{"sessions":{"items":{"$ref":"#/components/schemas/AIConversationSessionPublic"},"type":"array","title":"Sessions"},"has_more":{"type":"boolean","title":"Has More"},"total_count":{"type":"integer","title":"Total Count"}},"type":"object","required":["sessions","has_more","total_count"],"title":"AIConversationSessionPaginated","description":"Paginated response for conversation sessions."},"AIConversationSessionPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"assistant_config_id":{"type":"string","format":"uuid","title":"Assistant Config Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id","description":"Optional project context"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id","description":"Optional branch or change order context"},"context":{"anyOf":[{"$ref":"#/components/schemas/SessionContext"},{"type":"null"}],"description":"Session context (general, project, wbe, cost_element)"},"active_execution":{"anyOf":[{"$ref":"#/components/schemas/AgentExecutionPublic"},{"type":"null"}],"description":"Currently active agent execution, if any"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","assistant_config_id","title","created_at","updated_at"],"title":"AIConversationSessionPublic","description":"Schema for reading conversation session."},"AIModelCreate":{"properties":{"model_id":{"type":"string","maxLength":100,"title":"Model Id"},"display_name":{"type":"string","maxLength":255,"title":"Display Name"},"is_active":{"type":"boolean","title":"Is Active","default":true},"provider_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Provider Id","description":"Provider ID (injected from path)"}},"type":"object","required":["model_id","display_name"],"title":"AIModelCreate","description":"Schema for creating an AI model.\n\nWhen creating via API endpoint, provider_id comes from the URL path\nparameter and is injected by the route handler."},"AIModelPublic":{"properties":{"model_id":{"type":"string","maxLength":100,"title":"Model Id"},"display_name":{"type":"string","maxLength":255,"title":"Display Name"},"is_active":{"type":"boolean","title":"Is Active","default":true},"id":{"type":"string","format":"uuid","title":"Id"},"provider_id":{"type":"string","format":"uuid","title":"Provider Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["model_id","display_name","id","provider_id","created_at","updated_at"],"title":"AIModelPublic","description":"Schema for reading AI model."},"AIModelUpdate":{"properties":{"model_id":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Model Id"},"display_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Display Name"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"AIModelUpdate","description":"Schema for updating an AI model."},"AIProviderConfigCreate":{"properties":{"key":{"type":"string","maxLength":100,"title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"is_encrypted":{"type":"boolean","title":"Is Encrypted","default":false}},"type":"object","required":["key"],"title":"AIProviderConfigCreate","description":"Schema for creating a provider config."},"AIProviderConfigPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider_id":{"type":"string","format":"uuid","title":"Provider Id"},"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value","description":"***MASKED***"},"is_encrypted":{"type":"boolean","title":"Is Encrypted"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","provider_id","key","is_encrypted","created_at","updated_at"],"title":"AIProviderConfigPublic","description":"Schema for reading provider config (values masked if encrypted)."},"AIProviderCreate":{"properties":{"provider_type":{"type":"string","maxLength":50,"title":"Provider Type"},"name":{"type":"string","maxLength":255,"title":"Name"},"base_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Base Url"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["provider_type","name"],"title":"AIProviderCreate","description":"Schema for creating an AI provider."},"AIProviderPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider_type":{"type":"string","title":"Provider Type"},"name":{"type":"string","title":"Name"},"base_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Url"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","provider_type","name","base_url","is_active","created_at","updated_at"],"title":"AIProviderPublic","description":"Schema for reading AI provider (sensitive data masked)."},"AIProviderUpdate":{"properties":{"provider_type":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Provider Type"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"base_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Base Url"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"AIProviderUpdate","description":"Schema for updating an AI provider."},"AIToolPublic":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"permissions":{"items":{"type":"string"},"type":"array","title":"Permissions"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"version":{"type":"string","title":"Version"}},"type":"object","required":["name","description","permissions","version"],"title":"AIToolPublic","description":"Schema for returning AI tool metadata."},"AgentExecutionPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"session_id":{"type":"string","format":"uuid","title":"Session Id"},"status":{"type":"string","title":"Status"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"execution_mode":{"type":"string","title":"Execution Mode","default":"standard"},"total_tokens":{"type":"integer","title":"Total Tokens","default":0},"tool_calls_count":{"type":"integer","title":"Tool Calls Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","session_id","status","started_at","created_at","updated_at"],"title":"AgentExecutionPublic","description":"Schema for reading agent execution records."},"AgingChangeOrder":{"properties":{"change_order_id":{"type":"string","format":"uuid","title":"Change Order Id","description":"Change Order ID (UUID)"},"code":{"type":"string","title":"Code","description":"Business identifier (e.g., CO-2026-001)"},"title":{"type":"string","title":"Title","description":"Change order title"},"status":{"type":"string","title":"Status","description":"Current status"},"days_in_status":{"type":"integer","title":"Days In Status","description":"Number of days in current status"},"impact_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact Level","description":"Impact level (LOW/MEDIUM/HIGH/CRITICAL)"},"sla_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sla Status","description":"SLA status (pending/approaching/overdue)"}},"type":"object","required":["change_order_id","code","title","status","days_in_status"],"title":"AgingChangeOrder","description":"Change order that is stuck or aging."},"ApprovalInfoPublic":{"properties":{"impact_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact Level","description":"Financial impact level (LOW/MEDIUM/HIGH/CRITICAL)"},"financial_impact":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Financial Impact","description":"Financial impact details (budget_delta, revenue_delta)"},"assigned_approver":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Assigned Approver","description":"Assigned approver details"},"sla_assigned_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Assigned At","description":"When the approval SLA started"},"sla_due_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Due Date","description":"SLA deadline for approval"},"sla_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sla Status","description":"Current SLA tracking status (pending/approaching/overdue)"},"sla_business_days_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sla Business Days Remaining","description":"Number of business days remaining until SLA deadline"},"user_can_approve":{"type":"boolean","title":"User Can Approve","description":"Whether the current user has authority to approve this change order","default":false},"user_authority_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Authority Level","description":"Current user's authority level (LOW/MEDIUM/HIGH/CRITICAL)"}},"type":"object","title":"ApprovalInfoPublic","description":"Schema for approval information response."},"ApprovalRequest":{"properties":{"approval_id":{"type":"string","title":"Approval Id","description":"UUID of the approval request"},"approved":{"type":"boolean","title":"Approved","description":"True to approve, False to reject"}},"type":"object","required":["approval_id","approved"],"title":"ApprovalRequest","description":"Request body for approving/rejecting a tool execution via REST."},"ApprovalWorkloadItem":{"properties":{"approver_id":{"type":"string","format":"uuid","title":"Approver Id","description":"User ID of the approver"},"approver_name":{"type":"string","title":"Approver Name","description":"Full name of the approver"},"pending_count":{"type":"integer","title":"Pending Count","description":"Number of pending approvals","default":0},"overdue_count":{"type":"integer","title":"Overdue Count","description":"Number of overdue approvals (past SLA deadline)","default":0},"avg_days_waiting":{"type":"number","title":"Avg Days Waiting","description":"Average days waiting for approval","default":0.0}},"type":"object","required":["approver_id","approver_name"],"title":"ApprovalWorkloadItem","description":"Pending approval workload by approver."},"Body_login":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"^password$"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","format":"password","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"format":"password","title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_login"},"Body_upload_ai_file":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"Document file (PDF, DOCX, XLSX, PPTX, TXT, CSV, JSON, MD, max 10MB)"}},"type":"object","required":["file"],"title":"Body_upload_ai_file"},"Body_upload_ai_image":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"Image file (PNG, JPG, JPEG, max 5MB)"}},"type":"object","required":["file"],"title":"Body_upload_ai_image"},"BranchMode":{"type":"string","enum":["strict","merge"],"title":"BranchMode","description":"Branch resolution mode for time-travel queries.\n\nControls how entity lookups handle branch isolation:\n- STRICT: Only return entities from the specified branch\n- MERGE: Fall back to main branch if entity not found on specified branch"},"BranchPublic":{"properties":{"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id","description":"Unique branch ID"},"name":{"type":"string","title":"Name","description":"Branch name (e.g. 'main' or 'BR-CO-123')"},"type":{"type":"string","enum":["main","change_order"],"title":"Type","description":"Type of branch"},"is_default":{"type":"boolean","title":"Is Default","description":"Whether this is the default branch","default":false},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"When branch was created"},"change_order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Change Order Id","description":"Root ID of the associated change order"},"change_order_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change Order Code","description":"Business code of the change order"},"change_order_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change Order Status","description":"Status of the change order"}},"type":"object","required":["name","type"],"title":"BranchPublic","description":"Schema for a branch option."},"ChangeOrderApproval":{"properties":{"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments","description":"Optional comments explaining the approval/rejection decision"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Control date for the workflow operation (defaults to now)"}},"type":"object","title":"ChangeOrderApproval","description":"Schema for approving or rejecting a change order."},"ChangeOrderCreate":{"properties":{"code":{"type":"string","maxLength":50,"minLength":1,"title":"Code","description":"Business identifier (e.g., CO-2026-001)"},"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"Project this change applies to"},"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title","description":"Brief title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Detailed description"},"justification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Justification","description":"Business justification"},"effective_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Effective Date","description":"When change takes effect"},"status":{"$ref":"#/components/schemas/ChangeOrderStatus","description":"Workflow state","default":"Draft"},"impact_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact Level","description":"Financial impact level"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Control date for bitemporal operations"},"assigned_approver_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Approver Id","description":"Assigned approver"},"sla_assigned_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Assigned At","description":"SLA assigned timestamp"},"sla_due_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Due Date","description":"SLA due date"},"sla_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sla Status","description":"SLA status"}},"type":"object","required":["code","project_id","title"],"title":"ChangeOrderCreate","description":"Schema for creating a new Change Order."},"ChangeOrderImpactStats":{"properties":{"impact_level":{"type":"string","title":"Impact Level","description":"Impact level (LOW/MEDIUM/HIGH/CRITICAL)"},"count":{"type":"integer","title":"Count","description":"Number of change orders at this impact level"},"total_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Total Value","description":"Total cost exposure for COs at this impact level"}},"type":"object","required":["impact_level","count"],"title":"ChangeOrderImpactStats","description":"Statistics by impact level."},"ChangeOrderPublic":{"properties":{"code":{"type":"string","maxLength":50,"minLength":1,"title":"Code","description":"Business identifier (e.g., CO-2026-001)"},"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"Project this change applies to"},"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title","description":"Brief title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Detailed description"},"justification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Justification","description":"Business justification"},"effective_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Effective Date","description":"When change takes effect"},"status":{"$ref":"#/components/schemas/ChangeOrderStatus","description":"Workflow state","default":"Draft"},"impact_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact Level","description":"Financial impact level (LOW/MEDIUM/HIGH/CRITICAL)"},"change_order_id":{"type":"string","format":"uuid","title":"Change Order Id","description":"Root UUID identifier"},"id":{"type":"string","format":"uuid","title":"Id","description":"Version ID (primary key)"},"created_by":{"type":"string","format":"uuid","title":"Created By","description":"User who created this version"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"When this version was created (derived from transaction_time)"},"updated_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Updated By","description":"User who last updated"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At","description":"When last updated"},"branch":{"type":"string","title":"Branch","description":"Branch name"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name","description":"Change branch name for impact analysis (e.g., BR-CO-2026-001)"},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Id","description":"Parent version ID"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deleted At","description":"Soft delete timestamp"},"available_transitions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Available Transitions","description":"Valid workflow status transitions from current state"},"can_edit_status":{"type":"boolean","title":"Can Edit Status","description":"Whether Change Order status can be edited in current state","default":true},"branch_locked":{"type":"boolean","title":"Branch Locked","description":"Whether the associated branch is locked","default":false},"assigned_approver_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned Approver Id","description":"User ID assigned to approve this change order"},"sla_assigned_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Assigned At","description":"When the approval SLA started"},"sla_due_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Due Date","description":"SLA deadline for approval"},"sla_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sla Status","description":"Current SLA tracking status (pending/approaching/overdue)"},"assigned_approver":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Assigned Approver","description":"Assigned approver details (user_id, full_name, email, role)"}},"type":"object","required":["code","project_id","title","change_order_id","id","created_by","branch"],"title":"ChangeOrderPublic","description":"Schema for Change Order API responses."},"ChangeOrderRecoveryRequest":{"properties":{"impact_level":{"type":"string","pattern":"^(LOW|MEDIUM|HIGH|CRITICAL)$","title":"Impact Level","description":"Manual impact level assignment"},"assigned_approver_id":{"type":"string","format":"uuid","title":"Assigned Approver Id","description":"User to assign as approver (use User.id, not User.user_id)"},"skip_impact_analysis":{"type":"boolean","title":"Skip Impact Analysis","description":"Skip impact analysis and use manual values","default":true},"recovery_reason":{"type":"string","maxLength":500,"minLength":10,"title":"Recovery Reason","description":"Explanation for recovery (required for audit)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Control date for the workflow operation (defaults to now)"}},"type":"object","required":["impact_level","assigned_approver_id","recovery_reason"],"title":"ChangeOrderRecoveryRequest","description":"Request to recover a stuck change order workflow.\n\nContext: Admin-only endpoint to recover stuck change orders when\nimpact analysis fails or workflow gets stuck in intermediate states.\n\nArgs:\n impact_level: Manual impact level assignment (LOW/MEDIUM/HIGH/CRITICAL)\n assigned_approver_id: User to assign as approver\n skip_impact_analysis: Skip impact analysis and use manual values\n recovery_reason: Explanation for recovery (10-500 chars)\n control_date: Optional control date for the operation (defaults to now)"},"ChangeOrderStatsResponse":{"properties":{"total_count":{"type":"integer","title":"Total Count","description":"Total number of change orders","default":0},"total_cost_exposure":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Cost Exposure","description":"Total potential cost impact (sum of budget deltas)","default":"0"},"pending_value":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Pending Value","description":"Total value of pending change orders (not yet approved/rejected)","default":"0"},"approved_value":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Approved Value","description":"Total value of approved change orders","default":"0"},"by_status":{"items":{"$ref":"#/components/schemas/ChangeOrderStatusStats"},"type":"array","title":"By Status","description":"Breakdown by status"},"by_impact_level":{"items":{"$ref":"#/components/schemas/ChangeOrderImpactStats"},"type":"array","title":"By Impact Level","description":"Breakdown by impact level"},"cost_trend":{"items":{"$ref":"#/components/schemas/ChangeOrderTrendPoint"},"type":"array","title":"Cost Trend","description":"Cumulative cost trend over time"},"avg_approval_time_days":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Approval Time Days","description":"Average days from submission to approval (historical)"},"approval_workload":{"items":{"$ref":"#/components/schemas/ApprovalWorkloadItem"},"type":"array","title":"Approval Workload","description":"Pending approvals grouped by approver"},"aging_items":{"items":{"$ref":"#/components/schemas/AgingChangeOrder"},"type":"array","title":"Aging Items","description":"Change orders that have been in the same status too long"},"aging_threshold_days":{"type":"integer","title":"Aging Threshold Days","description":"Configured threshold for aging detection","default":7}},"type":"object","title":"ChangeOrderStatsResponse","description":"Aggregated statistics for change orders.\n\nResponse schema for GET /api/v1/change-orders/stats endpoint.\nProvides comprehensive analytics for the Change Order Dashboard."},"ChangeOrderStatus":{"type":"string","enum":["Draft","Submitted for Approval","Under Review","Approved","Implemented","Rejected"],"title":"ChangeOrderStatus","description":"Change Order workflow statuses.\n\nEach status has an associated Ant Design color name for UI rendering."},"ChangeOrderStatusStats":{"properties":{"status":{"type":"string","title":"Status","description":"Status value (Draft, Submitted for Approval, etc.)"},"count":{"type":"integer","title":"Count","description":"Number of change orders in this status"},"total_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Total Value","description":"Total cost exposure for COs in this status"}},"type":"object","required":["status","count"],"title":"ChangeOrderStatusStats","description":"Statistics by change order status."},"ChangeOrderTrendPoint":{"properties":{"trend_date":{"type":"string","format":"date","title":"Trend Date","description":"Date of the data point (week/month start)"},"cumulative_value":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Cumulative Value","description":"Cumulative cost impact up to this date","default":"0"},"count":{"type":"integer","title":"Count","description":"Number of change orders up to this date","default":0}},"type":"object","required":["trend_date"],"title":"ChangeOrderTrendPoint","description":"Single point in the cost trend."},"ChangeOrderUpdate":{"properties":{"code":{"anyOf":[{"type":"string","maxLength":50,"minLength":1},{"type":"null"}],"title":"Code"},"title":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"justification":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Justification"},"effective_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Effective Date"},"status":{"anyOf":[{"$ref":"#/components/schemas/ChangeOrderStatus"},{"type":"null"}]},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch","description":"Branch name for update (defaults to current branch)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Control date for bitemporal operations"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","description":"Optional comment for status transitions (Submit, Approve, Reject, Merge)"}},"type":"object","title":"ChangeOrderUpdate","description":"Schema for updating a Change Order.\n\nAll fields are optional to support partial updates."},"CloneTemplateRequest":{"properties":{"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id","description":"Project scope for the cloned layout"}},"type":"object","title":"CloneTemplateRequest","description":"Schema for cloning a template layout."},"CostElementCreate":{"properties":{"code":{"type":"string","maxLength":50,"minLength":1,"title":"Code"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"budget_amount":{"anyOf":[{"type":"number"},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Budget Amount"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"cost_element_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cost Element Id","description":"Root Cost Element ID (internal use only for seeding)"},"wbe_id":{"type":"string","format":"uuid","title":"Wbe Id"},"cost_element_type_id":{"type":"string","format":"uuid","title":"Cost Element Type Id"},"branch":{"type":"string","title":"Branch","description":"Branch name for entity creation"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["code","name","budget_amount","wbe_id","cost_element_type_id","branch"],"title":"CostElementCreate","description":"Properties required for creating a Cost Element."},"CostElementRead":{"properties":{"code":{"type":"string","maxLength":50,"minLength":1,"title":"Code"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"budget_amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$","title":"Budget Amount"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"id":{"type":"string","format":"uuid","title":"Id"},"cost_element_id":{"type":"string","format":"uuid","title":"Cost Element Id"},"wbe_id":{"type":"string","format":"uuid","title":"Wbe Id"},"wbe_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Wbe Name"},"cost_element_type_id":{"type":"string","format":"uuid","title":"Cost Element Type Id"},"cost_element_type_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Element Type Name"},"cost_element_type_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Element Type Code"},"branch":{"type":"string","title":"Branch"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"valid_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valid Time"},"transaction_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transaction Time"}},"type":"object","required":["code","name","budget_amount","id","cost_element_id","wbe_id","cost_element_type_id","branch","created_by"],"title":"CostElementRead","description":"Properties returned to client."},"CostElementTypeCreate":{"properties":{"code":{"type":"string","maxLength":50,"minLength":1,"title":"Code"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"cost_element_type_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cost Element Type Id","description":"Root Cost Element Type ID (internal use only for seeding)"},"department_id":{"type":"string","format":"uuid","title":"Department Id"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["code","name","department_id"],"title":"CostElementTypeCreate","description":"Properties required for creating a Cost Element Type."},"CostElementTypeRead":{"properties":{"code":{"type":"string","maxLength":50,"minLength":1,"title":"Code"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"id":{"type":"string","format":"uuid","title":"Id"},"cost_element_type_id":{"type":"string","format":"uuid","title":"Cost Element Type Id"},"department_id":{"type":"string","format":"uuid","title":"Department Id"},"created_by":{"type":"string","format":"uuid","title":"Created By"}},"type":"object","required":["code","name","id","cost_element_type_id","department_id","created_by"],"title":"CostElementTypeRead","description":"Properties returned to client."},"CostElementTypeUpdate":{"properties":{"code":{"anyOf":[{"type":"string","maxLength":50,"minLength":1},{"type":"null"}],"title":"Code"},"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"department_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Department Id"}},"type":"object","title":"CostElementTypeUpdate","description":"Properties that can be updated."},"CostElementUpdate":{"properties":{"code":{"anyOf":[{"type":"string","maxLength":50,"minLength":1},{"type":"null"}],"title":"Code"},"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"budget_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Budget Amount"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"cost_element_type_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cost Element Type Id"},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch","description":"Branch name for update (defaults to current branch)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for update (valid_time start)"}},"type":"object","title":"CostElementUpdate","description":"Properties that can be updated."},"CostRegistrationCreate":{"properties":{"amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Amount","description":"Cost amount (must be positive)"},"quantity":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Quantity","description":"Quantity of units consumed (optional)"},"unit_of_measure":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Unit Of Measure","description":"Unit of measure (e.g., 'hours', 'kg', 'm', 'each')"},"registration_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Registration Date","description":"When the cost was incurred (defaults to control date if not provided)"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description of the cost"},"invoice_number":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Invoice Number","description":"Optional invoice reference"},"vendor_reference":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Vendor Reference","description":"Optional vendor/supplier reference"},"cost_registration_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cost Registration Id","description":"Root Cost Registration ID (internal use only for seeding)"},"cost_element_id":{"type":"string","format":"uuid","title":"Cost Element Id","description":"ID of the cost element to charge"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["amount","cost_element_id"],"title":"CostRegistrationCreate","description":"Properties required for creating a Cost Registration."},"CostRegistrationRead":{"properties":{"amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$","title":"Amount","description":"Cost amount (must be positive)"},"quantity":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Quantity","description":"Quantity of units consumed (optional)"},"unit_of_measure":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Unit Of Measure","description":"Unit of measure (e.g., 'hours', 'kg', 'm', 'each')"},"registration_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Registration Date","description":"When the cost was incurred (defaults to control date if not provided)"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description of the cost"},"invoice_number":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Invoice Number","description":"Optional invoice reference"},"vendor_reference":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Vendor Reference","description":"Optional vendor/supplier reference"},"id":{"type":"string","format":"uuid","title":"Id"},"cost_registration_id":{"type":"string","format":"uuid","title":"Cost Registration Id"},"cost_element_id":{"type":"string","format":"uuid","title":"Cost Element Id"},"created_by":{"type":"string","format":"uuid","title":"Created By"}},"type":"object","required":["amount","id","cost_registration_id","cost_element_id","created_by"],"title":"CostRegistrationRead","description":"Properties returned to client."},"CostRegistrationUpdate":{"properties":{"amount":{"anyOf":[{"type":"number","exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Amount"},"quantity":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Quantity"},"unit_of_measure":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Unit Of Measure"},"registration_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Registration Date"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"invoice_number":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Invoice Number"},"vendor_reference":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Vendor Reference"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for update (valid_time start)"}},"type":"object","title":"CostRegistrationUpdate","description":"Properties that can be updated on a Cost Registration."},"DashboardActivity":{"properties":{"entity_id":{"type":"string","format":"uuid","title":"Entity Id","description":"Entity identifier"},"entity_name":{"type":"string","title":"Entity Name","description":"Entity name/code"},"entity_type":{"type":"string","title":"Entity Type","description":"Entity type (project, wbe, cost_element, change_order)"},"action":{"type":"string","title":"Action","description":"Action performed (created, updated, deleted, merged)"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"When the action occurred"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id","description":"User who performed the action"},"actor_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Name","description":"Name of user who performed action"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id","description":"Parent project ID (for child entities)"},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name","description":"Parent project name (for child entities)"},"branch":{"type":"string","title":"Branch","description":"Branch where action occurred"}},"type":"object","required":["entity_id","entity_name","entity_type","action","timestamp","branch"],"title":"DashboardActivity","description":"Schema for a single dashboard activity item.\n\nRepresents a recently updated entity with metadata for display."},"DashboardData":{"properties":{"last_edited_project":{"anyOf":[{"$ref":"#/components/schemas/ProjectSpotlight"},{"type":"null"}],"description":"Most recently edited project with metrics"},"recent_activity":{"additionalProperties":{"items":{"$ref":"#/components/schemas/DashboardActivity"},"type":"array"},"type":"object","title":"Recent Activity","description":"Recent activity grouped by entity type"}},"type":"object","required":["recent_activity"],"title":"DashboardData","description":"Schema for complete dashboard data response."},"DashboardLayoutCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name","description":"Layout name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Layout description"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id","description":"Project scope (null = global)"},"is_template":{"type":"boolean","title":"Is Template","description":"Whether this layout is a reusable template","default":false},"is_default":{"type":"boolean","title":"Is Default","description":"Whether this is the user's default layout for this scope","default":false},"widgets":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Widgets","description":"Widget instances array"}},"type":"object","required":["name"],"title":"DashboardLayoutCreate","description":"Schema for creating a new dashboard layout."},"DashboardLayoutRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"is_template":{"type":"boolean","title":"Is Template"},"is_default":{"type":"boolean","title":"Is Default"},"widgets":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Widgets"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","description","user_id","project_id","is_template","is_default","widgets","created_at","updated_at"],"title":"DashboardLayoutRead","description":"Schema for reading dashboard layout data."},"DashboardLayoutUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Layout name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Layout description"},"is_template":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Template","description":"Whether this layout is a reusable template"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default","description":"Whether this is the user's default layout"},"widgets":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Widgets","description":"Widget instances array"}},"type":"object","title":"DashboardLayoutUpdate","description":"Schema for updating a dashboard layout. All fields optional."},"DepartmentCreate":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name","description":"Department display name"},"manager_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Manager Id","description":"UUID of the department manager"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether the department is active","default":true},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description","description":"Department description"},"department_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Department Id","description":"Root Department ID (internal use only for seeding)"},"code":{"type":"string","maxLength":50,"pattern":"^[A-Z0-9_-]+$","title":"Code","description":"Unique department code (immutable)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["name","code"],"title":"DepartmentCreate"},"DepartmentRead":{"properties":{"name":{"type":"string","maxLength":255,"title":"Name","description":"Department display name"},"manager_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Manager Id","description":"UUID of the department manager"},"is_active":{"type":"boolean","title":"Is Active"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description","description":"Department description"},"id":{"type":"string","format":"uuid","title":"Id"},"department_id":{"type":"string","format":"uuid","title":"Department Id"},"code":{"type":"string","title":"Code"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Name"},"deleted_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Deleted By"}},"type":"object","required":["name","is_active","id","department_id","code","created_by"],"title":"DepartmentRead","description":"Schema for reading department data."},"DepartmentUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"code":{"anyOf":[{"type":"string","maxLength":50,"pattern":"^[A-Z0-9_-]+$"},{"type":"null"}],"title":"Code"},"manager_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Manager Id"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description"}},"type":"object","title":"DepartmentUpdate"},"EVMMetricsResponse":{"properties":{"entity_type":{"$ref":"#/components/schemas/EntityType","description":"Entity type (cost_element, wbe, or project)"},"entity_id":{"type":"string","format":"uuid","title":"Entity Id","description":"Entity ID (cost element, WBE, or project)"},"bac":{"type":"number","title":"Bac","description":"Budget at Completion (total planned budget)"},"pv":{"type":"number","title":"Pv","description":"Planned Value (budgeted cost of work scheduled)"},"ac":{"type":"number","title":"Ac","description":"Actual Cost (cost incurred to date)"},"ev":{"type":"number","title":"Ev","description":"Earned Value (budgeted cost of work performed)"},"cv":{"type":"number","title":"Cv","description":"Cost Variance (EV - AC, negative = over budget)"},"sv":{"type":"number","title":"Sv","description":"Schedule Variance (EV - PV, negative = behind schedule)"},"cpi":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Cpi","description":"Cost Performance Index (EV / AC, < 1.0 = over budget)"},"spi":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Spi","description":"Schedule Performance Index (EV / PV, < 1.0 = behind schedule)"},"eac":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Eac","description":"Estimate at Completion (projected total cost at completion)"},"vac":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vac","description":"Variance at Completion = BAC - EAC (negative = over budget)"},"etc":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Etc","description":"Estimate to Complete = EAC - AC (remaining work cost)"},"control_date":{"type":"string","format":"date-time","title":"Control Date","description":"Control date for time-travel query"},"branch":{"type":"string","title":"Branch","description":"Branch name"},"branch_mode":{"$ref":"#/components/schemas/BranchMode","description":"Branch mode (ISOLATED or MERGE)"},"progress_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Progress Percentage","description":"Progress percentage (0-100)"},"warning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Warning","description":"Warning message (e.g., no progress reported)"}},"type":"object","required":["entity_type","entity_id","bac","pv","ac","ev","cv","sv","control_date","branch","branch_mode"],"title":"EVMMetricsResponse","description":"Generic EVM metrics response for any entity type.\n\nProvides a flat structure with all EVM metrics explicitly defined.\nSupports cost_element, wbe, and project entity types.\n\nMetrics:\n- BAC: Budget at Completion (total planned budget)\n- PV: Planned Value (budgeted cost of work scheduled)\n- AC: Actual Cost (actual cost incurred)\n- EV: Earned Value (budgeted cost of work performed)\n- CV: Cost Variance (EV - AC)\n- SV: Schedule Variance (EV - PV)\n- CPI: Cost Performance Index (EV / AC)\n- SPI: Schedule Performance Index (EV / PV)\n- EAC: Estimate at Completion\n- VAC: Variance at Completion (BAC - EAC)\n- ETC: Estimate to Complete (EAC - AC)\n\nThis schema uses a flat structure with all metrics as individual fields,\nnot a list-based approach, for better type safety and API clarity."},"EVMTimeSeriesGranularity":{"type":"string","enum":["day","week","month"],"title":"EVMTimeSeriesGranularity","description":"Time granularity for EVM time-series aggregation.\n\nDefines the time interval for data point aggregation:\n- DAY: Daily data points\n- WEEK: Weekly data points (default)\n- MONTH: Monthly data points"},"EVMTimeSeriesPoint":{"properties":{"date":{"type":"string","format":"date-time","title":"Date","description":"Date of the data point"},"pv":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Pv","description":"Planned Value at this date"},"ev":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Ev","description":"Earned Value at this date"},"ac":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Ac","description":"Actual Cost at this date"},"forecast":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Forecast","description":"Forecast value at this date"},"actual":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Actual","description":"Actual value at this date"},"cpi":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Cpi","description":"Cost Performance Index (EV / AC, < 1.0 = over budget)"},"spi":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Spi","description":"Schedule Performance Index (EV / PV, < 1.0 = behind schedule)"}},"type":"object","required":["date","pv","ev","ac","forecast","actual"],"title":"EVMTimeSeriesPoint","description":"Single data point for EVM time-series charts.\n\nRepresents EVM metrics at a specific point in time for charting.\nUsed in time-series responses for trend visualization."},"EVMTimeSeriesResponse":{"properties":{"granularity":{"$ref":"#/components/schemas/EVMTimeSeriesGranularity","description":"Time granularity (day, week, month)"},"points":{"items":{"$ref":"#/components/schemas/EVMTimeSeriesPoint"},"type":"array","title":"Points","description":"List of time-series data points"},"start_date":{"type":"string","format":"date-time","title":"Start Date","description":"Start date of the time series"},"end_date":{"type":"string","format":"date-time","title":"End Date","description":"End date of the time series"},"total_points":{"type":"integer","title":"Total Points","description":"Total number of data points"}},"type":"object","required":["granularity","points","start_date","end_date","total_points"],"title":"EVMTimeSeriesResponse","description":"EVM time-series data for charts.\n\nContains aggregated EVM metrics over a time range with specified granularity.\nUsed for rendering trend charts and performance curves.\n\nServer-side aggregation is performed based on the requested granularity."},"EntityChange":{"properties":{"id":{"type":"integer","title":"Id","description":"Entity ID"},"name":{"type":"string","title":"Name","description":"Entity name"},"change_type":{"$ref":"#/components/schemas/EntityChangeType","description":"Type of change"},"budget_delta":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Budget Delta","description":"Budget allocation change (for modified/removed)"},"revenue_delta":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Revenue Delta","description":"Revenue allocation change (for modified/removed)"},"cost_delta":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Cost Delta","description":"Cost change (for modified/removed)"}},"type":"object","required":["id","name","change_type"],"title":"EntityChange","description":"A single entity change between branches."},"EntityChangeType":{"type":"string","enum":["added","modified","removed"]},"EntityChanges":{"properties":{"wbes":{"items":{"$ref":"#/components/schemas/EntityChange"},"type":"array","title":"Wbes","description":"Work Breakdown Element changes"},"cost_elements":{"items":{"$ref":"#/components/schemas/EntityChange"},"type":"array","title":"Cost Elements","description":"Cost Element changes"},"cost_registrations":{"items":{"$ref":"#/components/schemas/EntityChange"},"type":"array","title":"Cost Registrations","description":"Cost Registration (actual costs) changes"}},"type":"object","title":"EntityChanges","description":"Entity changes grouped by type."},"EntityType":{"type":"string","enum":["cost_element","wbe","project"],"title":"EntityType","description":"Entity type for EVM metrics.\n\nDefines the granularity level for EVM calculations:\n- COST_ELEMENT: Individual cost element (leaf node)\n- WBE: Work Breakdown Element (intermediate node)\n- PROJECT: Project level (root node)"},"FileAttachment":{"properties":{"file_id":{"type":"string","title":"File Id","description":"Unique file identifier"},"filename":{"type":"string","maxLength":255,"title":"Filename","description":"Original filename"},"file_type":{"type":"string","maxLength":100,"title":"File Type","description":"MIME type or file extension"},"file_size":{"type":"integer","minimum":0.0,"title":"File Size","description":"File size in bytes"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content","description":"Extracted text or base64-encoded content"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At","description":"Upload timestamp"}},"type":"object","required":["file_id","filename","file_type","file_size","uploaded_at"],"title":"FileAttachment","description":"Schema for file attachments in chat messages."},"FileUploadResponse":{"properties":{"file_id":{"type":"string","title":"File Id","description":"Unique file identifier"},"filename":{"type":"string","title":"Filename","description":"Original filename"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content","description":"Extracted text content (None if unsupported or extraction failed)"},"file_size":{"type":"integer","title":"File Size","description":"File size in bytes"},"content_type":{"type":"string","title":"Content Type","description":"MIME type of the file"},"file_type":{"type":"string","title":"File Type","description":"Category of file (document, spreadsheet, etc.)"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At","description":"Upload timestamp"}},"type":"object","required":["file_id","filename","file_size","content_type","file_type","uploaded_at"],"title":"FileUploadResponse","description":"Schema for file upload response."},"ForecastChanges":{"properties":{"forecasts":{"items":{"$ref":"#/components/schemas/ForecastComparison"},"type":"array","title":"Forecasts","description":"Forecast comparisons between main and change branch"}},"type":"object","title":"ForecastChanges","description":"Forecast changes for impact analysis."},"ForecastComparison":{"properties":{"costElementId":{"type":"string","format":"uuid","title":"Costelementid","description":"Cost Element ID"},"costElementCode":{"type":"string","title":"Costelementcode","description":"Cost Element code"},"costElementName":{"type":"string","title":"Costelementname","description":"Cost Element name"},"budgetAmount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Budgetamount","description":"BAC from CostElement"},"mainEac":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Maineac","description":"EAC in main branch (deprecated, use mainForecast)"},"mainForecast":{"anyOf":[{"$ref":"#/components/schemas/ForecastRead"},{"type":"null"}],"description":"Full Forecast object from main branch"},"changeEac":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Changeeac","description":"EAC in change branch (deprecated, use branchForecast)"},"branchForecast":{"anyOf":[{"$ref":"#/components/schemas/ForecastRead"},{"type":"null"}],"description":"Full Forecast object from change branch"}},"type":"object","required":["costElementId","costElementCode","costElementName","budgetAmount"],"title":"ForecastComparison","description":"Comparison of a single forecast between main and change branch.\n\nMatches frontend ForecastImpactList expectations with mainForecast and branchForecast\nobjects containing full ForecastRead data.\n\nField names use camelCase to match frontend TypeScript interface."},"ForecastCreate":{"properties":{"eac_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Eac Amount","description":"Estimate at Complete"},"basis_of_estimate":{"type":"string","maxLength":5000,"minLength":1,"title":"Basis Of Estimate","description":"Basis for the estimate"},"forecast_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Forecast Id","description":"Root Forecast ID (internal use only for seeding)"},"branch":{"type":"string","title":"Branch","description":"Branch name for creation (defaults to main if not specified)","default":"main"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["eac_amount","basis_of_estimate"],"title":"ForecastCreate","description":"Properties required for creating a Forecast."},"ForecastRead":{"properties":{"eac_amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$","title":"Eac Amount","description":"Estimate at Complete"},"basis_of_estimate":{"type":"string","maxLength":5000,"minLength":1,"title":"Basis Of Estimate","description":"Basis for the estimate"},"id":{"type":"string","format":"uuid","title":"Id"},"forecast_id":{"type":"string","format":"uuid","title":"Forecast Id"},"branch":{"type":"string","title":"Branch"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"approved_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Approved Date"},"approved_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Approved By"},"valid_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valid Time"},"transaction_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transaction Time"},"cost_element_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cost Element Id"},"cost_element_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Element Code"},"cost_element_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Element Name"},"cost_element_budget_amount":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Cost Element Budget Amount"}},"type":"object","required":["eac_amount","basis_of_estimate","id","forecast_id","branch","created_by"],"title":"ForecastRead","description":"Properties returned to client."},"ForecastUpdate":{"properties":{"eac_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Eac Amount"},"basis_of_estimate":{"anyOf":[{"type":"string","maxLength":5000,"minLength":1},{"type":"null"}],"title":"Basis Of Estimate"},"approved_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Approved Date"},"approved_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Approved By"},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch","description":"Branch name for update (defaults to current branch)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for update (valid_time start)"}},"type":"object","title":"ForecastUpdate","description":"Properties that can be updated."},"GanttDataResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/GanttItem"},"type":"array","title":"Items"},"project_start":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Project Start"},"project_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Project End"}},"type":"object","required":["items"],"title":"GanttDataResponse","description":"Response containing all Gantt data for a project."},"GanttItem":{"properties":{"cost_element_id":{"type":"string","format":"uuid","title":"Cost Element Id"},"cost_element_code":{"type":"string","title":"Cost Element Code"},"cost_element_name":{"type":"string","title":"Cost Element Name"},"wbe_id":{"type":"string","format":"uuid","title":"Wbe Id"},"wbe_code":{"type":"string","title":"Wbe Code"},"wbe_name":{"type":"string","title":"Wbe Name"},"wbe_level":{"type":"integer","title":"Wbe Level"},"parent_wbe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Wbe Id"},"budget_amount":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Budget Amount"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"},"progression_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Progression Type"}},"type":"object","required":["cost_element_id","cost_element_code","cost_element_name","wbe_id","wbe_code","wbe_name","wbe_level","parent_wbe_id","budget_amount"],"title":"GanttItem","description":"A single item in the Gantt chart (cost element with schedule)."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImageUploadResponse":{"properties":{"file_id":{"type":"string","title":"File Id","description":"Unique file identifier"},"filename":{"type":"string","title":"Filename","description":"Original filename"},"content":{"type":"string","title":"Content","description":"Base64-encoded image content"},"file_size":{"type":"integer","title":"File Size","description":"File size in bytes"},"content_type":{"type":"string","title":"Content Type","description":"MIME type of the image"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At","description":"Upload timestamp"}},"type":"object","required":["file_id","filename","content","file_size","content_type","uploaded_at"],"title":"ImageUploadResponse","description":"Schema for image upload response."},"ImpactAnalysisResponse":{"properties":{"change_order_id":{"type":"string","format":"uuid","title":"Change Order Id","description":"Change Order ID (UUID)"},"branch_name":{"type":"string","title":"Branch Name","description":"Branch name being compared (e.g., 'BR-CO-2026-001')"},"main_branch_name":{"type":"string","title":"Main Branch Name","description":"Main branch name (always 'main')"},"kpi_scorecard":{"$ref":"#/components/schemas/KPIScorecard","description":"KPI comparison"},"entity_changes":{"$ref":"#/components/schemas/EntityChanges","description":"Entity changes"},"waterfall":{"items":{"$ref":"#/components/schemas/WaterfallSegment"},"type":"array","title":"Waterfall","description":"Waterfall chart data"},"time_series":{"items":{"$ref":"#/components/schemas/TimeSeriesData"},"type":"array","title":"Time Series","description":"S-curve comparison data"},"forecast_changes":{"anyOf":[{"$ref":"#/components/schemas/ForecastChanges"},{"type":"null"}],"description":"Forecast impact analysis (EAC comparisons)"}},"type":"object","required":["change_order_id","branch_name","main_branch_name","kpi_scorecard","entity_changes"],"title":"ImpactAnalysisResponse","description":"Complete impact analysis response for a change order."},"InvokeAgentRequest":{"properties":{"message":{"type":"string","maxLength":10000,"minLength":1,"title":"Message","description":"User message content"},"execution_mode":{"type":"string","enum":["safe","standard","expert"],"title":"Execution Mode","description":"AI tool execution mode (default: 'standard')","default":"standard"}},"type":"object","required":["message"],"title":"InvokeAgentRequest","description":"Request body for invoking an agent via REST API."},"KPIMetric":{"properties":{"main_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Main Value","description":"Value in main branch"},"change_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Change Value","description":"Value in change branch (isolated)"},"merged_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Merged Value","description":"Merged value (main + change delta) when mode=merged"},"delta":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Delta","description":"Absolute difference (change - main)","default":"0"},"delta_percent":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta Percent","description":"Percentage difference ((change - main) / main * 100), null if main is 0"}},"type":"object","title":"KPIMetric","description":"A single KPI value comparison between main and change branch."},"KPIScorecard":{"properties":{"bac":{"$ref":"#/components/schemas/KPIMetric","description":"Budget at Completion comparison"},"budget_delta":{"$ref":"#/components/schemas/KPIMetric","description":"Total budget allocation delta"},"gross_margin":{"$ref":"#/components/schemas/KPIMetric","description":"Gross margin comparison"},"actual_costs":{"$ref":"#/components/schemas/KPIMetric","description":"Actual costs (AC) comparison"},"revenue_delta":{"$ref":"#/components/schemas/KPIMetric","description":"Revenue allocation delta"},"schedule_start_date":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Schedule start date comparison (ISO format string)"},"schedule_end_date":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Schedule end date comparison (ISO format string)"},"schedule_duration":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Schedule duration in days"},"eac":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Estimate at Completion (EAC) comparison"},"cpi":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Cost Performance Index (CPI) comparison"},"spi":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Schedule Performance Index (SPI) comparison"},"tcpi":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"To-Complete Performance Index (TCPI) comparison"},"vac":{"anyOf":[{"$ref":"#/components/schemas/KPIMetric"},{"type":"null"}],"description":"Variance at Completion (VAC) comparison"}},"type":"object","required":["bac","budget_delta","gross_margin","actual_costs","revenue_delta"],"title":"KPIScorecard","description":"KPI comparison scorecard for impact analysis."},"MergeRequest":{"properties":{"target_branch":{"type":"string","title":"Target Branch","description":"Target branch to merge into (default: 'main')","default":"main"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","description":"Optional comment explaining the merge"}},"type":"object","title":"MergeRequest","description":"Schema for merge operation request.\n\nAll fields are optional."},"ProgressEntryCreate":{"properties":{"progress_percentage":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Progress Percentage","description":"Work completion percentage (0.00 to 100.00)"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Optional notes about progress (e.g., justification for decrease)"},"progress_entry_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Progress Entry Id","description":"Root Progress Entry ID (internal use only for seeding)"},"cost_element_id":{"type":"string","format":"uuid","title":"Cost Element Id","description":"ID of the cost element to track progress for"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Control date for the progress entry (when the progress was measured). Defaults to current time if not provided."}},"type":"object","required":["progress_percentage","cost_element_id"],"title":"ProgressEntryCreate","description":"Properties required for creating a Progress Entry."},"ProgressEntryRead":{"properties":{"progress_percentage":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$","title":"Progress Percentage","description":"Work completion percentage (0.00 to 100.00)"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Optional notes about progress (e.g., justification for decrease)"},"id":{"type":"string","format":"uuid","title":"Id"},"progress_entry_id":{"type":"string","format":"uuid","title":"Progress Entry Id"},"cost_element_id":{"type":"string","format":"uuid","title":"Cost Element Id"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"valid_time":{"type":"string","title":"Valid Time"},"transaction_time":{"type":"string","title":"Transaction Time"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deleted At"}},"type":"object","required":["progress_percentage","id","progress_entry_id","cost_element_id","created_by","valid_time","transaction_time"],"title":"ProgressEntryRead","description":"Properties returned to client."},"ProgressEntryUpdate":{"properties":{"progress_percentage":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"},{"type":"null"}],"title":"Progress Percentage"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Control date for when the update should take effect. Defaults to current time if not provided."}},"type":"object","title":"ProgressEntryUpdate","description":"Properties that can be updated on a Progress Entry."},"ProjectBreadcrumbItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","project_id","code","name"],"title":"ProjectBreadcrumbItem","description":"Minimal project info for breadcrumb."},"ProjectBudgetSettingsCreate":{"properties":{"warning_threshold_percent":{"anyOf":[{"type":"number","maximum":100.0,"minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Warning Threshold Percent","description":"Warning threshold percentage (0-100)","default":"80.0"},"allow_project_admin_override":{"type":"boolean","title":"Allow Project Admin Override","description":"Whether project admins can override budget warnings","default":true}},"type":"object","title":"ProjectBudgetSettingsCreate","description":"Properties for creating/updating Project Budget Settings."},"ProjectBudgetSettingsRead":{"properties":{"warning_threshold_percent":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$","title":"Warning Threshold Percent","description":"Warning threshold percentage (0-100)","default":"80.0"},"allow_project_admin_override":{"type":"boolean","title":"Allow Project Admin Override","description":"Whether project admins can override budget warnings","default":true},"id":{"type":"string","format":"uuid","title":"Id"},"project_budget_settings_id":{"type":"string","format":"uuid","title":"Project Budget Settings Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"created_by":{"type":"string","format":"uuid","title":"Created By"}},"type":"object","required":["id","project_budget_settings_id","project_id","created_by"],"title":"ProjectBudgetSettingsRead","description":"Properties returned to client."},"ProjectCreate":{"properties":{"name":{"type":"string","maxLength":200,"title":"Name","description":"Project name"},"code":{"type":"string","maxLength":50,"title":"Code","description":"Unique project code"},"budget":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}],"title":"Budget","description":"Project budget"},"contract_value":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Contract Value","description":"Contract value"},"status":{"$ref":"#/components/schemas/ProjectStatus","description":"Project status","default":"Draft"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date","description":"Project start date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date","description":"Project end date"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description","description":"Description"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id","description":"Root Project ID (internal use only for seeding)"},"branch":{"type":"string","title":"Branch","description":"Branch name for creation (defaults to main if not specified)","default":"main"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["name","code","budget"],"title":"ProjectCreate","description":"Schema for creating a new project."},"ProjectMemberCreate":{"properties":{"role":{"$ref":"#/components/schemas/ProjectRole","description":"Project role for the user"},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"UUID of the user to assign"},"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"UUID of the project"},"assigned_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned By","description":"UUID of the user assigning the role"}},"type":"object","required":["role","user_id","project_id"],"title":"ProjectMemberCreate","description":"Schema for creating a new project member assignment."},"ProjectMemberRead":{"properties":{"role":{"$ref":"#/components/schemas/ProjectRole"},"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"assigned_at":{"type":"string","format":"date-time","title":"Assigned At"},"assigned_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Name","description":"Full name of the assigned user"},"user_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Email","description":"Email of the assigned user"},"assigned_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned By Name","description":"Full name of the user who assigned the role"},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name","description":"Name of the project"}},"type":"object","required":["role","id","user_id","project_id","assigned_at","created_at","updated_at"],"title":"ProjectMemberRead","description":"Schema for reading project member data."},"ProjectMemberUpdate":{"properties":{"role":{"$ref":"#/components/schemas/ProjectRole","description":"New project role for the user"},"assigned_by":{"type":"string","format":"uuid","title":"Assigned By","description":"UUID of the user updating the role"}},"type":"object","required":["role","assigned_by"],"title":"ProjectMemberUpdate","description":"Schema for updating a project member's role."},"ProjectMetrics":{"properties":{"total_budget":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Total Budget","description":"Total project budget"},"total_wbes":{"type":"integer","title":"Total Wbes","description":"Total number of WBEs"},"total_cost_elements":{"type":"integer","title":"Total Cost Elements","description":"Total number of cost elements"},"active_change_orders":{"type":"integer","title":"Active Change Orders","description":"Number of active change orders"},"ev_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ev Status","description":"Earned Value status (on_track, at_risk, behind)"}},"type":"object","required":["total_budget","total_wbes","total_cost_elements","active_change_orders"],"title":"ProjectMetrics","description":"Schema for project metrics in spotlight."},"ProjectRead":{"properties":{"name":{"type":"string","maxLength":200,"title":"Name","description":"Project name"},"code":{"type":"string","maxLength":50,"title":"Code","description":"Unique project code"},"budget":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Budget","description":"Project budget"},"contract_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Contract Value","description":"Contract value"},"status":{"$ref":"#/components/schemas/ProjectStatus","description":"Project status","default":"Draft"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date","description":"Project start date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date","description":"Project end date"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description","description":"Description"},"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"branch":{"type":"string","title":"Branch"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Name"},"deleted_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Deleted By"},"valid_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valid Time"},"transaction_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transaction Time"}},"type":"object","required":["name","code","budget","id","project_id","branch"],"title":"ProjectRead","description":"Schema for reading project data."},"ProjectRole":{"type":"string","enum":["project_admin","project_manager","project_editor","project_viewer"],"title":"ProjectRole","description":"Project-level roles for RBAC.\n\nEach role has specific permissions for project operations."},"ProjectSpotlight":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"Project identifier"},"project_name":{"type":"string","title":"Project Name","description":"Project name"},"project_code":{"type":"string","title":"Project Code","description":"Project code"},"last_activity":{"type":"string","format":"date-time","title":"Last Activity","description":"Timestamp of most recent activity"},"metrics":{"$ref":"#/components/schemas/ProjectMetrics","description":"Project metrics"},"branch":{"type":"string","title":"Branch","description":"Branch of last activity"}},"type":"object","required":["project_id","project_name","project_code","last_activity","metrics","branch"],"title":"ProjectSpotlight","description":"Schema for the last edited project spotlight."},"ProjectStatus":{"type":"string","enum":["Draft","Active","On Hold","Completed","Cancelled"],"title":"ProjectStatus","description":"Project workflow statuses.\n\nEach status has an associated Ant Design color name for UI rendering."},"ProjectUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Name"},"budget":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Budget"},"contract_value":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Contract Value"},"status":{"anyOf":[{"$ref":"#/components/schemas/ProjectStatus"},{"type":"null"}],"description":"Project status"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description"},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch","description":"Branch name for update (defaults to current branch)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for update (valid_time start)"}},"type":"object","title":"ProjectUpdate","description":"Schema for updating an existing project."},"RefreshRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshRequest","description":"Schema for refresh token request."},"ScheduleBaselineCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"Baseline name"},"start_date":{"type":"string","format":"date-time","title":"Start Date","description":"Schedule start date"},"end_date":{"type":"string","format":"date-time","title":"End Date","description":"Schedule end date"},"progression_type":{"type":"string","title":"Progression Type","description":"Type of progression curve (LINEAR, GAUSSIAN, LOGARITHMIC)","default":"LINEAR"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description of the baseline"},"schedule_baseline_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Schedule Baseline Id","description":"Root Schedule Baseline ID (internal use only for seeding)"},"branch":{"type":"string","title":"Branch","description":"Branch name for creation (defaults to main, not configurable by API consumer)","default":"main"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["name","start_date","end_date"],"title":"ScheduleBaselineCreate","description":"Properties required for creating a Schedule Baseline.\n\nNote: cost_element_id is obtained from the URL path when creating\na baseline for a specific cost element, not from the request body."},"ScheduleBaselineRead":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"Baseline name"},"start_date":{"type":"string","format":"date-time","title":"Start Date","description":"Schedule start date"},"end_date":{"type":"string","format":"date-time","title":"End Date","description":"Schedule end date"},"progression_type":{"type":"string","title":"Progression Type","description":"Type of progression curve (LINEAR, GAUSSIAN, LOGARITHMIC)","default":"LINEAR"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description of the baseline"},"id":{"type":"string","format":"uuid","title":"Id"},"schedule_baseline_id":{"type":"string","format":"uuid","title":"Schedule Baseline Id"},"cost_element_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Cost Element Id"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"branch":{"type":"string","title":"Branch"},"cost_element_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Element Code"},"cost_element_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cost Element Name"}},"type":"object","required":["name","start_date","end_date","id","schedule_baseline_id","created_by","branch"],"title":"ScheduleBaselineRead","description":"Properties returned to client."},"ScheduleBaselineUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"},"progression_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Progression Type"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch","description":"Branch name for update (defaults to main)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for update (valid_time start)"}},"type":"object","title":"ScheduleBaselineUpdate","description":"Properties that can be updated on a Schedule Baseline."},"SessionContext":{"properties":{"type":{"type":"string","enum":["general","project","wbe","cost_element"],"title":"Type","description":"Context type discriminator"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"Entity ID (required for non-general contexts)"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id","description":"Project ID (for WBE and cost_element contexts)"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Optional human-readable name for the context"}},"type":"object","required":["type"],"title":"SessionContext","description":"Structured session context for scoping AI conversations.\n\nUses discriminated union pattern to validate context-specific fields.\nEnsures type safety and prevents invalid context combinations."},"TimeSeriesData":{"properties":{"metric_name":{"type":"string","title":"Metric Name","description":"Metric being tracked (e.g., 'budget')"},"data_points":{"items":{"$ref":"#/components/schemas/TimeSeriesPoint"},"type":"array","title":"Data Points","description":"Weekly data points"}},"type":"object","required":["metric_name"],"title":"TimeSeriesData","description":"Weekly time-series data for S-curve comparison."},"TimeSeriesPoint":{"properties":{"week_start":{"type":"string","format":"date","title":"Week Start","description":"Week start date"},"main_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Main Value","description":"Value in main branch for this week"},"change_value":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Change Value","description":"Value in change branch for this week"}},"type":"object","required":["week_start"],"title":"TimeSeriesPoint","description":"A single point in time-series data."},"Token":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token"],"title":"Token","description":"Schema for authentication token."},"TokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"TokenResponse","description":"Schema for authentication token response including refresh token."},"UserHistory":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"full_name":{"type":"string","title":"Full Name"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"role":{"type":"string","title":"Role","default":"viewer"},"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"password_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Password Changed At"},"preferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preferences"},"valid_time":{"anyOf":[{"items":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"type":"array"},{"type":"null"}],"title":"Valid Time","description":"Valid time range for this version"},"transaction_time":{"anyOf":[{"items":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"type":"array"},{"type":"null"}],"title":"Transaction Time","description":"Transaction time range for this version"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Name"},"deleted_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Deleted By"}},"type":"object","required":["email","full_name","id","user_id","is_active","created_by"],"title":"UserHistory","description":"Schema for reading user version history (includes temporal fields)."},"UserPreferenceResponse":{"properties":{"theme":{"type":"string","enum":["light","dark"],"title":"Theme","description":"UI theme preference","default":"light"}},"additionalProperties":true,"type":"object","title":"UserPreferenceResponse","description":"Schema for preference API responses."},"UserPreferenceUpdate":{"properties":{"theme":{"anyOf":[{"type":"string","enum":["light","dark"]},{"type":"null"}],"title":"Theme","description":"UI theme preference","default":"light"}},"additionalProperties":true,"type":"object","title":"UserPreferenceUpdate","description":"Schema for updating user preferences.\n\nAll fields are optional to support partial updates."},"UserPublic":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"email":{"type":"string","title":"Email"},"full_name":{"type":"string","title":"Full Name"},"role":{"type":"string","title":"Role"},"is_active":{"type":"boolean","title":"Is Active"},"permissions":{"items":{"type":"string"},"type":"array","title":"Permissions","description":"List of permission strings (e.g., 'user-read', 'department-delete')"}},"type":"object","required":["id","user_id","email","full_name","role","is_active"],"title":"UserPublic","description":"User public data with RBAC permissions for frontend."},"UserRegister":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"full_name":{"type":"string","title":"Full Name"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"role":{"type":"string","title":"Role","default":"viewer"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id","description":"Root User ID (internal use only for seeding)"},"password":{"type":"string","minLength":8,"title":"Password","description":"Password must be at least 8 characters"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["email","full_name","password"],"title":"UserRegister","description":"Schema for user registration."},"UserUpdate":{"properties":{"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"department":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Department"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for valid_time"}},"type":"object","title":"UserUpdate","description":"Schema for user updates."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WBEBreadcrumb":{"properties":{"project":{"$ref":"#/components/schemas/ProjectBreadcrumbItem"},"wbe_path":{"items":{"$ref":"#/components/schemas/WBEBreadcrumbItem"},"type":"array","title":"Wbe Path","description":"Ordered list of WBEs from root to current (last item is the current WBE)"}},"type":"object","required":["project","wbe_path"],"title":"WBEBreadcrumb","description":"Breadcrumb trail for a WBE showing project and ancestor path."},"WBEBreadcrumbItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"wbe_id":{"type":"string","format":"uuid","title":"Wbe Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","wbe_id","code","name"],"title":"WBEBreadcrumbItem","description":"Minimal WBE info for breadcrumb."},"WBECreate":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"Parent project root ID"},"code":{"type":"string","maxLength":50,"title":"Code","description":"WBS code (e.g., 1.2.3)"},"name":{"type":"string","maxLength":255,"title":"Name","description":"WBE name"},"revenue_allocation":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Revenue Allocation","description":"Revenue allocation from project contract value"},"level":{"type":"integer","minimum":1.0,"title":"Level","description":"Hierarchy level","default":1},"parent_wbe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Wbe Id","description":"Parent WBE root ID"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description","description":"Description"},"wbe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Wbe Id","description":"Root WBE ID (internal use only for seeding)"},"branch":{"type":"string","title":"Branch","description":"Branch name for creation (defaults to main if not specified)","default":"main"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for creation (valid_time start)"}},"type":"object","required":["project_id","code","name"],"title":"WBECreate","description":"Schema for creating a new WBE."},"WBERead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"wbe_id":{"type":"string","format":"uuid","title":"Wbe Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"budget_allocation":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Budget Allocation","description":"Computed budget (sum of cost element budgets in full WBE hierarchy)","default":"0"},"revenue_allocation":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Revenue Allocation","description":"Revenue allocation from project contract value"},"level":{"type":"integer","title":"Level"},"parent_wbe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Wbe Id"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"branch":{"type":"string","title":"Branch"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Name"},"parent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Name"},"deleted_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Deleted By"},"valid_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valid Time"},"transaction_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transaction Time"}},"type":"object","required":["id","wbe_id","project_id","code","name","level","branch","created_by"],"title":"WBERead","description":"Schema for reading WBE data."},"WBEUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"revenue_allocation":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Revenue Allocation"},"level":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Level"},"parent_wbe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Wbe Id"},"description":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}],"title":"Description"},"branch":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch","description":"Branch name for update (defaults to current branch)"},"control_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Control Date","description":"Optional control date for update (valid_time start)"}},"type":"object","title":"WBEUpdate","description":"Schema for updating an existing WBE."},"WaterfallSegment":{"properties":{"name":{"type":"string","title":"Name","description":"Segment label"},"value":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Value","description":"Segment value (can be negative for decreases)"},"is_delta":{"type":"boolean","title":"Is Delta","description":"True if this represents a change (not a baseline)","default":false}},"type":"object","required":["name","value"],"title":"WaterfallSegment","description":"A single segment in the waterfall chart."}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"/api/auth/login"}}}}}}