# blade47/comp Wiki ## Technical docs: comp API URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/api-overview # comp API **Version:** inferred **288** endpoints detected from `(inferred from code)` ## Endpoints ### General | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/docs` | Redirect to Swagger documentation ~~deprecated~~ | | `POST` | `/cloud-security/scan/:connectionId` | | | `POST` | `/cloud-security/trigger/:connectionId` | | | `GET` | `/cloud-security/runs/:runId` | | | `GET` | `/v1/admin/integrations` | List all integrations with their credential status | | `GET` | `/v1/admin/integrations/:providerSlug` | Get details for a specific integration | | `POST` | `/v1/admin/integrations/credentials` | Save platform credentials for an integration | | `DELETE` | `/v1/admin/integrations/credentials/:providerSlug` | Delete platform credentials for an integration | | `GET` | `/integrations/checks/providers/:providerSlug` | List available checks for a provider | | `GET` | `/integrations/checks/connections/:connectionId` | List available checks for a connection | | `POST` | `/integrations/checks/connections/:connectionId/run` | Run checks for a connection | | `POST` | `/integrations/checks/connections/:connectionId/run/:checkId` | Run a specific check for a connection | ### Assistant Chat | Method | Path | Description | |--------|------|-------------| | `GET` | `/assistant-chat/history` | Get assistant chat history | | `PUT` | `/assistant-chat/history` | Save assistant chat history | | `DELETE` | `/assistant-chat/history` | Clear assistant chat history | ### Attachments | Method | Path | Description | |--------|------|-------------| | `GET` | `/attachments/:attachmentId/download` | Get attachment download URL | ### Browserbase | Method | Path | Description | |--------|------|-------------| | `POST` | `/browserbase/org-context` | Get or create organization browser context | | `GET` | `/browserbase/org-context` | Get organization browser context status | | `POST` | `/browserbase/session` | Create a new browser session | | `POST` | `/browserbase/session/close` | Close a browser session | | `POST` | `/browserbase/navigate` | Navigate to a URL | | `POST` | `/browserbase/check-auth` | Check authentication status | | `POST` | `/browserbase/automations` | Create a browser automation | | `GET` | `/browserbase/automations/task/:taskId` | Get all browser automations for a task | | `GET` | `/browserbase/automations/:automationId` | Get a browser automation by ID | | `PATCH` | `/browserbase/automations/:automationId` | Update a browser automation | | `DELETE` | `/browserbase/automations/:automationId` | Delete a browser automation | | `POST` | `/browserbase/automations/:automationId/start-live` | Start automation with live view | | `POST` | `/browserbase/automations/:automationId/execute` | Execute automation on existing session | | `POST` | `/browserbase/automations/:automationId/run` | Run a browser automation | | `GET` | `/browserbase/automations/:automationId/runs` | Get run history for an automation | | `GET` | `/browserbase/runs/:runId` | Get a specific run by ID | ### Comments | Method | Path | Description | |--------|------|-------------| | `GET` | `/comments` | Get comments for an entity | | `POST` | `/comments` | Create a new comment | | `PUT` | `/comments/:commentId` | Update a comment | | `DELETE` | `/comments/:commentId` | Delete a comment | ### Context | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/context` | Get all context entries | | `GET` | `/v1/context/:id` | Get context entry by ID | | `POST` | `/v1/context` | Create a new context entry | | `PATCH` | `/v1/context/:id` | Update a context entry | | `DELETE` | `/v1/context/:id` | Delete a context entry | ### Device Agent | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/device-agent/mac` | Download macOS device agent | | `GET` | `/v1/device-agent/windows` | Download Windows device agent | | `GET` | `/api/device-agent/status` | Retrieve device agent status | | `GET` | `/api/download-agent` | Download a device agent installer | | `HEAD` | `/api/download-agent` | Get metadata for a device agent installer | | `POST` | `/api/download-agent/token` | Create a one-time download token for a device agent | ### Devices | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/devices` | Get all devices | | `GET` | `/v1/devices/member/:memberId` | Get devices by member ID | ### Evidence Forms | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/evidence-forms` | List evidence forms | | `GET` | `/v1/evidence-forms/statuses` | Get submission statuses for all forms | | `GET` | `/v1/evidence-forms/my-submissions` | Get current user submissions | | `GET` | `/v1/evidence-forms/my-submissions/pending-count` | Get pending submission count for current user | | `GET` | `/v1/evidence-forms/:formType` | Get form definition and submissions | | `GET` | `/v1/evidence-forms/:formType/submissions/:submissionId` | Get a single submission | | `POST` | `/v1/evidence-forms/:formType/submissions` | Submit evidence form entry | | `PATCH` | `/v1/evidence-forms/:formType/submissions/:submissionId/review` | Review a submission | | `POST` | `/v1/evidence-forms/uploads` | Upload evidence form file | | `GET` | `/v1/evidence-forms/:formType/export.csv` | Export form submissions to CSV | | `POST` | `/api/evidence-forms/analyze` | Analyze evidence form submissions using AI. | ### Finding Templates | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/finding-template` | Get all finding templates | | `GET` | `/v1/finding-template/:id` | Get finding template by ID | | `POST` | `/v1/finding-template` | Create a finding template | | `PATCH` | `/v1/finding-template/:id` | Update a finding template | | `DELETE` | `/v1/finding-template/:id` | Delete a finding template | ### Findings | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/findings` | Get findings for a task | | `GET` | `/v1/findings/organization` | Get all findings for organization | | `GET` | `/v1/findings/:id` | Get finding by ID | | `POST` | `/v1/findings` | Create a finding | | `PATCH` | `/v1/findings/:id` | Update a finding | | `DELETE` | `/v1/findings/:id` | Delete a finding | | `GET` | `/v1/findings/:id/history` | Get finding history | ### Framework Editor Task Templates | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/framework-editor/task-template` | Get all task templates | | `GET` | `/v1/framework-editor/task-template/:id` | Get task template by ID | | `PATCH` | `/v1/framework-editor/task-template/:id` | Update a task template | | `DELETE` | `/v1/framework-editor/task-template/:id` | Delete a task template | ### Health | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/health` | Health check | ### Connections | Method | Path | Description | |--------|------|-------------| | `GET` | `/integrations/connections/providers` | List all available integration providers | | `GET` | `/integrations/connections/providers/:slug` | Get a specific provider's details | | `GET` | `/integrations/connections` | List connections for an organization | | `GET` | `/integrations/connections/:id` | Get a specific connection | | `POST` | `/integrations/connections` | Create a new connection with API key credentials | | `POST` | `/integrations/connections/:id/test` | Test a connection's credentials | | `POST` | `/integrations/connections/:id/pause` | Pause a connection | | `POST` | `/integrations/connections/:id/resume` | Resume a paused connection | | `POST` | `/integrations/connections/:id/disconnect` | Disconnect (soft delete) a connection | | `DELETE` | `/integrations/connections/:id` | Delete a connection permanently | | `PATCH` | `/integrations/connections/:id` | Update connection metadata (connectionName, regions, etc.) | | `POST` | `/integrations/connections/:id/ensure-valid-credentials` | Get valid credentials for a connection, refreshing OAuth tokens if needed. | | `PUT` | `/integrations/connections/:id/credentials` | Update credentials for a custom auth connection | ### integrations | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/integrations/oauth-apps` | List custom OAuth apps for an organization | | `GET` | `/v1/integrations/oauth-apps/setup/:providerSlug` | Get OAuth app setup info for a provider | | `POST` | `/v1/integrations/oauth-apps` | Save custom OAuth app credentials for an organization | | `DELETE` | `/v1/integrations/oauth-apps/:providerSlug` | Delete custom OAuth app credentials for an organization | | `GET` | `/v1/integrations/oauth/availability` | Check if OAuth credentials are available for a provider | | `POST` | `/v1/integrations/oauth/start` | Start OAuth flow - returns authorization URL | | `GET` | `/v1/integrations/oauth/callback` | OAuth callback - exchanges code for tokens | ### Integration Sync | Method | Path | Description | |--------|------|-------------| | `POST` | `integrations/sync/google-workspace/employees` | Sync employees from Google Workspace | | `POST` | `integrations/sync/google-workspace/status` | Check if Google Workspace is connected for an organization | | `POST` | `integrations/sync/rippling/employees` | Sync employees from Rippling | | `POST` | `integrations/sync/rippling/status` | Check if Rippling is connected for an organization | | `POST` | `integrations/sync/ramp/employees` | Sync employees from Ramp | | `POST` | `integrations/sync/jumpcloud/employees` | Sync employees from JumpCloud | | `POST` | `integrations/sync/jumpcloud/status` | Check if JumpCloud is connected for an organization | | `POST` | `integrations/sync/ramp/status` | Check if Ramp is connected for an organization | | `GET` | `integrations/sync/employee-sync-provider` | Get the current employee sync provider for an organization | | `POST` | `integrations/sync/employee-sync-provider` | Set the employee sync provider for an organization | ### Task Integrations | Method | Path | Description | |--------|------|-------------| | `GET` | `/integrations/tasks/template/:templateId/checks` | Get all integration checks that can auto-complete a specific task template | | `GET` | `/integrations/tasks/:taskId/checks` | Get integration checks for a specific task (by task ID) | | `POST` | `/integrations/tasks/:taskId/run-check` | Run a specific check for a task and store results | | `GET` | `/integrations/tasks/:taskId/runs` | Get check run history for a task | ### Integration Variables | Method | Path | Description | |--------|------|-------------| | `GET` | `/integrations/variables/providers/:providerSlug` | Get all variables required for a provider's checks | | `GET` | `/integrations/variables/connections/:connectionId` | Get variables for a specific connection (with current values) | | `GET` | `/integrations/variables/connections/:connectionId/options/:variableId` | Fetch dynamic options for a variable (requires active connection) | | `POST` | `/integrations/variables/connections/:connectionId` | Save variable values for a connection | ### Webhooks | Method | Path | Description | |--------|------|-------------| | `POST` | `/integrations/webhooks/:providerSlug/:connectionId` | Handle incoming webhooks for a specific provider and connection | ### Knowledge Base | Method | Path | Description | |--------|------|-------------| | `GET` | `/knowledge-base/documents` | List all knowledge base documents for an organization | | `POST` | `/knowledge-base/documents/upload` | Upload a knowledge base document | | `POST` | `/knowledge-base/documents/:documentId/download` | Get a signed download URL for a knowledge base document | | `POST` | `/knowledge-base/documents/:documentId/view` | Get a signed view URL for a knowledge base document | | `POST` | `/knowledge-base/documents/:documentId/delete` | Delete a knowledge base document | | `POST` | `/knowledge-base/documents/process` | Trigger processing of knowledge base documents | | `POST` | `/knowledge-base/runs/:runId/token` | Create a public access token for a Trigger.dev run | | `POST` | `/knowledge-base/manual-answers/:manualAnswerId/delete` | Delete a manual answer | | `POST` | `/knowledge-base/manual-answers/delete-all` | Delete all manual answers for an organization | ### Org Chart | Method | Path | Description | |--------|------|-------------| | `GET` | `/org-chart` | Get the organization chart | | `PUT` | `/org-chart` | Create or update an interactive organization chart | | `POST` | `/org-chart/upload` | Upload an image as the organization chart | | `DELETE` | `/org-chart` | Delete the organization chart | ### Organization | Method | Path | Description | |--------|------|-------------| | `GET` | `/organization` | Get organization details | | `PATCH` | `/organization` | Update organization details | | `POST` | `/organization/transfer-ownership` | Transfer organization ownership | | `DELETE` | `/organization` | Delete an organization | | `GET` | `/organization/primary-color` | Get organization primary color | ### People | Method | Path | Description | |--------|------|-------------| | `GET` | `/people` | Get all people for an organization | | `POST` | `/people` | Create a new person (member) | | `POST` | `/people/bulk` | Bulk create people (members) | | `GET` | `/people/:id` | Get a person (member) by ID | | `PATCH` | `/people/:id` | Update a person (member) | | `DELETE` | `/people/:id/host/:hostId` | Remove a host from a person (member) | | `DELETE` | `/people/:id` | Delete a person (member) | | `PATCH` | `/people/:id/unlink-device` | Unlink a device from a person (member) | ### Policies | Method | Path | Description | |--------|------|-------------| | `GET` | `/policies` | Get all policies for an organization | | `GET` | `/policies/download-all` | Download all published policies as a single PDF | | `GET` | `/policies/:id` | Get a policy by ID | | `POST` | `/policies` | Create a new policy | | `PATCH` | `/policies/:id` | Update a policy | | `DELETE` | `/policies/:id` | Delete a policy | | `GET` | `/policies/:id/versions` | Get all versions for a policy | | `GET` | `/policies/:id/versions/:versionId` | Get a policy version by ID | | `POST` | `/policies/:id/versions` | Create a new policy version | | `PATCH` | `/policies/:id/versions/:versionId` | Update policy version content | | `DELETE` | `/policies/:id/versions/:versionId` | Delete a policy version | | `POST` | `/policies/:id/versions/publish` | Publish a policy version | | `POST` | `/policies/:id/versions/:versionId/activate` | Set a policy version as active | | `POST` | `/policies/:id/versions/:versionId/submit-for-approval` | Submit a policy version for approval | | `POST` | `/policies/:id/ai-chat` | Chat with AI about a policy | ### Questionnaire | Method | Path | Description | |--------|------|-------------| | `POST` | `/questionnaire/parse` | Parse questionnaire content | | `POST` | `/questionnaire/answer-single` | Generated single answer result | | `POST` | `/questionnaire/save-answer` | Save manual or generated answer | | `POST` | `/questionnaire/delete-answer` | Delete questionnaire answer | | `POST` | `/questionnaire/export` | Export questionnaire by ID to specified format | | `POST` | `/questionnaire/upload-and-parse` | Upload file, parse questions (no answers), save to DB, return questionnaireId | | `POST` | `/questionnaire/upload-and-parse/upload` | Upload file, parse questions (no answers), save to DB, return questionnaireId | | `POST` | `/questionnaire/parse/upload` | | | `POST` | `/questionnaire/parse/upload/token` | | | `POST` | `/questionnaire/answers/export` | | | `POST` | `/questionnaire/answers/export/upload` | | | `POST` | `/questionnaire/auto-answer` | | ### Risks | Method | Path | Description | |--------|------|-------------| | `GET` | `/risks` | Get all risks for an organization | | `GET` | `/risks/:id` | Get a risk by its ID | | `POST` | `/risks` | Create a new risk | | `PATCH` | `/risks/:id` | Update an existing risk | | `DELETE` | `/risks/:id` | Delete a risk | ### SOA | Method | Path | Description | |--------|------|-------------| | `POST` | `/soa/save-answer` | Save a SOA answer | | `POST` | `/soa/auto-fill` | Auto-fill SOA document | | `POST` | `/soa/create-document` | Create a new SOA document | | `POST` | `/soa/ensure-setup` | Ensure SOA configuration and document exist | | `POST` | `/soa/approve` | Approve a SOA document | | `POST` | `/soa/decline` | Decline a SOA document | | `POST` | `/soa/submit-for-approval` | Submit SOA document for approval | ### Task Management | Method | Path | Description | |--------|------|-------------| | `GET` | `/task-management/stats` | Get task items statistics for an entity | | `GET` | `/task-management` | Get task items for an entity | | `POST` | `/task-management` | Create a new task item | | `PUT` | `/task-management/:id` | Update a task item | | `DELETE` | `/task-management/:id` | Delete a task item | | `POST` | `/task-management/attachments` | Upload attachment to task item | | `DELETE` | `/task-management/attachments/:attachmentId` | Delete attachment from task item | | `GET` | `/task-management/:id/activity` | Get task item activity log | ### Task Automations | Method | Path | Description | |--------|------|-------------| | `GET` | `/tasks/:taskId/automations` | Get all automations for a task | | `GET` | `/tasks/:taskId/automations/:automationId` | Get automation details | | `POST` | `/tasks/:taskId/automations` | Create a new automation | | `PATCH` | `/tasks/:taskId/automations/:automationId` | Update an automation | | `DELETE` | `/tasks/:taskId/automations/:automationId` | Delete an automation | | `GET` | `/tasks/:taskId/automations/:automationId/versions` | Get all versions for an automation | | `GET` | `/tasks/:taskId/automations/runs` | Get all automation runs for a task | ### Evidence Export | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/tasks/:taskId/evidence` | Get task evidence summary | | `GET` | `/v1/tasks/:taskId/evidence/automation/:automationId/pdf` | Export automation evidence as PDF | | `GET` | `/v1/tasks/:taskId/evidence/export` | Export task evidence as ZIP | ### Evidence Export (Auditor) | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/evidence-export/all` | Export all organization evidence as ZIP (Auditor only) | ### Internal - Tasks | Method | Path | Description | |--------|------|-------------| | `POST` | `/v1/internal/tasks/notify-status-change` | Send task status change notifications (email + in-app) without a user actor (internal) | | `POST` | `/v1/internal/tasks/notify-automation-failures` | Send automation failure notifications (email + in-app) when one or more automations fail (internal) | ### Tasks | Method | Path | Description | |--------|------|-------------| | `GET` | `/v1/tasks` | Get all tasks | | `PATCH` | `/v1/tasks/bulk` | Update status for multiple tasks | | `PATCH` | `/v1/tasks/bulk/assignee` | Update assignee for multiple tasks | | `POST` | `/v1/tasks/bulk/submit-for-review` | Bulk submit tasks for review | | `DELETE` | `/v1/tasks/bulk` | Delete multiple tasks | | `GET` | `/v1/tasks/:taskId` | Get task by ID | | `GET` | `/v1/tasks/:taskId/activity` | Get task activity | | `PATCH` | `/v1/tasks/:taskId` | Update a task | | `POST` | `/v1/tasks/:taskId/submit-for-review` | Submit task for review | | `POST` | `/v1/tasks/:taskId/approve` | Approve a task | | `POST` | `/v1/tasks/:taskId/reject` | Reject a task review | | `GET` | `/v1/tasks/:taskId/attachments` | Get task attachments | | `POST` | `/v1/tasks/:taskId/attachments` | Upload attachment to task | | `GET` | `/v1/tasks/:taskId/attachments/:attachmentId/download` | Get attachment download URL | | `DELETE` | `/v1/tasks/:taskId/attachments/:attachmentId` | Delete task attachment | ### Training | Method | Path | Description | |--------|------|-------------| | `POST` | `/training/send-completion-email` | Send training completion email with certificate | | `POST` | `/training/generate-certificate` | Generate training completion certificate PDF | ### Trust Access | Method | Path | Description | |--------|------|-------------| | `POST` | `/v1/trust-access/:friendlyUrl/requests` | Submit data access request | | `GET` | `/v1/trust-access/admin/requests` | List access requests | | `GET` | `/v1/trust-access/admin/requests/:id` | Get access request details | | `POST` | `/v1/trust-access/admin/requests/:id/approve` | Approve access request | | `POST` | `/v1/trust-access/admin/requests/:id/deny` | Deny access request | | `GET` | `/v1/trust-access/admin/grants` | List access grants | | `POST` | `/v1/trust-access/admin/grants/:id/revoke` | Revoke access grant | | `POST` | `/v1/trust-access/admin/grants/:id/resend-access-email` | Resend access granted email | | `GET` | `/v1/trust-access/nda/:token` | Get NDA details by token | | `POST` | `/v1/trust-access/nda/:token/preview-nda` | Preview NDA by token | | `POST` | `/v1/trust-access/nda/:token/sign` | Sign NDA | | `POST` | `/v1/trust-access/admin/requests/:id/resend-nda` | Resend NDA email | | `POST` | `/v1/trust-access/admin/requests/:id/preview-nda` | Preview NDA PDF | | `POST` | `/v1/trust-access/:friendlyUrl/reclaim` | Reclaim access | | `GET` | `/v1/trust-access/access/:token` | Get grant data by access token | | `GET` | `/v1/trust-access/access/:token/policies` | List policies by access token | | `GET` | `/v1/trust-access/access/:token/policies/download-all` | Download all policies as watermarked PDF | | `GET` | `/v1/trust-access/access/:token/policies/download-all-zip` | Download all policies as ZIP with individual PDFs | | `GET` | `/v1/trust-access/access/:token/compliance-resources` | List compliance resources by access token | | `GET` | `/v1/trust-access/access/:token/documents` | List additional documents by access token | | `GET` | `/v1/trust-access/access/:token/documents/download-all` | Download all additional documents as a ZIP by access token | | `GET` | `/v1/trust-access/access/:token/documents/:documentId` | Download additional document by access token | | `GET` | `/v1/trust-access/access/:token/compliance-resources/:framework` | Download compliance resource by access token | | `GET` | `/v1/trust-access/:friendlyUrl/faqs` | Get FAQs for a trust portal | | `GET` | `/v1/trust-access/:friendlyUrl/overview` | Get overview section for a trust portal | | `GET` | `/v1/trust-access/:friendlyUrl/custom-links` | Get custom links for a trust portal | | `GET` | `/v1/trust-access/:friendlyUrl/favicon` | Get favicon URL for a trust portal | | `GET` | `/v1/trust-access/:friendlyUrl/vendors` | Get vendors/subprocessors for a trust portal | ### Trust Portal | Method | Path | Description | |--------|------|-------------| | `GET` | `/trust-portal/domain/status` | Get domain verification status | | `POST` | `/trust-portal/compliance-resources/upload` | Upload or replace a compliance certificate (PDF only) | | `POST` | `/trust-portal/compliance-resources/signed-url` | Generate a temporary signed URL for a compliance certificate | | `POST` | `/trust-portal/compliance-resources/list` | List uploaded compliance certificates for the organization | | `POST` | `/trust-portal/documents/upload` | Upload an additional trust portal document | | `POST` | `/trust-portal/documents/list` | List additional trust portal documents for the organization | | `POST` | `/trust-portal/documents/:documentId/download` | Generate a temporary signed URL for a trust portal document | | `POST` | `/trust-portal/documents/:documentId/delete` | Delete (deactivate) a trust portal document | | `POST` | `/trust-portal/overview` | Update trust portal overview section | | `GET` | `/trust-portal/overview` | Get trust portal overview | | `POST` | `/trust-portal/custom-links` | Create a custom link for trust portal | | `POST` | `/trust-portal/custom-links/:linkId` | Update a custom link | | `POST` | `/trust-portal/custom-links/:linkId/delete` | Delete a custom link | | `POST` | `/trust-portal/custom-links/reorder` | Reorder custom links | | `GET` | `/trust-portal/custom-links` | List custom links for trust portal | | `POST` | `/trust-portal/vendors/:vendorId/trust-settings` | Update vendor trust portal settings | | `GET` | `/trust-portal/vendors` | List vendors configured for trust portal | ### Internal - Vendors | Method | Path | Description | |--------|------|-------------| | `POST` | `/internal/vendors/risk-assessment/trigger-batch` | Trigger vendor risk assessment tasks for a batch of vendors (internal) | | `POST` | `/internal/vendors/risk-assessment/trigger-single` | Trigger vendor risk assessment for a single vendor and return run info (internal) | ### Vendors | Method | Path | Description | |--------|------|-------------| | `GET` | `/vendors` | Get all vendors for an organization | | `GET` | `/vendors/:id` | Get a vendor by ID | | `POST` | `/vendors` | Create a new vendor | | `PATCH` | `/vendors/:id` | Update an existing vendor | | `DELETE` | `/vendors/:id` | Delete a vendor | ### Auth | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/auth/invitation` | Handle invitation link redirection | | `GET` | `/api/auth/test-db` | Test database connection (E2E only) | | `POST` | `/api/auth/test-login` | Perform a test login for E2E (Internal Only) | ### AI | Method | Path | Description | |--------|------|-------------| | `POST` | `/api/chat` | Engage in AI chat | ### Cloud Tests | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/cloud-tests/findings` | Retrieve cloud test findings for an organization. | | `GET` | `/api/cloud-tests/providers` | Retrieve active cloud providers for an organization. | ### File Management | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/get-image-url` | Get a signed URL for an image stored in S3. | ### QA Internal | Method | Path | Description | |--------|------|-------------| | `POST` | `/api/qa/approve-org` | Approve an organization by setting hasAccess to true (QA internal). | | `POST` | `/api/qa/delete-user` | Delete a user and all associated data (QA internal). | ### Retool Internal | Method | Path | Description | |--------|------|-------------| | `POST` | `/api/retool/reset-org` | Resets an organization's data | ### Secrets | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/secrets/:id` | Get a specific secret | | `PUT` | `/api/secrets/:id` | Update a secret | | `DELETE` | `/api/secrets/:id` | Delete a secret | | `GET` | `/api/secrets` | List all secrets for the organization | | `POST` | `/api/secrets` | Create a new secret | ### User Data | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/user-frameworks` | Retrieve user frameworks | ### Fleet Policies | Method | Path | Description | |--------|------|-------------| | `POST` | `/api/confirm-fleet-policy` | Confirms a fleet policy and uploads attachments. | --- ## Technical docs: Project Overview URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-1/project-overview
Relevant source files The following files were used as context for generating this wiki page: - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [apps/api/package.json](https://github.com/blade47/comp/blob/main/apps/api/package.json) - [apps/api/src/main.ts](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts)
Comp AI is an open-source compliance platform designed to automate compliance processes for various regulatory frameworks. It aims to simplify evidence collection, policy management, and control implementation, enabling organizations to achieve compliance with standards like SOC 2, ISO 27001, HIPAA, and GDPR in a streamlined manner. The platform emphasizes user control over data and infrastructure while leveraging AI for efficiency. The project is structured as a monorepo, encompassing multiple applications and shared packages, with a robust API service built on NestJS that handles core functionalities, integrations, and data management. ## Core Capabilities & Compliance Frameworks Comp AI provides automation for key compliance activities, including: * **Evidence Collection:** Streamlining the gathering of necessary documentation and data. * **Policy Management:** Assisting in the creation, maintenance, and enforcement of organizational policies. * **Control Implementation:** Guiding and automating the setup of security and operational controls. The platform is designed to help organizations achieve compliance with major frameworks such as: * SOC 2 * ISO 27001 * HIPAA * GDPR Sources: [README.md:19-23](https://github.com/blade47/comp/blob/main/README.md#L19-L23) ## High-Level Architecture Comp AI is structured as a monorepo, containing multiple applications (`apps`) and shared packages (`packages`). This architecture facilitates code sharing, consistent development practices, and independent versioning of components. Sources: [README.md:95-97](https://github.com/blade47/comp/blob/main/README.md#L95-L97), [README.md:275-280](https://github.com/blade47/comp/blob/main/README.md#L275-L280), [apps/api/package.json:2-3](https://github.com/blade47/comp/blob/main/apps/api/package.json#L2-L3) ### Technology Stack The project leverages a modern web development stack, including: * **Next.js:** For building web applications. * **Tailwind CSS:** For styling. * **Vercel:** For deployment and hosting. * **NestJS:** A progressive Node.js framework for building efficient, reliable, and scalable server-side applications (used in `@comp/api`). * **Prisma:** A next-generation ORM for database access. * **PostgreSQL:** The primary relational database. * **Trigger.dev:** For background jobs and workflow automation. * **Upstash (Redis/Vector):** For key-value store and vector database functionalities. * **AWS SDK:** For interacting with AWS services (e.g., S3, SecurityHub, STS). * **AI SDKs:** Integrations with Anthropic, Groq, and OpenAI for AI capabilities. * **Resend:** For email delivery. Sources: [README.md:32-37](https://github.com/blade47/comp/blob/main/README.md#L32-L37), [apps/api/package.json:6-48](https://github.com/blade47/comp/blob/main/apps/api/package.json#L6-L48) ## API Service (`@comp/api`) The `@comp/api` service is the backend component of Comp AI, built using the NestJS framework. It handles API requests, business logic, data persistence, and integrations with various external services. ### Key Dependencies The API service relies on a wide array of libraries and frameworks to provide its functionality: | Category | Key Dependencies --- ## Technical docs: GET Redirect to Swagger documentation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/redirecttoswagger ## Responses ## Try It --- ## Technical docs: Getting Started URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-1/getting-started
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/package.json](https://github.com/blade47/comp/blob/main/apps/api/package.json) - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [apps/api/docker-compose.yml](https://github.com/blade47/comp/blob/main/apps/api/docker-compose.yml)
This page provides a comprehensive guide to setting up and running the Comp AI platform locally for development. Comp AI is an open-source compliance platform designed to automate evidence collection, policy management, and control implementation for frameworks like SOC 2, ISO 27001, HIPAA, and GDPR. The instructions cover prerequisites, environment configuration, database setup, and how to start the development servers, enabling you to get a local instance of Comp AI up and running quickly. ## Prerequisites Before you begin, ensure your system meets the following software requirements: * **Node.js**: Version `20.x` or higher. * **Bun**: Version `1.1.36` or higher. * **PostgreSQL**: Version `15.x` or higher. Bun is used as the package manager and runtime for various scripts within the project. PostgreSQL is the primary database for the application. Sources: [README.md:49-52](https://github.com/blade47/comp/blob/main/README.md#L49-L52) ## Development Setup Follow these steps to set up the Comp AI project locally, including all necessary integrations. ### Overall Setup Flow The following diagram illustrates the high-level steps required to get the Comp AI project running locally: Sources: [README.md:61-82](https://github.com/blade47/comp/blob/main/README.md#L61-L82) ### 1. Clone the Repository Begin by cloning the Comp AI repository from GitHub: ```sh git clone https://github.com/trycompai/comp.git ``` Navigate into the project directory: ```sh cd comp ``` Sources: [README.md:64-69](https://github.com/blade47/comp/blob/main/README.md#L64-L69) ### 2. Install Dependencies Install all project dependencies using Bun: ```sh bun install ``` Sources: [README.md:71-73](https://github.com/blade47/comp/blob/main/README.md#L71-L73) ### 3. Environment Variables Create the necessary `.env` files by copying from their respective `.env.example` templates. These files will hold your credentials and configuration. ```sh cp apps/app/.env.example apps/app/.env cp apps/portal/.env.example apps/portal/.env cp packages/db/.env.example packages/db/.env ``` ```cmd copy apps\app\.env.example apps\app\.env copy apps\portal\.env.example apps\portal\.env copy packages\db\.env.example packages\db\.env ``` ```powershell Copy-Item apps\app\.env.example -Destination apps\app\.env Copy-Item apps\portal\.env.example -Destination apps\portal\.env Copy-Item packages\db\.env.example -Destination apps\db\.env ``` #### Required Environment Variables for `apps/app/.env` Ensure the following variables are defined in `comp/apps/app/.env`: | Variable | Description --- ## Technical docs: GET Get assistant chat history URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/assistant-chat/assistantchatcontroller-gethistory ## Parameters ## Responses ## Try It --- ## Technical docs: PUT Save assistant chat history URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/assistant-chat/assistantchatcontroller-savehistory ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: Configuration URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-1/configuration
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/config/better-auth.config.ts](https://github.com/blade47/comp/blob/main/apps/api/src/config/better-auth.config.ts) - [apps/api/src/config/aws.config.ts](https://github.com/blade47/comp/blob/main/apps/api/src/config/aws.config.ts) - [apps/api/src/config/load-env.ts](https://github.com/blade47/comp/blob/main/apps/api/src/config/load-env.ts) - [README.md](https://github.com/blade47/comp/blob/main/README.md)
This page details the configuration management within the project, focusing on how environment variables are loaded and how application-specific settings for services like AWS and "Better Auth" are defined and validated. The system leverages `dotenv` for loading environment variables and `zod` for robust schema validation, ensuring that all necessary configurations are present and correctly formatted at application startup. The configuration architecture aims to provide a clear, centralized, and validated approach to managing application settings, reducing runtime errors caused by missing or malformed environment variables. ## Environment Variable Loading The project utilizes a dedicated module, `load-env.ts`, to manage the loading of environment variables from `.env` files. This module ensures that environment variables are loaded early in the application lifecycle, supporting various deployment and development environments. It searches for `.env` files in predefined locations to maximize flexibility. The `loadEnv` function attempts to load the `.env` file from several common paths: 1. Relative to the compiled output (`dist/src/.env`). 2. Relative to the source directory (`src/.env`). 3. In the current working directory (`process.cwd()/.env`). Once an `.env` file is found, its variables are loaded and can optionally override existing environment variables. The `ensureEnvLoaded` function provides a mechanism to guarantee that environment variables have been processed, preventing redundant loading. ```typescript // apps/api/src/config/load-env.ts const searchPaths = [ // When compiled to dist/src (Nest build output) path.join(__dirname, '..', '..', '.env'), // When running with ts-node directly from src path.join(__dirname, '..', '.env'), // Fallback to current working directory path.join(process.cwd(), '.env'), ]; function loadEnv(): void { for (const envPath of searchPaths) { if (existsSync(envPath)) { config({ path: envPath, override: true }); envLoaded = true; return; } } envLoaded = true; } ``` ### Environment Loading Flow Sources: [apps/api/src/config/load-env.ts:1-25](https://github.com/blade47/comp/blob/main/apps/api/src/config/load-env.ts#L1-L25) ## Application-Specific Configurations The project uses `@nestjs/config`'s `registerAs` function in conjunction with `zod` schemas to define and validate specific configuration objects. This approach provides type safety and ensures that critical application settings are correctly structured and present. ### AWS Configuration The AWS configuration (`aws.config.ts`) defines the necessary parameters for interacting with Amazon Web Services. It includes settings for region, access keys, and S3 bucket details. The AWS configuration is validated at application startup using a `zod` schema. If any required environment variables are missing or invalid, the application will throw an error and fail to start, preventing potential runtime issues. #### AWS Configuration Options | Option | Environment Variable | Description | Default Value | Required | | :-------------- | :---------------------------- | :---------------------------------------------- | :------------ | :------- | | `region` | `APP_AWS_REGION` | AWS region to connect to. | `us-east-1` | No | | `accessKeyId` | `APP_AWS_ACCESS_KEY_ID` | AWS access key ID. | | Yes | | `secretAccessKey` | `APP_AWS_SECRET_ACCESS_KEY` | AWS secret access key. | | Yes | | `bucketName` | `APP_AWS_BUCKET_NAME` | Name of the S3 bucket to use. | | Yes | | `endpoint` | `APP_AWS_ENDPOINT` | Custom endpoint for AWS services (e.g., for localstack). | | No | Sources: [apps/api/src/config/aws.config.ts:1-33](https://github.com/blade47/comp/blob/main/apps/api/src/config/aws.config.ts#L1-L33) #### AWS Configuration Schema ### Better Auth Configuration The "Better Auth" configuration (`better-auth.config.ts`) specifies the URL for an external authentication service. The `BETTER_AUTH_URL` environment variable is **required**. If it is not provided or is not a valid URL, the application will fail to start. #### Better Auth Configuration Options | Option | Environment Variable | Description | Required | | :----- | :------------------- | :---------------------------------------- | :------- | | `url` | `BETTER_AUTH_URL` | The URL of the "Better Auth" service. | Yes | Sources: [apps/api/src/config/better-auth.config.ts:1-27](https://github.com/blade47/comp/blob/main/apps/api/src/config/better-auth.config.ts#L1-L27) #### Better Auth Configuration Schema ### Configuration Validation Flow ## General Environment Variable Setup For local development, environment variables are typically managed through `.env` files. The project provides example `.env.example` files that should be copied and filled with actual credentials. ### Create .env files Copy the example environment files for each application and package. ```sh cp apps/app/.env.example apps/app/.env cp apps/portal/.env.example apps/portal/.env cp packages/db/.env.example packages/db/.env ``` ```cmd copy apps\app\.env.example apps\app\.env copy apps\portal\.env.example apps\portal\.env copy packages\db\.env.example packages\db\.env ``` ```powershell Copy-Item apps\app\.env.example -Destination apps\app\.env Copy-Item apps\portal\.env.example -Destination apps\portal\.env Copy-Item packages\db\.env.example -Destination packages\db\.env ``` ### Fill out required variables Populate the newly created `.env` files with your specific credentials and settings. Ensure all required variables are present. The `README.md` specifically highlights the need for `NEXT_PUBLIC_PORTAL_URL` and `REVALIDATION_SECRET` in `comp/apps/app/.env` which might be missing from `.env.example`. #### Common Environment Variables | Variable | Description --- ## Technical docs: Troubleshooting URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-1/troubleshooting
Relevant source files The following files were used as context for generating this wiki page: - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [apps/api/src/common/filters/cors-exception.filter.ts](https://github.com/blade47/comp/blob/main/apps/api/src/common/filters/cors-exception.filter.ts) - [apps/api/src/common/pipes/zod-validation.pipe.ts](https://github.com/blade47/comp/blob/main/apps/api/src/common/pipes/zod-validation.pipe.ts)
Troubleshooting in the Comp AI platform involves diagnosing and resolving issues across various layers, from local development environment setup to API request handling. This guide provides insights into common problems and their solutions, focusing on environment configuration, database management, and API error responses. Understanding these areas is crucial for maintaining a smooth development workflow and ensuring the application functions as expected. ## Local Development Environment Troubleshooting Setting up the local development environment for Comp AI requires specific prerequisites and careful configuration of environment variables and the database. Issues in these areas are common and can prevent the application from starting or functioning correctly. ### Prerequisites and Initial Setup Ensure your system meets the minimum software requirements before attempting to run Comp AI locally. ### Verify Prerequisites Confirm that the following software is installed with the specified versions: - **Node.js**: Version `>=20.x` - **Bun**: Version `>=1.1.36` - **Postgres**: Version `>=15.x` If any of these are not met, update or install them accordingly. ### Clone Repository and Install Dependencies 1. Clone the Comp AI repository: ```sh git clone https://github.com/trycompai/comp.git ``` 2. Navigate to the project directory: ```sh cd comp ``` 3. Install dependencies using Bun: ```sh bun install ``` Sources: [README.md:65-71](https://github.com/blade47/comp/blob/main/README.md#L65-L71), [README.md:83-91](https://github.com/blade47/comp/blob/main/README.md#L83-L91) ### Environment Variable Configuration Incorrect or missing environment variables are a frequent source of issues. Comp AI requires several `.env` files to be correctly populated. #### Required `.env` Files Create the following `.env` files by copying from their respective `.env.example` counterparts: - `comp/apps/app/.env` - `comp/apps/portal/.env` - `comp/packages/db/.env` ```sh cp apps/app/.env.example apps/app/.env cp apps/portal/.env.example apps/portal/.env cp packages/db/.env.example packages/db/.env ``` ```cmd copy apps\app\.env.example apps\app\.env copy apps\portal\.env.example apps\portal\.env copy packages\db\.env.example apps\db\.env ``` ```powershell Copy-Item apps\app\.env.example -Destination apps\app\.env Copy-Item apps\portal\.env.example -Destination apps\portal\.env Copy-Item packages\db\.env.example -Destination apps\db\.env ``` #### Critical Environment Variables Ensure `comp/apps/app/.env` contains at least the following variables: | Variable | Description Sources: [README.md:94-118](https://github.com/blade47/comp/blob/main/README.md#L94-L118), [README.md:120-131](https://github.com/blade47/comp/blob/main/README.md#L120-L131), [README.md:133-140](https://github.com/blade47/comp/blob/main/README.md#L133-L140) #### Hard-coding Environment Variables Some environment variables might not load correctly from `.env` files, especially in certain development setups or environments. In such cases, the `README.md` explicitly recommends hard-coding these values directly into the relevant source files. This should be considered a temporary troubleshooting step and ideally resolved by fixing the environment variable loading mechanism. Specific locations for hard-coding include: - **Google OAuth credentials**: `GOOGLE_ID`, `GOOGLE_SECRET` in `comp/apps/portal/src/app/lib/auth.ts`. - **Redis (Upstash) credentials**: Redis URL and TOKEN in `comp/packages/kv/src/index.ts`. - **Trigger.dev Project ID**: `project` property in `comp/apps/app/trigger.config.ts`. Sources: [README.md:141-143](https://github.com/blade47/comp/blob/main/README.md#L141-L143), [README.md:156-158](https://github.com/blade47/comp/blob/main/README.md#L156-L158), [README.md:167-169](https://github.com/blade47/comp/blob/main/README.md#L167-L169), [README.md:176-178](https://github.com/blade47/comp/blob/main/README.md#L176-L178) ### Database Setup and Common Issues The PostgreSQL database is a core component. Proper setup and migration are essential. ### Start Database Container Navigate to `packages/db` and start the Docker container for PostgreSQL: ```sh cd packages/db bun docker:up ``` ### Verify Credentials The default credentials are: - **Database name**: `comp` - **Username**: `postgres` - **Password**: `postgres` If you need to change the password, connect to the database and run: ```sql ALTER USER postgres WITH PASSWORD 'new_password'; ``` ### Resolve "No function matches..." Error If you encounter an error message like `HINT: No function matches the given name and argument types...`, it indicates a missing database function. To fix this, run the following command, replacing `` with your PostgreSQL password: ```sh psql "postgresql://postgres:@localhost:5432/comp" -f ./packages/db/prisma/functionDefinition.sql ``` Expected output upon success is `CREATE FUNCTION`. Ensure you use the correct port and database name for your setup. ### Generate Prisma Client and Apply Schema After the database is running and any function definition issues are resolved: 1. Generate the Prisma client: ```sh bun db:generate ``` 2. Push the schema to the database: ```sh bun db:push ``` 3. (Optional) Seed the database with initial data: ```sh bun db:seed ``` #### Useful Database Commands For further database management and troubleshooting: - `bun db:studio`: Open Prisma Studio to view/edit data. - `bun db:migrate`: Run database migrations. - `bun docker:down`: Stop the database container. - `bun docker:clean`: Remove the database container and volume. Sources: [README.md:181-183](https://github.com/blade47/comp/blob/main/README.md#L181-L183), [README.md:185-188](https://github.com/blade47/comp/blob/main/README.md#L185-L188), [README.md:190-192](https://github.com/blade47/comp/blob/main/README.md#L190-L192), [README.md:194-203](https://github.com/blade47/comp/blob/main/README.md#L194-L203), [README.md:205-212](https://github.com/blade47/comp/blob/main/README.md#L205-L212) ## API Error Handling The Comp AI API includes specific mechanisms to handle common errors such as Cross-Origin Resource Sharing (CORS) issues and request validation failures. ### CORS Exception Handling The `CorsExceptionFilter` is a global exception filter designed to manage CORS headers on error responses. This is critical for allowing client applications (like the frontend) to communicate with the API, especially during development or when deployed across different domains. #### How it Works 1. **Catches `HttpException`**: The filter intercepts any `HttpException` thrown by the API. 2. **Extracts Origin**: It reads the `Origin` header from the incoming request. 3. **Checks Allowed Origins**: It compares the request origin against a predefined list of allowed origins. This list includes: * `http://localhost:3000` * `http://localhost:3001` * `http://127.0.0.1:3000` * `https://app.trycomp.ai` * `https://trycomp.ai` * The value of `process.env.APP_URL` 4. **Development Mode Flexibility**: If `NODE_ENV` is not `production`, it also allows origins containing `localhost`, `127.0.0.1`, or `ngrok`. 5. **Sets CORS Headers**: If the origin is allowed, it sets `Access-Control-Allow-Origin`, `Access-Control-Allow-Credentials`, `Access-Control-Allow-Methods`, and `Access-Control-Allow-Headers` on the response. 6. **Sends Error Response**: Finally, it sends the original `HttpException`'s response body with the appropriate HTTP status code. If you encounter CORS errors (e.g., "Access-Control-Allow-Origin header is not present") when making requests to the API, verify that your client's origin is included in the `allowedOrigins` list within the `CorsExceptionFilter` or that you are running in a development environment that permits your origin. ```typescript // apps/api/src/common/filters/cors-exception.filter.ts import { ExceptionFilter, Catch, ArgumentsHost, HttpException, } from '@nestjs/common'; import type { Response, Request } from 'express'; @Catch(HttpException) export class CorsExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); const request = ctx.getRequest(); const status = exception.getStatus(); const origin = request.headers.origin; if (origin) { const isDevelopment = process.env.NODE_ENV !== 'production'; const allowedOrigins = [ 'http://localhost:3000', 'http://localhost:3001', 'http://127.0.0.1:3000', 'https://app.trycomp.ai', 'https://trycomp.ai', process.env.APP_URL, ].filter(Boolean) as string[]; const isAllowed = allowedOrigins.includes(origin) || (isDevelopment && (origin.includes('localhost') || origin.includes('127.0.0.1') || origin.includes('ngrok'))); if (isAllowed) { response.setHeader('Access-Control-Allow-Origin', origin); response.setHeader('Access-Control-Allow-Credentials', 'true'); response.setHeader( 'Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,PATCH,OPTIONS', ); response.setHeader( 'Access-Control-Allow-Headers', 'Content-Type,Authorization,X-API-Key,X-Organization-Id', ); } } response.status(status).json(exception.getResponse()); } } ``` Sources: [apps/api/src/common/filters/cors-exception.filter.ts:1-42](https://github.com/blade47/comp/blob/main/apps/api/src/common/filters/cors-exception.filter.ts#L1-L42) ### Zod Validation Pipe The `ZodValidationPipe` is a custom NestJS pipe used for validating incoming request data (e.g., body, query parameters) against a Zod schema. This ensures that data conforms to expected types and structures before being processed by controller handlers. #### How it Works 1. **Constructor**: It takes a `ZodSchema` instance during its creation. 2. **`transform` Method**: When applied to a route handler parameter, this method attempts to parse the incoming `value` using the provided `schema`. 3. **Validation Failure**: If `schema.parse(value)` throws an error (meaning the data does not match the schema), the pipe catches it and throws a `BadRequestException` with the message 'Validation failed'. Using `ZodValidationPipe` helps enforce data integrity at the API boundary, preventing malformed requests from reaching business logic. When troubleshooting, if you receive a `400 Bad Request` with the message 'Validation failed', it indicates that the request payload does not conform to the expected Zod schema for that endpoint. ```typescript // apps/api/src/common/pipes/zod-validation.pipe.ts import { ArgumentMetadata, BadRequestException, PipeTransform, } from '@nestjs/common'; import { ZodSchema } from 'zod'; export class ZodValidationPipe implements PipeTransform { constructor(private schema: ZodSchema) {} transform(value: unknown, metadata: ArgumentMetadata) { try { const parsedValue = this.schema.parse(value); return parsedValue; } catch (error) { throw new BadRequestException('Validation failed'); } } } ``` Sources: [apps/api/src/common/pipes/zod-validation.pipe.ts:1-15](https://github.com/blade47/comp/blob/main/apps/api/src/common/pipes/zod-validation.pipe.ts#L1-L15) ### API Request Flow with Error Handling The following sequence diagram illustrates how an API request is processed, including the points where CORS and Zod validation errors might be handled. Sources: [apps/api/src/common/filters/cors-exception.filter.ts](https://github.com/blade47/comp/blob/main/apps/api/src/common/filters/cors-exception.filter.ts), [apps/api/src/common/pipes/zod-validation.pipe.ts](https://github.com/blade47/comp/blob/main/apps/api/src/common/pipes/zod-validation.pipe.ts) --- ## Technical docs: DELETE Clear assistant chat history URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/assistant-chat/assistantchatcontroller-clearhistory ## Parameters ## Responses ## Try It --- ## Technical docs: API Architecture URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-2/api-architecture
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/app.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts) - [apps/api/src/main.ts](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts) - [apps/api/src/app.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/app.controller.ts) - [apps/api/src/app.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/app.service.ts)
The API architecture is built upon the NestJS framework, providing a structured and modular approach to developing server-side applications. It serves as the central backend for various functionalities, integrating numerous domain-specific modules, handling requests, and providing a robust and scalable foundation. The core of the API is defined by its entry point (`main.ts`), which initializes the NestJS application, configures global middleware, security settings, and API documentation. The `AppModule` acts as the root module, orchestrating the integration of various feature modules, configuration settings, and global guards to manage the application's overall behavior. ## Application Entry Point and Bootstrap Process The `main.ts` file is the primary entry point for the API application. It is responsible for bootstrapping the NestJS application, applying global configurations, setting up middleware, and starting the HTTP server. Before the NestJS application starts, environment variables are loaded to ensure proper configuration. The `bootstrap` function performs several critical steps: 1. **Application Creation:** Initializes the NestJS application using `AppModule`. 2. **CORS Configuration:** Enables Cross-Origin Resource Sharing for all origins, with credentials and exposed headers. 3. **Security Headers:** Applies `helmet` middleware to set various HTTP security headers, including Content Security Policy (CSP). 4. **Body Parsing:** Configures `express.json` and `express.urlencoded` to handle request body parsing, with a generous limit of 150MB to accommodate large payloads like base64-encoded attachments. 5. **Global Pipes:** Registers a `ValidationPipe` globally to enforce data validation, whitelisting, and automatic transformation of incoming data. 6. **API Versioning:** Enables URI-based API versioning, defaulting to version `1`. 7. **Swagger/OpenAPI Documentation:** Generates and serves interactive API documentation at `/api/docs`. In development environments, it also writes the OpenAPI specification to a JSON file. 8. **Server Start:** Listens for incoming HTTP requests on a configured port (defaulting to `3333`). 9. **Graceful Shutdown:** Implements handlers for `SIGTERM` and `SIGINT` signals to ensure the application closes gracefully. Sources: [apps/api/src/main.ts:1-93](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L1-L93) ## Core Module Structure The `AppModule` (`app.module.ts`) serves as the root module of the NestJS application. It aggregates all other feature modules, global configurations, and providers, defining the overall structure and dependencies of the API. ### Key Components of `AppModule` * **`imports`**: This array lists all the modules that `AppModule` depends on. It includes: * `ConfigModule`: For loading and managing application configurations. * `ThrottlerModule`: Implements rate limiting to protect against abuse. * A comprehensive list of feature modules, each encapsulating specific domain logic (e.g., `AuthModule`, `OrganizationModule`, `DevicesModule`, `TasksModule`, `SOAModule`, `CloudSecurityModule`, etc.). * **`controllers`**: Declares `AppController`, which handles basic routes like the root redirect to API documentation. * **`providers`**: Registers services and other injectable components, including `AppService` and a global `ThrottlerGuard` for rate limiting. Sources: [apps/api/src/app.module.ts:1-85](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts#L1-L85) ### Configuration Management The `ConfigModule` is configured globally within `AppModule` to load environment-specific configurations. It uses `awsConfig` and `betterAuthConfig` to provide structured configuration objects throughout the application. The `.env` file is loaded manually in `main.ts` before NestJS initializes, ensuring that environment variables are available for configuration loading. The `ConfigModule` is configured with `isGlobal: true`, making the configuration available across all modules without needing to re-import it. The `load` property specifies configuration factories (`awsConfig`, `betterAuthConfig`) that provide typed configuration objects. Sources: [apps/api/src/app.module.ts:10-21](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts#L10-L21), [apps/api/src/main.ts:1](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L1) ## Request Handling Flow When a request arrives at the API, it passes through a series of middleware, guards, pipes, and controllers before reaching the business logic in services. Sources: [apps/api/src/main.ts:1-93](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L1-L93), [apps/api/src/app.module.ts:22-30](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts#L22-L30), [apps/api/src/app.controller.ts:1-12](https://github.com/blade47/comp/blob/main/apps/api/src/app.controller.ts#L1-L12), [apps/api/src/app.service.ts:1-7](https://github.com/blade47/comp/blob/main/apps/api/src/app.service.ts#L1-L7) ### Global Middleware and Guards The API employs several global mechanisms to ensure security, performance, and data integrity: * **CORS:** Enabled for all origins (`origin: true`) to allow client applications to interact with the API. * **Helmet:** Configured to add various HTTP security headers, including a Content Security Policy (CSP) that restricts sources for scripts, styles, images, and connections. * **Body Parsers:** `express.json` and `express.urlencoded` are used to parse incoming request bodies, with a `150mb` limit to support large data transfers. * **ThrottlerGuard:** A global guard provided by `ThrottlerModule` that limits requests to 100 per minute per IP address, preventing abuse and ensuring service availability. Sources: [apps/api/src/main.ts:18-47](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L18-L47), [apps/api/src/app.module.ts:22-30](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts#L22-L30) ### Validation Pipe A global `ValidationPipe` is applied to all incoming requests. This pipe automatically validates incoming data against defined DTOs (Data Transfer Objects), ensuring that requests conform to expected schemas. The `ValidationPipe` is configured with: - `whitelist: true`: Removes properties that are not defined in the DTO. - `forbidNonWhitelisted: true`: Throws an error if non-whitelisted properties are present. - `transform: true`: Automatically transforms incoming payload objects to DTO instances. - `transformOptions: { enableImplicitConversion: true }`: Enables implicit type conversion for primitive types. Sources: [apps/api/src/main.ts:50-59](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L50-L59) ## API Versioning The API supports URI-based versioning, allowing different versions of endpoints to coexist. The default version is `1`. ```typescript app.enableVersioning({ type: VersioningType.URI, defaultVersion: '1', }); ``` This means endpoints can be accessed like `/v1/resource` or `/v1/another-resource`. Sources: [apps/api/src/main.ts:61-64](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L61-L64) ## API Documentation The API automatically generates and serves interactive documentation using Swagger (OpenAPI). This documentation is accessible at `/api/docs`. ### Documentation Features * **Title and Description:** Provides a clear overview of the API. * **Version:** Specifies the API version (`1.0`). * **Servers:** Lists available API servers, including local development and production environments. * **Authentication:** Supports API key authentication (`X-API-Key` header). * **Persistence:** Swagger UI is configured to persist authorization tokens between page refreshes. * **Development Output:** In non-production environments, the OpenAPI specification is written to `packages/docs/openapi.json` for external tooling or reference. Sources: [apps/api/src/main.ts:68-93](https://github.com/blade47/comp/blob/main/apps/api/src/main.ts#L68-L93) ### Root Endpoint Redirect The root path (`/`) of the API is configured to automatically redirect clients to the Swagger documentation page (`/api/docs`). This redirect is excluded from the generated Swagger documentation itself. ```typescript @Controller({ version: VERSION_NEUTRAL }) export class AppController { constructor(private readonly appService: AppService) {} @Get() @Redirect('/api/docs', 302) @ApiExcludeEndpoint() redirectToSwagger(): void { // This method redirects to Swagger documentation } } ``` Sources: [apps/api/src/app.controller.ts:1-12](https://github.com/blade47/comp/blob/main/apps/api/src/app.controller.ts#L1-L12) --- ## Technical docs: GET Get attachment download URL URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/attachments/attachmentscontroller-getattachmentdownloadurl ## Parameters ## Responses ## Try It --- ## Technical docs: POST Get or create organization browser context URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-getorcreateorgcontext ## Parameters ## Responses ## Try It --- ## Technical docs: Module Map URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-2/module-map
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/app.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts) - [apps/api/src/health/health.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/health/health.module.ts) - [apps/api/src/integration-platform/integration-platform.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/integration-platform.module.ts) - [apps/api/src/questionnaire/questionnaire.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.module.ts)
This document provides an overview of the module structure within the `apps/api` directory, focusing on how different feature modules are organized and integrated into the main application. It details the `AppModule` as the root, along with specific examples like `HealthModule`, `IntegrationPlatformModule`, and `QuestionnaireModule`, illustrating their responsibilities and dependencies. The architecture leverages NestJS modules to encapsulate related functionalities, promoting modularity and maintainability. Each module typically groups controllers, services, and repositories relevant to a specific domain, which are then imported into the `AppModule` to form the complete API application. ## Core Application Module (`AppModule`) The `AppModule` serves as the root module for the NestJS API application. It aggregates all other feature modules, global configurations, and core services required for the application to function. This module is responsible for setting up global configurations like rate limiting and loading environment-specific settings. ### Global Configuration and Guards The `AppModule` initializes several global configurations and guards: * **`ConfigModule`**: Configures the application to load environment variables and specific configuration objects (`awsConfig`, `betterAuthConfig`). It is set as global, making configuration available throughout the application. * **`ThrottlerModule`**: Implements rate limiting to protect the API from abuse. It is configured to allow 100 requests per minute (`ttl: 60000`, `limit: 100`) per IP address. * **`APP_GUARD`**: The `ThrottlerGuard` is provided globally using `APP_GUARD`, ensuring that rate limiting is applied to all routes by default. Sources: [apps/api/src/app.module.ts:1-60](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts#L1-L60) ### Feature Module Imports The `AppModule` imports a wide array of feature modules, each responsible for a specific domain or functionality within the API. This modular approach helps in organizing the codebase and managing dependencies. The `AppModule` imports 29 distinct feature modules, demonstrating a comprehensive microservices-like architecture within a single NestJS application. The following diagram illustrates the primary modules imported by the `AppModule`: Sources: [apps/api/src/app.module.ts:31-57](https://github.com/blade47/comp/blob/main/apps/api/src/app.module.ts#L31-L57) ## Health Module (`HealthModule`) The `HealthModule` is a simple module dedicated to providing health check endpoints for the API. It contains only a controller, `HealthController`, which would typically expose endpoints to verify the application's operational status. Sources: [apps/api/src/health/health.module.ts:1-6](https://github.com/blade47/comp/blob/main/apps/api/src/health/health.module.ts#L1-L6) ## Integration Platform Module (`IntegrationPlatformModule`) The `IntegrationPlatformModule` is a comprehensive module responsible for managing various aspects of third-party integrations. It encompasses controllers for handling OAuth flows, managing connections, administrative tasks, and webhook processing. It also provides services for credential management, connection handling, and automated checks, supported by dedicated repositories for data persistence. ### Components This module is structured with a clear separation of concerns, including: * **Controllers**: Handle incoming HTTP requests related to integrations. * **Services**: Encapsulate business logic for integration functionalities. * **Repositories**: Manage data access for integration-related entities. The module also exports several services, making them available for use by other modules that import `IntegrationPlatformModule`. Exporting services like `CredentialVaultService` and `ConnectionService` allows other modules to securely interact with integration functionalities without needing to know the internal implementation details of the `IntegrationPlatformModule`. ### Module Structure The following diagram illustrates the internal components of the `IntegrationPlatformModule`: Sources: [apps/api/src/integration-platform/integration-platform.module.ts:1-62](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/integration-platform.module.ts#L1-L62) ## Questionnaire Module (`QuestionnaireModule`) The `QuestionnaireModule` handles functionalities related to questionnaires. It includes a controller for API endpoints and a service for business logic. Notably, it imports the `TrustPortalModule`, indicating a dependency on trust portal functionalities, possibly for questionnaire publishing or data integration. Sources: [apps/api/src/questionnaire/questionnaire.module.ts:1-11](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.module.ts#L1-L11) --- ## Technical docs: Extensions Layer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-2/extensions-layer
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/customPrismaExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/customPrismaExtension.ts) - [apps/api/emailExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/emailExtension.ts) - [apps/api/integrationPlatformExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/integrationPlatformExtension.ts)
The Extensions Layer refers to a set of custom build extensions designed to integrate specific project dependencies and workspace packages into the `@trigger.dev/build` process. These extensions customize how certain modules are handled during the build, ensuring they are correctly resolved, generated, and bundled for deployment or local development. This layer addresses challenges such as managing Prisma client generation, resolving imports for internal workspace packages, and copying necessary build artifacts. By using the `@trigger.dev/build` `BuildExtension` interface, these extensions hook into various stages of the build lifecycle, like `onBuildStart` and `onBuildComplete`, to perform specialized tasks. ## Prisma Extension The `PrismaExtension` is responsible for integrating Prisma into the build process, particularly for the `@trycompai/db` package. Its primary goal is to ensure that the Prisma client is correctly generated and included in the deployment bundle, and that Prisma-related modules are externalized where appropriate. ### Purpose and Configuration The extension handles the resolution of the `schema.prisma` file, the local generation of the Prisma client during development, and the copying and generation of the client for deployment. It can be configured with various options to control its behavior. This extension is crucial for projects using Prisma, especially when the schema is part of a shared workspace package like `@trycompai/db`, as it ensures the Prisma client is available and correctly configured in both development and deployment environments. **`PrismaExtensionOptions`** | Option | Type | Description

The following files were used as context for generating this
this.moduleExternals = [
'@prisma/client',
'@prisma/client',
'@trycompai/db', // Add the published package to externals
];
}

externalsForTarget(target: any) {
if (target === 'dev') {
return [];
}
return this.moduleExternals;
}

async onBuildStart(context: BuildContext) {
if (context.target === 'dev') {
return;
}

const resolution = this.tryResolveSchemaPath(context as ExtendedBuildContext);

if (!resolution.path) {
context.logger.debug(
'Prisma schema not found during build start, likely before dependencies are installed.',
{ searched: resolution.searched },
);
return;
}

this._resolvedSchemaPath = resolution.path;
context.logger.debug(`Resolved prisma schema to ${resolution.path}`);
await this.ensureLocalPrismaClient(context as ExtendedBuildContext, resolution.path);
}

async onBuildComplete(context: BuildContext, manifest: BuildManifest) {
if (context.target === 'dev') {
return;
}

if (!this._resolvedSchemaPath || !existsSync(this._resolvedSchemaPath)) {
const resolution = this.tryResolveSchemaPath(context as ExtendedBuildContext);

if (!resolution.path) {
throw new Error(
[
'PrismaExtension could not find the prisma schema. Make sure @trycompai/db is installed',
`with version ${this.options.dbPackageVersion || 'latest'} and that its dist files are built.`,
'Searched the following locations:',
...resolution.searched.map((candidate) => ` - ${candidate}`),
].join('\n'),
);
}

this._resolvedSchemaPath = resolution.path;
}

assert(this._resolvedSchemaPath, 'Resolved schema path is not set');
const schemaPath = this._resolvedSchemaPath;

await this.ensureLocalPrismaClient(context as ExtendedBuildContext, schemaPath);

context.logger.debug('Looking for @prisma/client in the externals', {
externals: manifest.externals,
});

const prismaExternal = manifest.externals?.find(
(external) => external.name === '@prisma/client',
);
const version = prismaExternal?.version ?? this.options.version;

if (!version) {
throw new Error(
`PrismaExtension could not determine the version of @prisma/client. It's possible that the @prisma/client was not used in the project. If this isn't the case, please provide a version in the PrismaExtension options.`,
);
}

context.logger.debug(
`PrismaExtension is generating the Prisma client for version ${version} from @trycompai/db package`,
);

const commands: string[] = [];
const env: Record = {};

// Copy the prisma schema from the published package to the build output path
const schemaDestinationPath = join(manifest.outputPath, 'prisma', 'schema.prisma');
const schemaDestinationDir = dirname(schemaDestinationPath);
context.logger.debug(
`Copying the prisma schema from ${schemaPath} to ${schemaDestinationPath}`,
);
await mkdir(schemaDestinationDir, { recursive: true });
await cp(schemaPath, schemaDestinationPath);

// Add prisma generate command to generate the client from the copied schema
commands.push(
`${binaryForRuntime(manifest.runtime)} node_modules/prisma/build/index.js generate --schema=./prisma/schema.prisma`,
);

// Only handle migrations if requested
if (this.options.migrate) {
context.logger.debug(
'Migration support not implemented for published package - please handle migrations separately',
);
// You could add migration commands here if needed
// commands.push(`${binaryForRuntime(manifest.runtime)} npx prisma migrate deploy`);
}

// Set up environment variables
env.DATABASE_URL = manifest.deploy.env?.DATABASE_URL;

if (this.options.directUrlEnvVarName) {
env[this.options.directUrlEnvVarName] =
manifest.deploy.env?.[this.options.directUrlEnvVarName] ??
process.env[this.options.directUrlEnvVarName];
if (!env[this.options.directUrlEnvVarName]) {
context.logger.warn(
`prismaExtension could not resolve the ${this.options.directUrlEnvVarName} environment variable. Make sure you add it to your environment variables or provide it as an environment variable to the deploy CLI command. See our docs for more info: https://trigger.dev/docs/deploy-environment-variables`,
);
}
} else {
env.DIRECT_URL = manifest.deploy.env?.DIRECT_URL;
env.DIRECT_DATABASE_URL = manifest.deploy.env?.DIRECT_DATABASE_URL;
}

if (!env.DATABASE_URL) {
context.logger.warn(
'prismaExtension could not resolve the DATABASE_URL environment variable. Make sure you add it to your environment variables. See our docs for more info: https://trigger.dev/docs/deploy-environment-variables',
);
}

context.logger.debug('Adding the prisma layer with the following commands', {
commands,
env,
dependencies: {
prisma: version,
'@trycompai/db': this.options.dbPackageVersion || 'latest',
},
});

context.addLayer({
id: 'prisma',
commands,
dependencies: {
prisma: version,
'@trycompai/db': this.options.dbPackageVersion || 'latest',
},
build: {
env,
},
});
}

private async ensureLocalPrismaClient(
context: ExtendedBuildContext,
schemaSourcePath: string,
): Promise {
const schemaDir = resolve(context.workingDir, 'prisma');
const schemaDestinationPath = resolve(schemaDir, 'schema.prisma');

await mkdir(schemaDir, { recursive: true });
await cp(schemaSourcePath, schemaDestinationPath);

const clientEntryPoint = resolve(context.workingDir, 'node_modules/.prisma/client/default.js');

if (existsSync(clientEntryPoint) && !process.env.TRIGGER_PRISMA_FORCE_GENERATE) {
context.logger.debug('Prisma client already generated locally, skipping regenerate.');
return;
}

const prismaBinary = this.resolvePrismaBinary(context.workingDir);

if (!prismaBinary) {
context.logger.debug(
'Prisma CLI not available yet, skipping local generate until install finishes.',
);
return;
}

context.logger.log('Prisma client missing. Generating before Trigger indexing.');
await this.runPrismaGenerate(context, prismaBinary, schemaDestinationPath);
}

private runPrismaGenerate(
context: ExtendedBuildContext,
prismaBinary: string,
schemaPath: string,
): Promise {
return new Promise((resolvePromise, rejectPromise) => {
const child = spawn(prismaBinary, ['generate', `--schema=${schemaPath}`], {
cwd: context.workingDir,
env: {
...process.env,
PRISMA_HIDE_UPDATE_MESSAGE: '1',
},
});

child.stdout?.on('data', (data: Buffer) => {
context.logger.debug(data.toString().trim());
});

child.stderr?.on('data', (data: Buffer) => {
context.logger.warn(data.toString().trim());
});

child.on('error', (error) => {
rejectPromise(error);
});

child.on('close', (code) => {
if (code === 0) {
resolvePromise();
} else {
rejectPromise(new Error(`prisma generate exited with code ${code}`));
}
});
});
}

private resolvePrismaBinary(workingDir: string): string | undefined {
const binDir = resolve(workingDir, 'node_modules', '.bin');
const executable = process.platform === 'win32' ? 'prisma.cmd' : 'prisma';
const binaryPath = resolve(binDir, executable);

if (!existsSync(binaryPath)) {
return undefined;
}

return binaryPath;
}

private tryResolveSchemaPath(context: ExtendedBuildContext): SchemaResolution {
const candidates = this.buildSchemaCandidates(context);
const path = candidates.find((candidate) => existsSync(candidate));
return { path, searched: candidates };
}

private buildSchemaCandidates(context: ExtendedBuildContext): string[] {
const candidates = new Set();

const addNodeModuleCandidates = (start: string | undefined) => {
if (!start) {
return;
}

let current = start;
while (true) {
candidates.add(resolve(current, 'node_modules/@trycompai/db/dist/schema.prisma'));
const parent = dirname(current);
if (parent === current) {
break;
}
current = parent;
}
};

addNodeModuleCandidates(context.workingDir);
addNodeModuleCandidates(context.workspaceDir);

candidates.add(resolve(context.workingDir, '../../packages/db/dist/schema.prisma'));
candidates.add(resolve(context.workingDir, '../packages/db/dist/schema.prisma'));

return Array.from(candidates);
}
}




--- File: apps/api/emailExtension.ts ---
import type {
BuildContext,
BuildExtension,
BuildManifest,
} from '@trigger.dev/build';
import type { Plugin } from 'esbuild';
import { existsSync } from 'node:fs';
import { cp, mkdir } from 'node:fs/promises';
import { resolve } from 'node:path';

const PACKAGE_NAME = '@trycompai/email';

/**
* Custom Trigger.dev build extension for @trycompai/email workspace package.
*
* Since @trycompai/email is a workspace package (not published to npm),
* we need to:
* 1. Add an esbuild plugin to resolve the import path during build
* 2. Copy the built dist files into the trigger.dev deployment
*/
export function emailExtension(): EmailExtension {
return new EmailExtension();
}

class EmailExtension implements BuildExtension {
public readonly name = 'EmailExtension';
private _packagePath: string | undefined;

async onBuildStart(context: BuildContext) {
if (context.target === 'dev') {
return;
}

this._packagePath = this.findPackageRoot(context.workingDir);

if (!this._packagePath) {
throw new Error(
[
`EmailExtension could not find ${PACKAGE_NAME}.`,
'Make sure the package is built (run `bun run build` in packages/email).',
].join('\n'),
);
}

context.logger.debug(`Found email package at ${this._packagePath}`);

const packagePath = this._packagePath;
const resolvePlugin: Plugin = {
name: 'resolve-email',
setup(build) {
build.onResolve({ filter: /^@trycompai\/email$/ }, () => {
return {
path: resolve(packagePath, 'dist/index.js'),
};
});

build.onResolve(
{ filter: /^@trycompai\/email\// },
(args) => {
const subpath = args.path.replace(`${PACKAGE_NAME}/`, '');
return {
path: resolve(packagePath, 'dist', `${subpath}/index.js`),
};
},
);
},
};

context.registerPlugin(resolvePlugin);
}

async onBuildComplete(context: BuildContext, manifest: BuildManifest) {
if (context.target === 'dev') {
return;
}

const packagePath = this._packagePath;
if (!packagePath) {
return;
}

const packageDistPath = resolve(packagePath, 'dist');

const destPath = resolve(
manifest.outputPath,
'node_modules/@trycompai/email',
);
const destDistPath = resolve(destPath, 'dist');

await mkdir(destDistPath, { recursive: true });

await cp(packageDistPath, destDistPath, { recursive: true });

const packageJsonPath = resolve(packagePath, 'package.json');
if (existsSync(packageJsonPath)) {
await cp(packageJsonPath, resolve(destPath, 'package.json'));
}

context.logger.log(
'Copied @trycompai/email to deployment bundle',
);
}

private findPackageRoot(workingDir: string): string | undefined {
const candidates = [
resolve(workingDir, '../../packages/email'),
resolve(workingDir, '../packages/email'),
];

for (const candidate of candidates) {
if (
existsSync(candidate) &&
existsSync(resolve(candidate, 'dist/index.js'))
) {
return candidate;
}
}

return undefined;
}
}


--- File: apps/api/integrationPlatformExtension.ts ---
import type {
BuildContext,
BuildExtension,
BuildManifest,
} from '@trigger.dev/build';
import type { Plugin } from 'esbuild';
import { existsSync } from 'node:fs';
import { cp, mkdir } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';

const PACKAGE_NAME = '@comp/integration-platform';

/**
* Custom Trigger.dev build extension for @comp/integration-platform workspace package.
*
* Since @comp/integration-platform is a workspace package (not published to npm),
* we need to:
* 1. Add an esbuild plugin to resolve the import path during build
* 2. Copy the built dist files into the trigger.dev deployment
*/
export function integrationPlatformExtension(): IntegrationPlatformExtension {
return new IntegrationPlatformExtension();
}

class IntegrationPlatformExtension implements BuildExtension {
public readonly name = 'IntegrationPlatformExtension';
private _packagePath: string | undefined;

async onBuildStart(context: BuildContext) {
if (context.target === 'dev') {
return;
}

// Find the package path
this._packagePath = this.findPackageRoot(context.workingDir);

if (!this._packagePath) {
throw new Error(
[
`IntegrationPlatformExtension could not find ${PACKAGE_NAME}.`,
'Make sure the package is built (run `bun run build` in packages/integration-platform).',
].join('\n'),
);
}

context.logger.debug(`Found integration-platform at ${this._packagePath}`);

// Register esbuild plugin to resolve the workspace package
const packagePath = this._packagePath;
const resolvePlugin: Plugin = {
name: 'resolve-integration-platform',
setup(build) {
// Resolve bare import
build.onResolve({ filter: /^@comp\/integration-platform$/ }, () => {
return {
path: resolve(packagePath, 'dist/index.js'),
};
});

// Resolve subpath imports like @comp/integration-platform/types
build.onResolve(
{ filter: /^@comp\/integration-platform\// },
(args) => {
const subpath = args.path.replace(`${PACKAGE_NAME}/`, '');
return {
path: resolve(packagePath, 'dist', `${subpath}/index.js`),
};
},
);
},
};

context.registerPlugin(resolvePlugin);
}

async onBuildComplete(context: BuildContext, manifest: BuildManifest) {
if (context.target === 'dev') {
return;
}

const packagePath = this._packagePath;
if (!packagePath) {
return;
}1. **Start with the `

` block** listing all source files. 2. **No H1 title.** 3. **Introduction:** Explain what the "Extensions Layer" is, focusing on its role in customizing the build process for specific dependencies or workspace packages. Mention it uses `@trigger.dev/build` extensions. 4. **Prisma Extension (`PrismaExtension`)**: * **Purpose:** Explain its role in handling Prisma during the build process, especially for the `@trycompai/db` package. * **Key Features:** * Externalizing Prisma-related modules. * Resolving `schema.prisma` path. * Ensuring local Prisma client generation. * Copying schema and generating client in the build output. * Handling environment variables (`DATABASE_URL`, `DIRECT_URL`). * **Methods:** `onBuildStart`, `onBuildComplete`, `ensureLocalPrismaClient`, `runPrismaGenerate`, `resolvePrismaBinary`, `tryResolveSchemaPath`, `buildSchemaCandidates`. * **Diagram:** A flowchart showing the `onBuildStart` and `onBuildComplete` lifecycle, especially schema resolution and client generation. * **Configuration:** `PrismaExtensionOptions`. 5. **Email Extension (`EmailExtension`)**: * **Purpose:** Explain its role in integrating the `@trycompai/email` workspace package into the build. * **Key Features:** * Finding the package root. * Registering an esbuild plugin for path resolution. * Copying `dist` files and `package.json` to the deployment bundle. * **Methods:** `onBuildStart`, `onBuildComplete`, `findPackageRoot`. * **Diagram:** A sequence diagram showing how `onBuildStart` registers the esbuild plugin and `onBuildComplete` copies files. 6. **Integration Platform Extension (`IntegrationPlatformExtension`)**: * **Purpose:** Similar to `EmailExtension`, but for `@comp/integration-platform`. * **Key Features:** * Finding the package root. * Registering an esbuild plugin for path resolution. * Copying `dist` files and `package.json` to the deployment bundle. * **Methods:** `onBuildStart`, `onBuildComplete`, `findPackageRoot`. * **Diagram:** A flowchart for the build process, showing the steps of finding the package, registering the plugin, and copying files. This can be similar to the Email Extension but perhaps a high-level flow. 7. **Overall Architecture/Interaction:** A high-level diagram showing how these extensions fit into the `@trigger.dev/build` lifecycle. Let's refine the diagrams: * **Prisma Extension Flowchart:** Focus on `onBuildStart` and `onBuildComplete` logic, especially schema resolution, `ensureLocalPrismaClient`, and the final `addLayer` call. * **Workspace Package Extension (Email/Integration Platform) Sequence Diagram:** Show `BuildContext` interacting with the extension, then the extension interacting with `esbuild` (via `registerPlugin`) and the file system (via `cp`, `mkdir`). Constraint Checklist & Confidence Score: 1.
block first: Yes 2. No H1 title: Yes 3. Based ONLY on source files: Yes 4. Introduction (1-2 paragraphs): Yes 5. Detailed Sections (H2, H3): Yes 6. Explain architecture, components, data flow: Yes 7. Identify key elements: Yes 8. Mermaid Diagrams (at least 2): Yes, planning 3. * Flowcharts: Yes * Sequence Diagrams: Yes * Node IDs alphanumeric: Yes * Arrow syntax: Yes * Node labels < 25 chars or
: Yes * Wrap labels with special chars in quotes: Yes * No
in labels: Yes * Split complex diagrams: Yes * `mermaid` fences: Yes * Valid syntax: Will double check. 9. Tables: Yes, for options/config. 10. Code Snippets (optional): Yes, for key parts like `prismaExtension` or `emailExtension` function calls. 11. Source Citations: Yes, at the end of each section. 12. Technical Accuracy: Yes 13. Clarity: Yes 14. MDX Components: Yes, will use Callouts, maybe Steps. Confidence Score: 5/5 Mental Sandbox: * For Prisma, the `onBuildStart` is for dev target and `onBuildComplete` is for deployment. I need to make this distinction clear. The `ensureLocalPrismaClient` is called in both, but its purpose differs slightly (local dev vs. preparing for deployment). * The `buildSchemaCandidates` logic is important for Prisma, showing how it searches for `schema.prisma`. * For Email/Integration, the `findPackageRoot` is crucial. The esbuild `onResolve` setup is also key. * I should highlight that these extensions are for workspace packages not published to npm, which is a common use case for custom build logic. Key information to extract for each extension: * **PrismaExtension**: * `PrismaExtensionOptions`: `version`, `migrate`, `directUrlEnvVarName`, `dbPackageVersion`. * `moduleExternals`: `['@prisma/client', '@prisma/engines', '@trycompai/db']`. * `onBuildStart`: Resolves schema, ensures local client (for dev/indexing). * `onBuildComplete`: Resolves schema, ensures local client, copies schema, generates client, adds layer with dependencies and env vars. * `tryResolveSchemaPath` and `buildSchemaCandidates`: How schema is found. * `ensureLocalPrismaClient` and `runPrismaGenerate`: How Prisma client is handled. * **EmailExtension**: * `PACKAGE_NAME`: `@trycompai/email`. * `onBuildStart`: Finds package root, registers esbuild plugin to resolve imports to `dist/index.js`. * `onBuildComplete`: Copies `dist` folder and `package.json` to `node_modules/@trycompai/email` in the output. * `findPackageRoot`: Searches relative paths for the package. * **IntegrationPlatformExtension**: * `PACKAGE_NAME`: `@comp/integration-platform`. * Similar logic to `EmailExtension` for finding package, registering esbuild plugin, and copying files. I'll make sure to explicitly mention that these extensions are part of the `@trigger.dev/build` system, which is implied by the imports but good to state directly.The Extensions Layer comprises a set of custom build extensions designed to integrate specific project dependencies and internal workspace packages into the `@trigger.dev/build` process. These extensions customize how certain modules are handled during the build lifecycle, ensuring they are correctly resolved, generated, and bundled for both local development and deployment. By implementing the `BuildExtension` interface from `@trigger.dev/build`, these extensions hook into critical stages like `onBuildStart` and `onBuildComplete`. This allows them to perform specialized tasks such as managing Prisma client generation, resolving module paths for internal workspace packages not published to npm, and copying necessary build artifacts to the final deployment bundle. This layer is essential for maintaining a consistent and functional application across different environments. ## Prisma Extension The `PrismaExtension` is a custom build extension specifically designed to manage Prisma integration within the build process, particularly for the `@trycompai/db` package. Its primary function is to ensure that the Prisma schema is correctly located, the Prisma client is generated, and all necessary Prisma-related artifacts are included in the final deployment. ### Purpose and Configuration This extension handles the complexities of Prisma client generation, which is often required at different stages of the build. It ensures that the `schema.prisma` file is resolved from the `@trycompai/db` package and that the Prisma client is generated locally for development and then again for the deployment bundle. The `PrismaExtension` is crucial for projects utilizing Prisma, especially when the Prisma schema resides within a shared workspace package. It automates the setup required for Prisma to function correctly in both development and deployed environments. The behavior of the `PrismaExtension` can be customized using the `PrismaExtensionOptions`. | Option | Type | Description

The following files were used as context for generating this wiki page:

  • [apps/api/customPrismaExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/customPrismaExtension.ts)
  • [apps/api/emailExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/emailExtension.ts)
  • [apps/api/integrationPlatformExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/integrationPlatformExtension.ts)
The Extensions Layer comprises a set of custom build extensions designed to integrate specific project dependencies and internal workspace packages into the `@trigger.dev/build` process. These extensions customize how certain modules are handled during the build lifecycle, ensuring they are correctly resolved, generated, and bundled for both local development and deployment. By implementing the `BuildExtension` interface from `@trigger.dev/build`, these extensions hook into critical stages like `onBuildStart` and `onBuildComplete`. This allows them to perform specialized tasks such as managing Prisma client generation, resolving module paths for internal workspace packages not published to npm, and copying necessary build artifacts to the final deployment bundle. This layer is essential for maintaining a consistent and functional application across different environments. ## Prisma Extension The `PrismaExtension` is a custom build extension specifically designed to manage Prisma integration within the build
--- ## Technical docs: GET Get organization browser context status URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-getorgcontextstatus ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new browser session URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-createsession ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: Build Pipeline URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-2/build-pipeline
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/buildspec.yml](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml) - [apps/api/buildspec.multistage.yml](https://github.com/blade47/comp/blob/main/apps/api/buildspec.multistage.yml) - [apps/api/docker-compose.yml](https://github.com/blade47/comp/blob/main/apps/api/docker-compose.yml) - [.syncpackrc.json](https://github.com/blade47/comp/blob/main/.syncpackrc.json)
This document outlines the build pipelines for the `api` application, covering both the traditional CodeBuild approach and a more streamlined multi-stage Docker build process. It also details the local development setup using Docker Compose and the project's dependency management strategy. The primary goal of these pipelines is to build the `api` service, package it into a Docker image, and deploy it to an Amazon ECS cluster. The project utilizes two distinct CodeBuild specifications for the `api` service: `buildspec.yml` for a standard, step-by-step build within the CodeBuild environment, and `buildspec.multistage.yml` which offloads most of the build logic to a multi-stage Dockerfile. For local development and testing, `docker-compose.yml` provides a convenient way to run the `api` service using the same multi-stage Docker build approach. Dependency consistency across the monorepo is enforced using `syncpack` as configured in `.syncpackrc.json`. ## Standard CodeBuild Pipeline (`buildspec.yml`) The `apps/api/buildspec.yml` file defines a comprehensive CodeBuild pipeline for the `api` application. This pipeline is responsible for fetching dependencies, building the application, creating a Docker image, pushing it to Amazon ECR, and finally updating the Amazon ECS service. ### Pipeline Phases The build process is divided into three main phases: `pre_build`, `build`, and `post_build`. ### Pre-Build Phase This phase focuses on initial setup, including logging into Amazon ECR and preparing environment variables for the build process. It also installs `bun`, the JavaScript runtime and package manager used in the project. **Key Actions:** * Log in to Amazon ECR using AWS CLI. * Define `REPOSITORY_URI` based on `$ECR_REPOSITORY_URI`. * Derive `COMMIT_HASH` from `$CODEBUILD_RESOLVED_SOURCE_VERSION` and set `IMAGE_TAG`. * Install `bun` using its official installation script. ### Build Phase This is the core of the pipeline, where the application is built and packaged into a Docker image. It involves environment configuration, validation, dependency installation, workspace package building, the main API application build, and meticulous preparation of build artifacts for Docker. **Key Actions:** * **Environment Setup**: Sets critical environment variables like `PATH`, `PGSSLMODE`, `NODE_ENV`, `NEXT_TELEMETRY_DISABLED`, `UV_THREADPOOL_SIZE`, and `NODE_OPTIONS`. * **Environment Variable Validation**: Ensures essential environment variables (e.g., `DATABASE_URL`, `BASE_URL`, AWS credentials) are set, failing the build if any are missing. * **Dependency Installation**: Installs only the `api` workspace dependencies using `bun install --filter=@comp/api`. * **Workspace Package Building**: Builds shared workspace packages (`packages/db`, `packages/integration-platform`). * **NestJS Application Build**: Navigates to `apps/api` and builds the NestJS application using `bun run build`. * **Build Output Verification**: Checks for the presence of `main.js` in the build output. * **Artifact Preparation**: * Creates a `docker-build` directory. * Copies the built `api` application artifacts (handling both `dist/apps/api/src` and `dist/src` output structures). * Copies the `prisma` directory. * Copies the root `node_modules` directory. * Replaces workspace symlinks for `@trycompai/utils`, `@trycompai/db`, and `@comp/integration-platform` with their actual built output and `package.json` files. * Copies the `Dockerfile` to the `docker-build` directory. * Modifies `package.json` to remove the workspace dependency for `@comp/integration-platform` before copying. * Copies `bun.lock`. * **Docker Image Build**: Builds the Docker image using the prepared `docker-build` context and tags it with the commit hash and `latest`. ### Post-Build Phase This phase handles the deployment of the newly built Docker image. **Key Actions:** * Push the Docker image to Amazon ECR with both the specific `IMAGE_TAG` and `latest`. * Update the Amazon ECS service to use the new image, forcing a new deployment. * Generate `imagedefinitions.json` for ECS deployment. The build process critically depends on several environment variables, which are validated during the `build` phase. These include database connection strings, base URLs for various services, and AWS credentials for S3 access.
Essential Environment Variables | Variable Name | Description | | :------------------------ | :--------------------------------------------------- | | `DATABASE_URL` | Connection string for the database. | | `BASE_URL` | Base URL for the application. | | `BETTER_AUTH_URL` | URL for the authentication service. | | `TRUST_APP_URL` | URL for the trusted application. | | `APP_AWS_BUCKET_NAME` | AWS S3 bucket name for application assets. | | `APP_AWS_ACCESS_KEY_ID` | AWS access key ID for S3. | | `APP_AWS_SECRET_ACCESS_KEY` | AWS secret access key for S3. |
### Build Flowchart The following flowchart illustrates the detailed steps within the `build` phase of the standard CodeBuild pipeline. Sources: [apps/api/buildspec.yml:1-105](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L1-L105) ## Multi-stage Docker Build Pipeline (`buildspec.multistage.yml`) This alternative pipeline simplifies the CodeBuild process by leveraging a multi-stage Dockerfile (`Dockerfile.multistage`) to handle the entire build process within a Docker container. CodeBuild's role is reduced to orchestrating the Docker build, pushing the image, and updating the ECS service. ### Pipeline Phases ### Pre-Build Phase Similar to the standard pipeline, this phase handles ECR login and image tagging. **Key Actions:** * Log in to Amazon ECR. * Derive `COMMIT_HASH` and set `IMAGE_TAG`. ### Build Phase The core difference lies here: the actual application build is performed by Docker. **Key Actions:** * Change directory to `apps/api`. * Execute `docker build` using `Dockerfile.multistage` with the `production` target. The build context is set to the monorepo root (`../..`), allowing the Dockerfile to access all necessary files. ### Post-Build Phase This phase is identical to the standard pipeline, handling deployment. **Key Actions:** * Push the Docker image to Amazon ECR. * Update the Amazon ECS service. * Generate `imagedefinitions.json`. ### Build Flowchart (Multi-stage) Sources: [apps/api/buildspec.multistage.yml:1-32](https://github.com/blade47/comp/blob/main/apps/api/buildspec.multistage.yml#L1-L32) ## Local Development and Testing (`docker-compose.yml`) The `apps/api/docker-compose.yml` file is designed for local development and testing of the `api` service. It utilizes the same multi-stage Dockerfile (`Dockerfile.multistage`) as the simplified CodeBuild pipeline to ensure consistency between local and production builds. ### Service Configuration The `api` service is configured with the following properties: | Property | Value | Description | | :-------------- | :------------------------------------ | :----------------------------------------------------------------------- | | `build.context` | `../..` | The build context is the monorepo root. | | `build.dockerfile` | `apps/api/Dockerfile.multistage` | Specifies the multi-stage Dockerfile for building. | | `build.target` | `production` | Builds the `production` stage of the Dockerfile. | | `container_name` | `comp-api-test` | Assigns a specific name to the container. | | `ports` | `"3333:3333"` | Maps container port 3333 to host port 3333. | | `environment` | `NODE_ENV=production`, `PORT=3333` | Sets environment variables within the container. | | `env_file` | `.env` | Loads environment variables from a local `.env` file. | | `healthcheck` | `CMD wget ... http://localhost:3333/v1/health` | Defines a health check that pings the `/v1/health` endpoint. | | `restart` | `unless-stopped` | Restarts the container automatically unless explicitly stopped. | This `docker-compose.yml` is explicitly marked for local testing only. It should not be used for production deployments. ### Healthcheck Flow The healthcheck defined in `docker-compose.yml` ensures that the `api` service is running and responsive before marking the container as healthy. ```mermaid sequenceDiagram participant DockerCompose participant APIService as "API Service (Container)" participant HealthEndpoint as "API Health Endpoint (/v1/health)" DockerCompose->>APIService: Start container (comp-api-test) APIService-->>DockerCompose: Container started loop Healthcheck (every 30s) DockerCompose->>APIService: Execute healthcheck command (wget) APIService->>HealthEndpoint: HTTP GET /v1/health HealthEndpoint-->>APIService: HTTP 200 OK APIService-->>DockerCompose: Healthcheck successful end DockerCompose->>DockerCompose: Mark service as healthy ``` Sources: [apps/api/docker-compose.yml:1-24](https://github.com/blade47/comp/blob/main/apps/api/docker-compose.yml#L1-L24) ## Dependency Management (`.syncpackrc.json`) The `.syncpackrc.json` file configures `syncpack`, a tool used to maintain consistency in package dependencies across the monorepo. This ensures that all packages using a particular dependency (e.g., React, Next.js) are on the same version, and that internal workspace packages are correctly referenced. ### Configuration Elements * **`source`**: Specifies the locations of `package.json` files to be managed. This includes the root `package.json` and those within `apps/*/package.json` and `packages/*/package.json`. * **`dependencyTypes`**: Defines which types of dependencies `syncpack` should manage: `prod` (dependencies), `dev` (devDependencies), and `peer` (peerDependencies). * **`semverGroups`**: Defines rules for semantic versioning ranges. * A specific rule ensures that internal packages (prefixed with `@comp/`) always use `workspace:*` for their version range, indicating they are part of the monorepo. * **`versionGroups`**: Defines groups of packages that must have consistent versions across all `package.json` files in the monorepo. This is crucial for avoiding dependency hell and ensuring a stable build environment. * **`lintRules`**: Defines rules for forbidden dependencies. For example, it prevents direct dependencies on Node.js built-in modules like `crypto`, `fs`, or `path`, which might indicate a misunderstanding of module bundling or environment. ### Version Groups Examples The following table lists some of the key dependency groups enforced by `syncpack` to maintain consistency: | Label | Dependencies | | :---------------------------------- | :---------------------------------------------------------------------------- | | Use exact versions for internal packages | `@comp/**` | | Ensure React is consistent | `react`, `react-dom`, `@types/react`, `@types/react-dom`, `react-is` | | Ensure Next.js is consistent | `next` | | Ensure TypeScript is consistent | `typescript` | | Ensure common build tools are consistent | `postcss`, `tailwindcss`, `@tailwindcss/**`, `autoprefixer` | | Ensure testing tools are consistent | `@types/node`, `prettier`, `turbo` | | Ensure ESLint is consistent | `eslint`, `eslint-config-next` | Sources: [.syncpackrc.json:1-55](https://github.com/blade47/comp/blob/main/.syncpackrc.json#L1-L55) --- ## Technical docs: Auth Security URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/auth-security
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/auth/hybrid-auth.guard.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts) - [apps/api/src/auth/types.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/types.ts) - [apps/api/src/auth/platform-admin.guard.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/platform-admin.guard.ts) - [apps/api/src/auth/auth-context.decorator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/auth-context.decorator.ts) - [apps/api/src/auth/auth.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/auth.module.ts) - [apps/api/src/auth/api-key.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.service.ts) - [apps/api/src/auth/internal-token.guard.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/internal-token.guard.ts) - [apps/api/src/auth/api-key.guard.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.guard.ts) - [apps/api/src/auth/organization.decorator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/organization.decorator.ts) - [apps/api/src/auth/role-validator.guard.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/role-validator.guard.ts)
The authentication and authorization system within the API (`apps/api`) is designed to secure endpoints by verifying the identity of incoming requests and ensuring they have the necessary permissions. It supports multiple authentication mechanisms, including API Keys for external integrations, JSON Web Tokens (JWT) for internal frontend applications, and an internal token for inter-service communication. This system leverages NestJS Guards and custom decorators to provide a flexible and robust security layer, allowing granular control over access to resources based on authentication type, user identity, organization context, and assigned roles. ## Authentication Context and Types The core of the authentication system relies on defining a clear context for authenticated requests. This context is captured by the `AuthenticatedRequest` interface, which extends the standard `Request` object, and the `AuthContext` interface, used for extracting authentication details. ### AuthenticatedRequest and AuthContext These interfaces define the structure for authentication-related data that is attached to the request object after successful authentication. ```typescript export interface AuthenticatedRequest extends Request { organizationId: string; authType: 'api-key' | 'jwt'; isApiKey: boolean; userId?: string; // Only available for JWT auth userEmail?: string; // Only available for JWT auth userRoles: string[] | null; } export interface AuthContext { organizationId: string; authType: 'api-key' | 'jwt'; isApiKey: boolean; userId?: string; // Only available for JWT auth userEmail?: string; // Only available for JWT auth userRoles: string[] | null; } ``` Sources: [apps/api/src/auth/types.ts:3-17](https://github.com/blade47/comp/blob/main/apps/api/src/auth/types.ts#L3-L17) The `userId` and `userEmail` fields are only populated when authentication is performed via JWT (session-based authentication). For API Key authentication, these fields will be undefined, as API keys are organization-scoped and not tied to a specific user. ## Authentication Guards The API uses several NestJS `CanActivate` guards to enforce different authentication and authorization policies. ### HybridAuthGuard The `HybridAuthGuard` is the primary authentication guard, designed to handle both API Key and JWT-based authentication seamlessly. It attempts to authenticate a request first using an API Key, and if that fails, it tries JWT authentication. ### Request Interception The guard intercepts incoming requests and inspects the `x-api-key` and `authorization` headers. ### API Key Authentication Attempt If an `x-api-key` header is present, the guard delegates to `handleApiKeyAuth`. ### JWT Authentication Attempt If no `x-api-key` is found, or API key authentication fails, the guard checks for an `Authorization: Bearer` header and delegates to `handleJwtAuth`. ### Context Assignment Upon successful authentication, the guard populates the `AuthenticatedRequest` object with relevant details like `organizationId`, `userId`, `userEmail`, `userRoles`, `authType`, and `isApiKey`. #### Hybrid Authentication Flow Sources: [apps/api/src/auth/hybrid-auth.guard.ts:25-34](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts#L25-L34), [apps/api/src/auth/hybrid-auth.guard.ts:36-54](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts#L36-L54), [apps/api/src/auth/hybrid-auth.guard.ts:56-173](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts#L56-L173) The `handleJwtAuth` method uses `jose` library's `createRemoteJWKSet` to fetch JSON Web Key Sets (JWKS) from the `betterAuthUrl`. It includes a retry mechanism for key mismatch errors (`ERR_JWKS_NO_MATCHING_KEY`). If a key mismatch occurs, it attempts to fetch a fresh JWKS with no cache to ensure it has the latest keys for verification. This helps in handling JWT key rotation scenarios. Sources: [apps/api/src/auth/hybrid-auth.guard.ts:77-119](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts#L77-L119) For JWT authentication, an `X-Organization-Id` header is explicitly required. The guard verifies that the authenticated user (`userId` from JWT payload) is a member of the specified organization using `db.member.findFirst`. Sources: [apps/api/src/auth/hybrid-auth.guard.ts:125-139](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts#L125-L139), [apps/api/src/auth/hybrid-auth.guard.ts:175-194](https://github.com/blade47/comp/blob/main/apps/api/src/auth/hybrid-auth.guard.ts#L175-L194) ### ApiKeyService and ApiKeyGuard The `ApiKeyService` is responsible for the logic of handling API keys, while `ApiKeyGuard` integrates this service into the NestJS guard system. #### ApiKeyService This service provides methods for hashing, extracting, and validating API keys. ```typescript @Injectable() export class ApiKeyService { private hashApiKey(apiKey: string, salt?: string): string { /* ... */ } extractApiKey(apiKeyHeader?: string): string | null { /* ... */ } async validateApiKey(apiKey: string): Promise { /* ... */ } } ``` Sources: [apps/api/src/auth/api-key.service.ts:10-12](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.service.ts#L10-L12) API keys are stored in the database (`db.apiKey`) in a hashed format, optionally with a salt. The `hashApiKey` method uses SHA256 for hashing. When validating, the provided API key is hashed with the stored salt (or without for backward compatibility) and compared against the stored hash. Sources: [apps/api/src/auth/api-key.service.ts:14-25](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.service.ts#L14-L25), [apps/api/src/auth/api-key.service.ts:58-62](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.service.ts#L58-L62) #### ApiKeyGuard This guard specifically handles API key authentication. It extracts the `X-API-Key` header, validates it using `ApiKeyService`, and attaches the `organizationId` to the request. ```mermaid sequenceDiagram participant Client participant ApiKeyGuard participant ApiKeyService participant Database Client->>ApiKeyGuard: Request with X-API-Key ApiKeyGuard->>ApiKeyService: extractApiKey(header) ApiKeyService-->>ApiKeyGuard: Extracted Key ApiKeyGuard->>ApiKeyService: validateApiKey(key) ApiKeyService->>Database: findMany({ isActive: true }) Database-->>ApiKeyService: API Key Records (hashed, salt, orgId, expiresAt) ApiKeyService->>ApiKeyService: Hash provided key with record salts ApiKeyService->>ApiKeyService: Find matching record & check expiry alt Key Valid & Not Expired ApiKeyService->>Database: update({ id: matchingRecord.id, data: { lastUsedAt: now() } }) Database-->>ApiKeyService: Update successful ApiKeyService-->>ApiKeyGuard: organizationId ApiKeyGuard->>ApiKeyGuard: Set request.organizationId ApiKeyGuard-->>Client: Access Granted else Key Invalid or Expired ApiKeyService-->>ApiKeyGuard: null ApiKeyGuard->>Client: UnauthorizedException end ``` Sources: [apps/api/src/auth/api-key.guard.ts:13-30](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.guard.ts#L13-L30), [apps/api/src/auth/api-key.service.ts:39-88](https://github.com/blade47/comp/blob/main/apps/api/src/auth/api-key.service.ts#L39-L88) ### PlatformAdminGuard This guard is used to restrict access to endpoints that should only be accessible by platform administrators. It exclusively uses JWT authentication. 1. **JWT Requirement**: It strictly requires a `Bearer` JWT token. 2. **JWT Verification**: Verifies the JWT against the `betterAuthUrl`'s JWKS endpoint, similar to `HybridAuthGuard`. 3. **Admin Check**: After verifying the JWT and extracting the `userId`, it queries the database (`db.user`) to check if `user.isPlatformAdmin` is true. 4. **Context Assignment**: If successful, it sets `request.userId`, `request.userEmail`, and `request.isPlatformAdmin`. Sources: [apps/api/src/auth/platform-admin.guard.ts:28-34](https://github.com/blade47/comp/blob/main/apps/api/src/auth/platform-admin.guard.ts#L28-L34), [apps/api/src/auth/platform-admin.guard.ts:40-45](https://github.com/blade47/comp/blob/main/apps/api/src/auth/platform-admin.guard.ts#L40-L45), [apps/api/src/auth/platform-admin.guard.ts:60-104](https://github.com/blade47/comp/blob/main/apps/api/src/auth/platform-admin.guard.ts#L60-L104) ### RoleValidatorGuard The `RoleValidatorGuard` enables role-based access control (RBAC) for specific endpoints. It is instantiated using the `RequireRoles` factory function, which defines the roles required for access. - **Role Check**: Compares the `userRoles` from the `AuthenticatedRequest` (populated by `HybridAuthGuard`) against the `allowedRoles` configured for the guard. - **API Key Exemption**: Requests authenticated via API keys are explicitly allowed to bypass role checks, as API keys are organization-scoped and not tied to specific user roles. However, they still require an `organizationId`. - **JWT Requirement**: For role-based authorization, JWT authentication is mandatory, ensuring `userId`, `organizationId`, and `userRoles` are available. Sources: [apps/api/src/auth/role-validator.guard.ts:20-22](https://github.com/blade47/comp/blob/main/apps/api/src/auth/role-validator.guard.ts#L20-L22), [apps/api/src/auth/role-validator.guard.ts:24-34](https://github.com/blade47/comp/blob/main/apps/api/src/auth/role-validator.guard.ts#L24-L34), [apps/api/src/auth/role-validator.guard.ts:36-40](https://github.com/blade47/comp/blob/main/apps/api/src/auth/role-validator.guard.ts#L36-L40), [apps/api/src/auth/role-validator.guard.ts:42-46](https://github.com/blade47/comp/blob/main/apps/api/src/auth/role-validator.guard.ts#L42-L46) ### InternalTokenGuard This guard protects internal API endpoints that should only be accessible by other internal services. - **Token Check**: It expects an `X-Internal-Token` header in the request. - **Environment Variable**: The value of this header is compared against the `process.env.INTERNAL_API_TOKEN` environment variable. - **Production Enforcement**: In production environments, `INTERNAL_API_TOKEN` must be configured. If not, an `UnauthorizedException` is thrown. - **Development Flexibility**: In non-production environments, if `INTERNAL_API_TOKEN` is not set, the guard allows the request to proceed, facilitating local development. Sources: [apps/api/src/auth/internal-token.guard.ts:15-28](https://github.com/blade47/comp/blob/main/apps/api/src/auth/internal-token.guard.ts#L15-L28), [apps/api/src/auth/internal-token.guard.ts:30-35](https://github.com/blade47/comp/blob/main/apps/api/src/auth/internal-token.guard.ts#L30-L35) ## Auth Context Decorators Custom parameter decorators simplify accessing authentication details within controllers and resolvers. These decorators rely on the `HybridAuthGuard` (or `ApiKeyGuard` for `Organization` decorator) having successfully populated the request object. Sources: [apps/api/src/auth/auth-context.decorator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/auth-context.decorator.ts), [apps/api/src/auth/organization.decorator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/auth/organization.decorator.ts) | Decorator | Description The `AuthModule` registers and exports the following guards and services: - `ApiKeyService` - `ApiKeyGuard` - `HybridAuthGuard` - `InternalTokenGuard` ## AuthModule The `AuthModule` is a NestJS module that encapsulates all authentication-related services and guards. It makes these components available for dependency injection throughout the application. ```typescript import { Module } from '@nestjs/common'; import { ApiKeyGuard } from './api-key.guard'; import { ApiKeyService } from './api-key.service'; import { HybridAuthGuard } from './hybrid-auth.guard'; import { InternalTokenGuard } from './internal-token.guard'; @Module({ providers: [ApiKeyService, ApiKeyGuard, HybridAuthGuard, InternalTokenGuard], exports: [ApiKeyService, ApiKeyGuard, HybridAuthGuard, InternalTokenGuard], }) export class AuthModule {} ``` Sources: [apps/api/src/auth/auth.module.ts:1-12](https://github.com/blade47/comp/blob/main/apps/api/src/auth/auth.module.ts#L1-L12) --- ## Technical docs: POST Close a browser session URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-closesession ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: Assistant Chat URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/assistant-chat
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/assistant-chat/assistant-chat.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.service.ts) - [apps/api/src/assistant-chat/assistant-chat.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.controller.ts) - [apps/api/src/assistant-chat/assistant-chat.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.dto.ts) - [apps/api/src/assistant-chat/upstash-redis.client.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/upstash-redis.client.ts) - [apps/api/src/assistant-chat/assistant-chat.types.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.types.ts) - [apps/api/src/assistant-chat/assistant-chat.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.module.ts)
The Assistant Chat module provides an API for managing ephemeral chat history for an AI assistant. It allows users to retrieve, save, and clear their conversation history, scoped to their user ID and organization ID. The history is stored in a Redis-compatible key-value store with a default time-to-live (TTL) of 7 days, designed for session context rather than long-term archiving. This module integrates with the application's authentication system to ensure that chat history operations are user-scoped and secure. It leverages a flexible Redis client that can connect to an Upstash Redis instance or fall back to an in-memory store for development or testing environments. ## Architecture Overview The Assistant Chat feature is implemented as a NestJS module, encapsulating its components: a controller for handling API requests, a service for business logic and data manipulation, and DTOs for data validation and transfer. It relies on a Redis client for persistence and integrates with the application's authentication module. The chat history is designed to be ephemeral, with a default Time-To-Live (TTL) of 7 days. This means chat sessions are not intended for long-term storage or searchable archives but rather for maintaining context within recent interactions. The TTL can be configured via the `ASSISTANT_CHAT_TTL_SECONDS` environment variable. Sources: [apps/api/src/assistant-chat/assistant-chat.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.module.ts), [apps/api/src/assistant-chat/assistant-chat.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.controller.ts), [apps/api/src/assistant-chat/assistant-chat.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.service.ts) ## API Endpoints The `AssistantChatController` exposes a set of RESTful endpoints for managing assistant chat history. All endpoints are protected by the `HybridAuthGuard` and require user-scoped authentication. API key authentication is explicitly disallowed for chat history operations. ### Base Path `/v1/assistant-chat` Sources: [apps/api/src/assistant-chat/assistant-chat.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.controller.ts) ### Endpoints | Method | Path | Description | Request Body | Response Body | | :----- | :-------- | :------------------------------------------------------------------------ | :----------------------------------------- | :--------------------------------------------- | | `GET` | `/history` | Retrieves the current user-scoped assistant chat history. | N/A | `{ messages: AssistantChatMessage[] }` | | `PUT` | `/history` | Replaces the current user-scoped assistant chat history with new messages. | `SaveAssistantChatHistoryDto` | `{ success: true }` | | `DELETE` | `/history` | Deletes the current user-scoped assistant chat history. | N/A | `{ success: true }` | Sources: [apps/api/src/assistant-chat/assistant-chat.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.controller.ts) ### Authentication and Authorization All endpoints are secured using `HybridAuthGuard`. The `AuthContext` decorator is used to extract user and organization information from the authenticated request. A `BadRequestException` is thrown if the `organizationId` or `userId` is missing, or if the request is authenticated via an API key instead of a user JWT. Assistant chat history operations are strictly limited to user-authenticated requests (Bearer JWT). Requests authenticated with an API key will be rejected with a `BadRequestException`. This ensures that chat history is always tied to a specific user and organization. Sources: [apps/api/src/assistant-chat/assistant-chat.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.controller.ts) ## Data Models The core data structure for assistant chat is `AssistantChatMessage`, which represents a single message in the conversation. ### AssistantChatMessage This type defines the structure of a single message, including its ID, role (user or assistant), text content, and creation timestamp. | Field | Type | Description | Example | | :-------- | :------- | :----------------------------------------- | :-------------------- | | `id` | `string` | Unique identifier for the message. | `msg_abc123` | | `role` | `'user' \| 'assistant'` | The sender of the message. | `user` | | `text` | `string` | The content of the message. | `How do I invite a teammate?` | | `createdAt` | `number` | Unix epoch timestamp in milliseconds. | `1735781554000` | Sources: [apps/api/src/assistant-chat/assistant-chat.types.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.types.ts), [apps/api/src/assistant-chat/assistant-chat.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.dto.ts) ### Data Transfer Objects (DTOs) The `assistant-chat.dto.ts` file defines DTOs used for API request bodies and Swagger documentation. Sources: [apps/api/src/assistant-chat/assistant-chat.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.dto.ts) ## Service Logic The `AssistantChatService` handles the core business logic for chat history management, including interaction with the Redis client and data validation. ### Key Generation A unique key is generated for each user's chat history in Redis, combining the organization ID and user ID. This ensures data isolation between different users and organizations. ```typescript const getAssistantChatKey = ({ organizationId, userId, }: GetAssistantChatKeyParams): string => { return `assistant-chat:v1:${organizationId}:${userId}`; }; ``` Sources: [apps/api/src/assistant-chat/assistant-chat.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.service.ts#L16-L21) ### History Operations - **`getHistory(params)`**: Retrieves the chat history for a given user and organization. It fetches raw data from Redis and then uses a Zod schema (`StoredMessagesSchema`) for safe parsing and validation. If parsing fails, an empty array is returned. - **`saveHistory(params, messages)`**: Stores the provided chat messages for a user and organization. It first validates the incoming messages against `StoredMessagesSchema` to maintain data integrity in the cache. The data is stored with a configurable TTL. - **`clearHistory(params)`**: Deletes the chat history associated with a user and organization from Redis. Sources: [apps/api/src/assistant-chat/assistant-chat.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.service.ts#L29-L57) ### Data Validation The `AssistantChatService` uses Zod schemas to ensure the integrity and shape of the stored chat messages. - `StoredMessageSchema`: Validates individual chat messages. - `StoredMessagesSchema`: Validates an array of `StoredMessageSchema` objects. Sources: [apps/api/src/assistant-chat/assistant-chat.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/assistant-chat.service.ts#L8-L14) ## Redis Client The `upstash-redis.client.ts` file provides an abstraction over Redis interactions. It dynamically chooses between an actual Upstash Redis client and an in-memory implementation based on environment variables. Sources: [apps/api/src/assistant-chat/upstash-redis.client.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/upstash-redis.client.ts#L23-L34) ### `assistantChatRedisClient` This client object provides `get`, `set`, and `del` methods, abstracting the underlying storage mechanism. It's used by the `AssistantChatService` to interact with the chat history store. The `InMemoryRedis` class provides a basic in-memory key-value store that mimics the behavior of a Redis client for `get`, `set`, and `del` operations. It supports an optional `ex` (expire) parameter for `set` operations, which sets a time-to-live for stored keys. This implementation is primarily for local development or testing when an external Redis instance is not available. ```typescript class InMemoryRedis { private storage = new Map(); async get(key: string): Promise { const record = this.storage.get(key); if (!record) return null; if (record.expiresAt && record.expiresAt <= Date.now()) { this.storage.delete(key); return null; } return record.value as T; } async set( key: string, value: unknown, options?: { ex?: number }, ): Promise<'OK'> { const expiresAt = options?.ex ? Date.now() + options.ex * 1000 : undefined; this.storage.set(key, { value, expiresAt }); return 'OK'; } async del(key: string): Promise { const existed = this.storage.delete(key); return existed ? 1 : 0; } } ``` Sources: [apps/api/src/assistant-chat/upstash-redis.client.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/upstash-redis.client.ts#L9-L31) --- ## Technical docs: POST Navigate to a URL URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-navigatetourl ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Check authentication status URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-checkauth ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: Evidence Forms URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/evidence-forms
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/evidence-forms/evidence-forms.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts) - [apps/api/src/evidence-forms/evidence-forms.definitions.ts](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.definitions.ts) - [apps/api/src/evidence-forms/evidence-forms.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.controller.ts) - [apps/api/src/evidence-forms/evidence-forms.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.module.ts)
The Evidence Forms module provides a robust system for managing and processing various types of evidence submissions within an organization. It defines a set of pre-built forms, handles their submission, validation, file uploads, and review processes. This module integrates with authentication and attachment services to ensure secure and efficient evidence management. At a high level, the system allows users to submit structured data and associated files for different evidence types (e.g., meeting minutes, policy documents). Authorized personnel can then review these submissions, approving or rejecting them with reasons. All interactions are secured through JWT or API key authentication and scoped to specific organizations. ## Architecture Overview The Evidence Forms module follows a standard NestJS architecture, comprising a Controller, Service, and Module. It leverages shared definitions for form structures and integrates with other core services like `AttachmentsService` for file management and the database (`@trycompai/db`) for persistence. The `EvidenceFormsController` exposes RESTful API endpoints, handling incoming HTTP requests. These requests are then delegated to the `EvidenceFormsService`, which encapsulates the business logic, data validation, and interactions with the database and other services. The `EvidenceFormsModule` orchestrates these components, declaring dependencies and making the service available for injection. Sources: - [apps/api/src/evidence-forms/evidence-forms.module.ts:1-11](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.module.ts#L1-L11) - [apps/api/src/evidence-forms/evidence-forms.controller.ts:1-50](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.controller.ts#L1-L50) - [apps/api/src/evidence-forms/evidence-forms.service.ts:1-26](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L1-L26) ## Data Structures and Definitions The core of the Evidence Forms system relies on well-defined data structures, primarily sourced from a shared `@comp/company` package. These definitions dictate the structure of forms, their fields, and the schema for submissions. ### Form Definitions Key definitions include: * `evidenceFormTypeSchema`: A Zod schema for validating the type of an evidence form (e.g., 'meeting', 'policy'). * `evidenceFormDefinitions`: An object mapping `EvidenceFormType` to its detailed `EvidenceFormDefinition`. * `evidenceFormDefinitionList`: An array of all available `EvidenceFormDefinition` objects. * `evidenceFormSubmissionSchemaMap`: A map where each `EvidenceFormType` is associated with its specific Zod schema for validating submission payloads. * `EvidenceFormFieldDefinition`: Describes a single field within an evidence form, including its key, type (e.g., 'text', 'file', 'matrix'), and validation rules. * `EvidenceFormDefinition`: Defines an entire evidence form, including its `type`, `name`, `description`, `fields`, and `submissionDateMode`. Sources: - [apps/api/src/evidence-forms/evidence-forms.definitions.ts:1-10](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.definitions.ts#L1-L10) - [apps/api/src/evidence-forms/evidence-forms.service.ts:10-16](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L10-L16) ### Validation Schemas The service uses Zod for robust input validation: * `listQuerySchema`: Validates query parameters for listing submissions (search, limit, offset). * `uploadSchema`: Validates parameters for file uploads (formType, fileName, fileType, fileData). * `reviewSchema`: Validates the payload for reviewing a submission (action: 'approved' | 'rejected', reason). ```typescript // Example: listQuerySchema const listQuerySchema = z.object({ search: z.string().trim().optional(), limit: z.coerce.number().int().min(1).max(200).optional().default(50), offset: z.coerce.number().int().min(0).optional().default(0), }); ``` Sources: - [apps/api/src/evidence-forms/evidence-forms.service.ts:18-22](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L18-L22) - [apps/api/src/evidence-forms/evidence-forms.service.ts:24-28](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L24-L28) - [apps/api/src/evidence-forms/evidence-forms.service.ts:30-33](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L30-L33) ## Core Service Logic (`EvidenceFormsService`) The `EvidenceFormsService` handles all business logic related to evidence forms. ### Authentication and Authorization The service enforces strict access control: * `requireJwtUser(authContext: AuthContext)`: Ensures the request is authenticated via JWT and has a `userId`. API key authentication is explicitly denied for operations requiring a user context. * `requirePrivilegedEvidenceAccess(authContext: AuthContext)`: Builds upon `requireJwtUser` by checking if the authenticated user possesses one of the `EVIDENCE_FORM_REVIEWER_ROLES` (`owner`, `admin`, `auditor`). This is crucial for operations like reviewing submissions or exporting data. The `EVIDENCE_FORM_REVIEWER_ROLES` constant defines which user roles are authorized to perform privileged actions on evidence forms. Sources: - [apps/api/src/evidence-forms/evidence-forms.service.ts:100-109](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L100-L109) - [apps/api/src/evidence-forms/evidence-forms.service.ts:111-124](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L111-L124) - [apps/api/src/evidence-forms/evidence-forms.service.ts:35-35](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L35-L35) ### File Handling The service provides functionality for uploading and managing files associated with evidence forms. * `decodeBase64File(fileData: string)`: Decodes a base64 encoded file string into a Buffer, performing basic validation on the input format and size. * `uploadFile(params: { ... })`: Handles the entire file upload process. It validates the input payload, decodes the base64 file data, checks against size limits (`MAX_UPLOAD_FILE_SIZE_BYTES`, `MAX_UPLOAD_BASE64_LENGTH`), and then delegates to `AttachmentsService` to upload the file to S3 and generate a presigned download URL. Uploaded files are subject to a maximum size limit of 100MB. This is enforced both by checking the base64 string length and the decoded file buffer length. Sources: - [apps/api/src/evidence-forms/evidence-forms.service.ts:126-146](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L126-L146) - [apps/api/src/evidence-forms/evidence-forms.service.ts:37-38](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L37-L38) - [apps/api/src/evidence-forms/evidence-forms.service.ts:321-356](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L321-L356) ### Data Transformation and Export Several utility functions facilitate data manipulation, especially for CSV export: * `toCsvRow(values: string[])`: Converts an array of strings into a CSV row, handling proper escaping of double quotes. * `flattenValue(value: unknown)`: Converts various data types (objects, numbers, booleans, strings) into a string representation suitable for CSV. Special handling is included for file objects to return their download URL. * `flattenMatrixRows(value: unknown, field: EvidenceFormFieldDefinition)`: Specifically designed to flatten data from 'matrix' type form fields into a readable string format for CSV. * `normalizeSubmissionFormType(submission: T)`: Transforms the internal database `DbEvidenceFormType` to the external `EvidenceFormType` for API responses. Sources: - [apps/api/src/evidence-forms/evidence-forms.service.ts:40-42](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L40-L42) - [apps/api/src/evidence-forms/evidence-forms.service.ts:44-71](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L44-L71) - [apps/api/src/evidence-forms/evidence-forms.service.ts:73-94](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L73-L94) - [apps/api/src/evidence-forms/evidence-forms.service.ts:96-98](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L96-L98) ### Submission and Review Workflow The service manages the lifecycle of evidence form submissions. **Key methods:** * `listForms()`: Returns a list of all available evidence form definitions. * `getFormStatuses(organizationId: string)`: Retrieves the latest submission date for each form type within a given organization. * `getFormWithSubmissions(params: { ... })`: Fetches a specific form definition along with its submissions for an organization. Requires privileged access and supports search, pagination. * `getSubmission(params: { ... })`: Retrieves a single evidence form submission by ID. Requires privileged access. * `submitForm(params: { ... })`: Creates a new evidence form submission. It validates the payload against the form's schema, handles automatic submission date population, and stores the data in the database. * `reviewSubmission(params: { ... })`: Allows privileged users to approve or reject a pending submission. Requires a reason for rejection. * `getMySubmissions(params: { ... })`: Retrieves all submissions made by the currently authenticated user. * `getPendingSubmissionCount(params: { ... })`: Returns the count of pending submissions for the authenticated user. * `exportCsv(params: { ... })`: Exports all submissions for a specific form type within an organization to a CSV format. This method requires privileged access and uses the data transformation utilities (`flattenValue`, `flattenMatrixRows`, `toCsvRow`) to format the output. It also generates presigned URLs for any attached files. Sources: - [apps/api/src/evidence-forms/evidence-forms.service.ts:148-150](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L148-L150) - [apps/api/src/evidence-forms/evidence-forms.service.ts:152-167](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L152-L167) - [apps/api/src/evidence-forms/evidence-forms.service.ts:169-216](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L169-L216) - [apps/api/src/evidence-forms/evidence-forms.service.ts:218-251](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L218-L251) - [apps/api/src/evidence-forms/evidence-forms.service.ts:253-319](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L253-L319) - [apps/api/src/evidence-forms/evidence-forms.service.ts:358-444](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L358-L444) - [apps/api/src/evidence-forms/evidence-forms.service.ts:446-500](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L446-L500) - [apps/api/src/evidence-forms/evidence-forms.service.ts:502-526](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L502-L526) - [apps/api/src/evidence-forms/evidence-forms.service.ts:528-543](https://github.com/blade47/comp/blob/main/apps/api/src/evidence-forms/evidence-forms.service.ts#L528-L543) ## API Endpoints (`EvidenceFormsController`) The `EvidenceFormsController` exposes a set of RESTful API endpoints for interacting with the evidence forms system. All endpoints are protected by `HybridAuthGuard` and require an `X-Organization-Id` header. | Method | Path | Summary | Description --- File: apps/api/src/evidence-forms/evidence-forms.service.ts --- import { AttachmentsService } from '@/attachments/attachments.service'; import type { AuthContext } from '@/auth/types'; import { db, EvidenceFormType as DbEvidenceFormType } from '@trycompai/db'; import { toDbEvidenceFormType, toExternalEvidenceFormType, } from '@comp/company'; import { BadRequestException, Injectable, NotFoundException, UnauthorizedException, } from '@nestjs/common'; import { z } from 'zod'; import { evidenceFormDefinitionList, evidenceFormDefinitions, evidenceFormSubmissionSchemaMap, evidenceFormTypeSchema, type EvidenceFormFieldDefinition, type EvidenceFormType, } from './evidence-forms.definitions'; const listQuerySchema = z.object({ search: z.string().trim().optional(), limit: z.coerce.number().int().min(1).max(200).optional().default(50), offset: z.coerce.number().int().min(0).optional().default(0), }); const uploadSchema = z.object({ formType: evidenceFormTypeSchema, fileName: z.string().min(1), fileType: z.string().min(1), fileData: z.string().min(1), }); const reviewSchema = z.object({ action: z.enum(['approved', 'rejected']), reason: z.string().trim().optional(), }); const EVIDENCE_FORM_REVIEWER_ROLES = ['owner', 'admin', 'auditor'] as const; const MAX_UPLOAD_FILE_SIZE_BYTES = 100 * 1024 * 1024; const MAX_UPLOAD_BASE64_LENGTH = Math.ceil(MAX_UPLOAD_FILE_SIZE_BYTES / 3) * 4; function toCsvRow(values: string[]): string { return values.map((value) => `"${value.replace(/"/g, '""')}"`).join(','); } function flattenValue(value: unknown): string { if (value === null || value === undefined) { return ''; } if (typeof value === 'object') { if ( 'fileName' in value && typeof value.fileName === 'string' && 'downloadUrl' in value && typeof value.downloadUrl === 'string' ) { return value.downloadUrl; } return JSON.stringify(value); } if (typeof value === 'string') { return value; } if ( typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint' ) { return value.toString(); } if (typeof value === 'symbol') { return value.description ?? ''; } return ''; } function flattenMatrixRows( value: unknown, field: EvidenceFormFieldDefinition, ): string { if (!Array.isArray(value)) { return ''; } const columns = Array.isArray(field.columns) ? field.columns : []; if (columns.length === 0) { return JSON.stringify(value); } return value .filter((row) => row && typeof row === 'object') .map((row) => { const rowRecord = row as Record; return columns .map((column) => { const cellValue = rowRecord[column.key]; const normalizedValue = typeof cellValue === 'string' ? cellValue : ''; return `${column.label}: ${normalizedValue}`; }) .join(' | '); }) .join(' || '); } function normalizeSubmissionFormType< T extends { formType: DbEvidenceFormType }, >(submission: T): Omit & { formType: EvidenceFormType } { return { ...submission, formType: toExternalEvidenceFormType(submission.formType) ?? 'meeting', }; } @Injectable() export class EvidenceFormsService { constructor(private readonly attachmentsService: AttachmentsService) {} private requireJwtUser(authContext: AuthContext): string { if (authContext.isApiKey || authContext.authType === 'api-key') { throw new UnauthorizedException( 'This endpoint requires JWT authentication and does not support API key authentication', ); } if (!authContext.userId) { throw new UnauthorizedException('Authenticated user session is required'); } return authContext.userId; } private requirePrivilegedEvidenceAccess(authContext: AuthContext): string { const userId = this.requireJwtUser(authContext); const roles = authContext.userRoles ?? []; const hasRequiredRole = EVIDENCE_FORM_REVIEWER_ROLES.some((role) => roles.includes(role), ); if (!hasRequiredRole) { throw new UnauthorizedException( `Access denied. Required one of roles: ${EVIDENCE_FORM_REVIEWER_ROLES.join(', ')}`, ); } return userId; } private decodeBase64File(fileData: string): Buffer { const normalized = fileData.trim(); if (normalized.length === 0 || normalized.length % 4 !== 0) { throw new BadRequestException( 'Invalid file data. Expected base64 string.', ); } const base64Pattern = /^[A-Za-z0-9+/]+={0,2}$/; if (!base64Pattern.test(normalized)) { throw new BadRequestException( 'Invalid file data. Expected base64 string.', ); } const fileBuffer = Buffer.from(normalized, 'base64'); if (!fileBuffer.length) { throw new BadRequestException('File cannot be empty'); } return fileBuffer; } listForms() { return evidenceFormDefinitionList; } async getFormStatuses(organizationId: string) { const results = await db.evidenceSubmission.groupBy({ by: ['formType'], where: { organizationId }, _max: { submittedAt: true }, }); const statuses: Record = {}; for (const form of evidenceFormDefinitionList) { const match = results.find( (r) => r.formType === toDbEvidenceFormType(form.type), ); statuses[form.type] = { lastSubmittedAt: match?._max.submittedAt?.toISOString() ?? null, }; } return statuses; } async getFormWithSubmissions(params: { organizationId: string; authContext: AuthContext; formType: string; search?: string; limit?: string; offset?: string; }) { const { organizationId, formType } = params; this.requirePrivilegedEvidenceAccess(params.authContext); const parsedType = evidenceFormTypeSchema.safeParse(formType); if (!parsedType.success) { throw new BadRequestException('Unsupported form type'); } const parsedQuery = listQuerySchema.safeParse({ search: params.search, limit: params.limit, offset: params.offset, }); if (!parsedQuery.success) { throw new BadRequestException(parsedQuery.error.flatten()); } const query = parsedQuery.data; const submissions = await db.evidenceSubmission.findMany({ where: { organizationId, formType: toDbEvidenceFormType(parsedType.data), }, include: { submittedBy: { select: { id: true, name: true, email: true, }, }, }, orderBy: { submittedAt: 'desc', }, }); const filtered = query.search ? submissions.filter((submission) => { const searchTarget = JSON.stringify(submission.data).toLowerCase(); return searchTarget.includes(query.search!.toLowerCase()); }) : submissions; const paginated = filtered.slice(query.offset, query.offset + query.limit); return { form: evidenceFormDefinitions[parsedType.data], submissions: paginated.map(normalizeSubmissionFormType), total: filtered.length, }; } async getSubmission(params: { organizationId: string; authContext: AuthContext; formType: string; submissionId: string; }) { this.requirePrivilegedEvidenceAccess(params.authContext); const parsedType = evidenceFormTypeSchema.safeParse(params.formType); if (!parsedType.success) { throw new BadRequestException('Unsupported form type'); } const submission = await db.evidenceSubmission.findFirst({ where: { id: params.submissionId, organizationId: params.organizationId, formType: toDbEvidenceFormType(parsedType.data), }, include: { submittedBy: { select: { id: true, name: true, email: true, }, }, reviewedBy: { select: { id: true, name: true, email: true, }, }, }, }); if (!submission) { throw new NotFoundException('Submission not found'); } return { form: evidenceFormDefinitions[parsedType.data], submission: normalizeSubmissionFormType(submission), }; } async submitForm(params: { organizationId: string; formType: string; payload: unknown; authContext: AuthContext; }) { const parsedType = evidenceFormTypeSchema.safeParse(params.formType); if (!parsedType.success) { throw new BadRequestException('Unsupported form type'); } if (!params.authContext.userId) { throw new BadRequestException( 'Authenticated user session is required to submit evidence forms', ); } const formDefinition = evidenceFormDefinitions[parsedType.data]; const nowIso = new Date().toISOString(); if (!params.payload || typeof params.payload !== 'object') { throw new BadRequestException('Submission payload must be an object'); } const payloadObject: Record = { ...(params.payload as Record), }; if (formDefinition.submissionDateMode === 'auto') { payloadObject.submissionDate = nowIso; } const schema = evidenceFormSubmissionSchemaMap[parsedType.data]; const parsedPayload = schema.safeParse(payloadObject); if (!parsedPayload.success) { const flattened = parsedPayload.error.flatten(); const fieldErrors = Object.entries(flattened.fieldErrors) .map(([field, messages]) => { const msg = Array.isArray(messages) && messages.length > 0 ? messages[0] : 'is required'; return `${field}: ${msg}`; }) .slice(0, 5); const message = fieldErrors.length > 0 ? `Please fix the following: ${fieldErrors.join('; ')}` : 'Please fill in all required fields'; throw new BadRequestException(message); } return await db.evidenceSubmission .create({ data: { organizationId: params.organizationId, formType: toDbEvidenceFormType(parsedType.data), submittedById: params.authContext.userId, data: parsedPayload.data, }, include: { submittedBy: { select: { id: true, name: true, email: true, }, }, }, }) .then(normalizeSubmissionFormType); } async uploadFile(params: { organizationId: string; authContext: AuthContext; payload: unknown; }) { if (!params.authContext.userId) { throw new BadRequestException( 'Authenticated user session is required to upload evidence files', ); } const parsed = uploadSchema.safeParse(params.payload); if (!parsed.success) { throw new BadRequestException(parsed.error.flatten()); } if (parsed.data.fileData.length > MAX_UPLOAD_BASE64_LENGTH) { throw new BadRequestException( `File exceeds the ${MAX_UPLOAD_FILE_SIZE_BYTES / (1024 * 1024)}MB limit`, ); } const fileBuffer = this.decodeBase64File(parsed.data.fileData); if (fileBuffer.length > MAX_UPLOAD_FILE_SIZE_BYTES) { throw new BadRequestException( `File exceeds the ${MAX_UPLOAD_FILE_SIZE_BYTES / (1024 * 1024)}MB limit`, ); } const fileKey = await this.attachmentsService.uploadToS3( fileBuffer, parsed.data.fileName, parsed.data.fileType, params.organizationId, 'evidence-forms', parsed.data.formType, ); const downloadUrl = await this.attachmentsService.getPresignedDownloadUrl(fileKey); return { fileName: parsed.data.fileName, fileKey, downloadUrl, }; } async exportCsv(params: { organizationId: string; formType: string; authContext: AuthContext; }) { this.requirePrivilegedEvidenceAccess(params.authContext); const parsedType = evidenceFormTypeSchema.safeParse(params.formType); if (!parsedType.success) { throw new BadRequestException('Unsupported form type'); } const formType: EvidenceFormType = parsedType.data; const form = evidenceFormDefinitions[formType]; const submissions = await db.evidenceSubmission.findMany({ where: { organizationId: params.organizationId, formType: toDbEvidenceFormType(formType), }, include: { submittedBy: { select: { name: true, email: true, }, }, }, orderBy: { submittedAt: 'desc', }, }); if (submissions.length === 0) { throw new BadRequestException( 'No submissions available for export for this form', ); } const headers = [ 'submissionId', 'submissionDate', 'submittedByName', 'submittedByEmail', ...form.fields .filter((field) => field.key !== 'submissionDate') .map((field) => field.key), ]; const rows = await Promise.all( submissions.map(async (submission) => { const data = submission.data as Record; const fieldValues = await Promise.all( form.fields .filter((field) => field.key !== 'submissionDate') .map(async (field) => { const rawValue = data[field.key]; if ( rawValue && typeof rawValue === 'object' && 'fileKey' in rawValue && typeof rawValue.fileKey === 'string' ) { const signedUrl = await this.attachmentsService.getPresignedDownloadUrl( rawValue.fileKey, ); return signedUrl; } if (field.type === 'matrix') { return flattenMatrixRows(rawValue, field); } return flattenValue(rawValue); }), ); return [ submission.id, typeof data.submissionDate === 'string' ? data.submissionDate : submission.submittedAt.toISOString(), submission.submittedBy?.name ?? '', submission.submittedBy?.email ?? '', ...fieldValues, ]; }), ); const csvLines = [toCsvRow(headers), ...rows.map((row) => toCsvRow(row))]; return csvLines.join('\n'); } async reviewSubmission(params: { organizationId: string; formType: string; submissionId: string; payload: unknown; authContext: AuthContext; }) { const parsedType = evidenceFormTypeSchema.safeParse(params.formType); if (!parsedType.success) { throw new BadRequestException('Unsupported form type'); } const reviewerUserId = this.requirePrivilegedEvidenceAccess( params.authContext, ); const parsed = reviewSchema.safeParse(params.payload); if (!parsed.success) { throw new BadRequestException(parsed.error.flatten()); } if (parsed.data.action === 'rejected' && !parsed.data.reason) { throw new BadRequestException( 'A reason is required when rejecting a submission', ); } const submission = await db.evidenceSubmission.findFirst({ where: { id: params.submissionId, organizationId: params.organizationId, formType: toDbEvidenceFormType(parsedType.data), }, }); if (!submission) { throw new NotFoundException('Submission not found'); } if (submission.status !== 'pending') { throw new BadRequestException( 'Submission must be pending to be reviewed', ); } return await db.evidenceSubmission .update({ where: { id: params.submissionId }, data: { status: parsed.data.action, reviewedById: reviewerUserId, reviewedAt: new Date(), reviewReason: parsed.data.reason, }, include: { submittedBy: { select: { id: true, name: true, email: true, }, }, reviewedBy: { select: { id: true, name: true, email: true, }, }, }, }) .then(normalizeSubmissionFormType); } async getMySubmissions(params: { organizationId: string; authContext: AuthContext; formType?: string; }) { const userId = this.requireJwtUser(params.authContext); const where: Record = { organizationId: params.organizationId, submittedById: userId, }; if (params.formType) { const parsedType = evidenceFormTypeSchema.safeParse(params.formType); if (!parsedType.success) { throw new BadRequestException('Unsupported form type'); } where.formType = toDbEvidenceFormType(parsedType.data); } return await db.evidenceSubmission .findMany({ where, include: { reviewedBy: { select: { id: true, name: true, email: true, }, }, }, orderBy: { submittedAt: 'desc', }, }) .then((submissions) => submissions.map(normalizeSubmissionFormType)); } async getPendingSubmissionCount(params: { organizationId: string; authContext: AuthContext; }) { const userId = this.requireJwtUser(params.authContext); const count = await db.evidenceSubmission.count({ where: { organizationId: params.organizationId, submittedById: userId, status: 'pending', }, }); return { count }; } } --- File: apps/api/src/evidence-forms/evidence-forms.definitions.ts --- // Single source of truth: re-export from shared @comp/company package export { evidenceFormTypeSchema, evidenceFormFileSchema, evidenceFormSubmissionSchemaMap, evidenceFormDefinitions, evidenceFormDefinitionList, type EvidenceFormType, type EvidenceFormFieldDefinition, type EvidenceFormDefinition, } from '@comp/company'; --- File: apps/api/src/evidence-forms/evidence-forms.controller.ts --- import { AuthContext, OrganizationId } from '@/auth/auth-context.decorator'; import { HybridAuthGuard } from '@/auth/hybrid-auth.guard'; import type { AuthContext as AuthContextType } from '@/auth/types'; import { Body, Controller, Get, Header, Param, Patch, Post, Query, Res, UseGuards, } from '@nestjs/common'; import { ApiHeader, ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger'; import type { Response } from 'express'; import { EvidenceFormsService } from './evidence-forms.service'; @ApiTags('Evidence Forms') @Controller({ path: 'evidence-forms', version: '1' }) @UseGuards(HybridAuthGuard) @ApiSecurity('apikey') @ApiHeader({ name: 'X-Organization-Id', description: 'Organization ID (required for session auth, optional for API key auth)', required: false, }) export class EvidenceFormsController { constructor(private readonly evidenceFormsService: EvidenceFormsService) {} @Get() @ApiOperation({ summary: 'List evidence forms', description: 'List all available pre-built evidence forms', }) listForms() { return this.evidenceFormsService.listForms(); } @Get('statuses') @ApiOperation({ summary: 'Get submission statuses for all forms', description: 'Returns the latest submission date per form type for the active organization', }) async getFormStatuses(@OrganizationId() organizationId: string) { return this.evidenceFormsService.getFormStatuses(organizationId); } @Get('my-submissions') @ApiOperation({ summary: 'Get current user submissions', description: 'Returns all evidence form submissions by the authenticated user for the active organization', }) async getMySubmissions( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Query('formType') formType?: string, ) { return this.evidenceFormsService.getMySubmissions({ organizationId, authContext, formType, }); } @Get('my-submissions/pending-count') @ApiOperation({ summary: 'Get pending submission count for current user', description: 'Returns the count of pending evidence submissions for the authenticated user', }) async getPendingSubmissionCount( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, ) { return this.evidenceFormsService.getPendingSubmissionCount({ organizationId, authContext, }); } @Get(':formType') @ApiOperation({ summary: 'Get form definition and submissions', description: 'Fetch a specific form definition with submissions for the active organization', }) async getFormWithSubmissions( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Param('formType') formType: string, @Query('search') search?: string, @Query('limit') limit?: string, @Query('offset') offset?: string, ) { return this.evidenceFormsService.getFormWithSubmissions({ organizationId, authContext, formType, search, limit, offset, }); } @Get(':formType/submissions/:submissionId') @ApiOperation({ summary: 'Get a single submission', description: 'Fetch one evidence form submission for the active organization', }) async getSubmission( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Param('formType') formType: string, @Param('submissionId') submissionId: string, ) { return this.evidenceFormsService.getSubmission({ organizationId, authContext, formType, submissionId, }); } @Post(':formType/submissions') @ApiOperation({ summary: 'Submit evidence form entry', description: 'Create a new organization-scoped evidence form submission using Zod-validated payloads', }) async submitForm( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Param('formType') formType: string, @Body() body: unknown, ) { return this.evidenceFormsService.submitForm({ organizationId, formType, payload: body, authContext, }); } @Patch(':formType/submissions/:submissionId/review') @ApiOperation({ summary: 'Review a submission', description: 'Approve or reject an evidence form submission with an optional reason', }) async reviewSubmission( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Param('formType') formType: string, @Param('submissionId') submissionId: string, @Body() body: unknown, ) { return this.evidenceFormsService.reviewSubmission({ organizationId, formType, submissionId, payload: body, authContext, }); } @Post('uploads') @ApiOperation({ summary: 'Upload evidence form file', description: 'Upload a file for evidence form fields and return file metadata for submission payload', }) async uploadFile( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Body() body: unknown, ) { return this.evidenceFormsService.uploadFile({ organizationId, authContext, payload: body, }); } @Get(':formType/export.csv') @ApiOperation({ summary: 'Export form submissions to CSV', description: 'Export all form submissions for an organization as CSV', }) @Header('Content-Type', 'text/csv') async exportCsv( @OrganizationId() organizationId: string, @AuthContext() authContext: AuthContextType, @Param('formType') formType: string, @Res() res: Response, ) { const csv = await this.evidenceFormsService.exportCsv({ organizationId, authContext, formType, }); const filename = `${formType}-submissions-${new Date().toISOString().slice(0, 10)}.csv`; res.setHeader('Content-Disposition', `attachment; filename="${filename}"`); res.send(csv); } } --- File: apps/api/src/evidence-forms/evidence-forms.module.ts --- import { Module } from '@nestjs/common'; import { AttachmentsModule } from '@/attachments/attachments.module'; import { AuthModule } from '@/auth/auth.module'; import { EvidenceFormsController } from './evidence-forms.controller'; import { EvidenceFormsService } from './evidence-forms.service'; @Module({ imports: [AuthModule, AttachmentsModule], controllers: [EvidenceFormsController], providers: [EvidenceFormsService], exports: [EvidenceFormsService], }) export class EvidenceFormsModule {} --- ## Technical docs: Finding Templates URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/finding-templates
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/finding-template/index.ts](https://github.com/blade47/comp/blob/main/apps/api/src/finding-template/index.ts)
The `finding-template/index.ts` file serves as a "barrel" file, acting as a central entry point for the "Finding Templates" module within the API application. Its primary purpose is to re-export various components related to finding templates, making them easily importable from a single location. This pattern simplifies imports for other parts of the application that need to interact with the finding template functionality. This file aggregates the core building blocks of the Finding Templates feature, including its main module, business logic service, API controller, and data transfer objects (DTOs) for creating and updating finding templates. The `index.ts` file is a common pattern in TypeScript/JavaScript projects, often referred to as a "barrel" file. It consolidates exports from multiple files into a single, convenient module, streamlining imports and improving code organization. ## Module Structure and Exports The `index.ts` file explicitly re-exports five distinct components, each playing a specific role in the Finding Templates feature. These exports collectively define the public interface of the `finding-template` directory. The exported components are: * `finding-template.module`: The main NestJS module for the Finding Templates feature, responsible for organizing controllers, providers, and other modules. * `finding-template.service`: Contains the business logic and data access operations related to finding templates. * `finding-template.controller`: Handles incoming HTTP requests and defines the API endpoints for managing finding templates. * `create-finding-template.dto`: A Data Transfer Object used for validating and structuring data when creating a new finding template. * `update-finding-template.dto`: A Data Transfer Object used for validating and structuring data when updating an existing finding template. ### Exported Components Overview The following diagram illustrates how `index.ts` acts as the central export point for the Finding Templates module's components. Sources: [apps/api/src/finding-template/index.ts:1-5](https://github.com/blade47/comp/blob/main/apps/api/src/finding-template/index.ts#L1-L5) ### Categorization of Exports The exports can be broadly categorized by their role within a typical NestJS application structure. Sources: [apps/api/src/finding-template/index.ts:1-5](https://github.com/blade47/comp/blob/main/apps/api/src/finding-template/index.ts#L1-L5) ## Code Snippet The content of the `index.ts` file is straightforward, consisting solely of re-export statements: ```typescript export * from './finding-template.module'; export * from './finding-template.service'; export * from './finding-template.controller'; export * from './dto/create-finding-template.dto'; export * from './dto/update-finding-template.dto'; ``` Sources: [apps/api/src/finding-template/index.ts:1-5](https://github.com/blade47/comp/blob/main/apps/api/src/finding-template/index.ts#L1-L5) --- ## Technical docs: POST Create a browser automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-createautomation ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get all browser automations for a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-getautomationsfortask ## Parameters ## Responses ## Try It --- ## Technical docs: Findings Workflow URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/findings-workflow
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/findings/index.ts](https://github.com/blade47/comp/blob/main/apps/api/src/findings/index.ts)
The "Findings Workflow" within the API context refers to the set of components and processes involved in managing "findings" — likely security findings, vulnerabilities, or similar reportable items. This workflow is encapsulated within a dedicated module, and its public interface is defined by the `index.ts` file. The `index.ts` file acts as a barrel file, consolidating and re-exporting key elements of the `findings` module. This approach simplifies imports for other parts of the application, allowing them to import all necessary components from a single entry point (`apps/api/src/findings`) rather than individual files. ## Module Structure and Export Mechanism The `apps/api/src/findings/index.ts` file serves as the primary export hub for the `findings` module. It aggregates and re-exports several core components, making them easily accessible throughout the application. This pattern promotes modularity and maintainability by providing a clear, consolidated interface for the module. The exported components collectively define the structure and capabilities of the Findings Workflow, encompassing the module's definition, its business logic, API interaction, and data transfer objects. The `index.ts` file utilizes the "barrel file" pattern. This pattern groups exports from multiple modules into a single, convenient module. It simplifies import statements in consuming files, making the codebase cleaner and easier to navigate. Sources: [apps/api/src/findings/index.ts:1-5](https://github.com/blade47/comp/blob/main/apps/api/src/findings/index.ts#L1-L5) ## Key Components of the Findings Workflow The `index.ts` file exports five primary components that form the backbone of the Findings Workflow. These components are designed to work together to handle the lifecycle of findings within the API. ### FindingsModule The `FindingsModule` is the root module for the findings functionality. In a typical NestJS application, this module would declare providers (like services), controllers, and potentially import other modules required for its operation. It acts as the organizational unit for all finding-related logic and resources. ### FindingsService The `FindingsService` is responsible for encapsulating the business logic related to findings. This typically includes operations such as creating, retrieving, updating, and deleting findings, as well as any complex data manipulations or interactions with a database or external services. ### FindingsController The `FindingsController` handles incoming HTTP requests related to findings. It defines the API endpoints (e.g., `/findings`, `/findings/:id`) and orchestrates the interaction between the HTTP layer and the `FindingsService`. It receives requests, validates input using DTOs, calls the appropriate service methods, and sends back HTTP responses. ### CreateFindingDto The `CreateFindingDto` (Data Transfer Object) defines the structure and validation rules for data submitted when creating a new finding. DTOs ensure that incoming data conforms to expected formats and types, enhancing data integrity and security. ### UpdateFindingDto Similar to `CreateFindingDto`, the `UpdateFindingDto` defines the structure and validation rules for data submitted when updating an existing finding. It specifies which fields can be modified and their respective constraints. Sources: [apps/api/src/findings/index.ts:1-5](https://github.com/blade47/comp/blob/main/apps/api/src/findings/index.ts#L1-L5) --- ## Technical docs: Policy Management URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/policy-management
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/policies/policies.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.controller.ts) - [apps/api/src/policies/policies.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts) - [apps/api/src/policies/schemas/version-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/schemas/version-operations.ts) - [apps/api/src/policies/schemas/policy-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/schemas/policy-operations.ts) - [apps/api/src/policies/dto/ai-suggest-policy.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/ai-suggest-policy.dto.ts) - [apps/api/src/policies/policies.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.module.ts) - [apps/api/src/policies/dto/create-policy.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/create-policy.dto.ts) - [apps/api/src/policies/dto/update-policy.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/update-policy.dto.ts) - [apps/api/src/policies/dto/version.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/version.dto.ts)
Policy Management provides a robust system for organizations to create, manage, version, and publish their internal policies. It encompasses features for policy lifecycle management, including drafting, reviewing, publishing, and archiving policies, along with advanced functionalities like AI-powered content suggestions and PDF generation. The system is designed to handle various policy states and ensures proper authorization and data integrity throughout the policy lifecycle. It integrates with authentication mechanisms and attachment services for secure storage and retrieval of policy-related documents. ## Architecture and Components The Policy Management module is built using NestJS and follows a modular architecture, separating concerns into controllers, services, and DTOs (Data Transfer Objects). ### Module Structure The `PoliciesModule` orchestrates the Policy Management features, importing necessary modules and registering its components. ```typescript // apps/api/src/policies/policies.module.ts @Module({ imports: [AuthModule, AttachmentsModule], controllers: [PoliciesController], providers: [PoliciesService, PolicyPdfRendererService], exports: [PoliciesService], }) export class PoliciesModule {} ``` Sources: [apps/api/src/policies/policies.module.ts:1-11](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.module.ts#L1-L11) ### Policies Controller The `PoliciesController` handles incoming HTTP requests related to policies and policy versions. It defines the API endpoints, applies authentication guards, and delegates business logic to the `PoliciesService`. All endpoints are secured using `HybridAuthGuard` and require an `X-Organization-Id` header for session authentication or an `X-API-Key` for API key authentication. All policy management API endpoints require authentication, either via session cookies with an `X-Organization-Id` header or via an API key. Sources: [apps/api/src/policies/policies.controller.ts:1-25](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.controller.ts#L1-L25) ### Policies Service The `PoliciesService` encapsulates the core business logic for policy operations. It interacts with the database (via Prisma), the `AttachmentsService` for S3 operations (e.g., storing/retrieving policy PDFs), and the `PolicyPdfRendererService` for generating PDF documents. It also contains logic for managing policy versions, handling status transitions, and ensuring data consistency. Key responsibilities include: * CRUD operations for policies. * Managing policy versions (creation, update, deletion, publishing, activation, approval workflows). * Generating and managing PDF representations of policies. * Handling concurrent updates and unique constraint errors during versioning. * Converting policy content (TipTap JSON) to plain text for AI processing. Sources: [apps/api/src/policies/policies.service.ts:1-30](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L1-L30) ## Policy Data Model Policies and their versions are stored with various attributes to manage their lifecycle and content. ### Policy Attributes The `Policy` entity in the database includes the following key fields: | Field Name | Type | Description | | :----------------- | :------------------- | :----------------------------------------------------------------------- | | `id` | `string` | Unique identifier for the policy. | | `name` | `string` | Name of the policy. | | `description` | `string` | Optional description of the policy. | | `status` | `PolicyStatus` | Current status of the policy (`draft`, `published`, `needs_review`). | | `content` | `unknown[]` (JSON) | Main content of the policy (TipTap JSON format). | | `draftContent` | `unknown[]` (JSON) | Draft content, potentially different from `content` if changes are pending. | | `frequency` | `Frequency` | How often the policy should be reviewed. | | `department` | `Departments` | Department the policy applies to. | | `isRequiredToSign` | `boolean` | Indicates if the policy requires employee acknowledgment. | | `signedBy` | `string[]` | List of user IDs who have signed the policy. | | `reviewDate` | `Date` | Next scheduled review date. | | `isArchived` | `boolean` | Flag indicating if the policy is archived. | | `createdAt` | `Date` | Timestamp of creation. | | `updatedAt` | `Date` | Timestamp of last update. | | `lastArchivedAt` | `Date` | Timestamp of last archival. | | `lastPublishedAt` | `Date` | Timestamp of last publication. | | `organizationId` | `string` | ID of the organization this policy belongs to. | | `assigneeId` | `string` | ID of the member assigned to manage the policy. | | `approverId` | `string` | ID of the member designated to approve the policy. | | `policyTemplateId` | `string` | ID of the template used to create the policy. | | `currentVersionId` | `string` | ID of the currently active/published policy version. | | `pendingVersionId` | `string` | ID of the version currently awaiting approval. | | `displayFormat` | `string` | Format for displaying the policy. | | `pdfUrl` | `string` | URL to the policy's PDF in S3. | Sources: [apps/api/src/policies/policies.service.ts:33-72](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L33-L72), [apps/api/src/policies/dto/create-policy.dto.ts:20-107](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/create-policy.dto.ts#L20-L107) ### Policy Version Attributes Each policy can have multiple versions, tracked by the `PolicyVersion` entity: | Field Name | Type | Description | | :-------------- | :----------------- | :----------------------------------------------- | | `id` | `string` | Unique identifier for the version. | | `policyId` | `string` | ID of the parent policy. | | `version` | `number` | Sequential version number (e.g., 1, 2, 3). | | `content` | `unknown[]` (JSON) | Content of this specific version. | | `pdfUrl` | `string` | URL to this version's PDF in S3. | | `publishedById` | `string` | ID of the member who published this version. | | `changelog` | `string` | Description of changes in this version. | Sources: [apps/api/src/policies/policies.service.ts:394-400](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L394-L400) ### Enums Several enums define the possible values for policy attributes: ```typescript // apps/api/src/policies/dto/create-policy.dto.ts export enum PolicyStatus { DRAFT = 'draft', PUBLISHED = 'published', NEEDS_REVIEW = 'needs_review', } export enum Frequency { MONTHLY = 'monthly', QUARTERLY = 'quarterly', YEARLY = 'yearly', } export enum Departments { NONE = 'none', ADMIN = 'admin', GOV = 'gov', HR = 'hr', IT = 'it', ITSM = 'itsm', QMS = 'qms', } ``` Sources: [apps/api/src/policies/dto/create-policy.dto.ts:10-18](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/create-policy.dto.ts#L10-L18), [apps/api/src/policies/dto/create-policy.dto.ts:20-25](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/create-policy.dto.ts#L20-L25), [apps/api/src/policies/dto/create-policy.dto.ts:27-35](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/create-policy.dto.ts#L27-L35) ### DTOs Data Transfer Objects (DTOs) are used for request and response bodies, ensuring data validation and clear API contracts. Sources: [apps/api/src/policies/dto/create-policy.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/create-policy.dto.ts), [apps/api/src/policies/dto/update-policy.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/update-policy.dto.ts), [apps/api/src/policies/dto/version.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/version.dto.ts), [apps/api/src/policies/dto/ai-suggest-policy.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/ai-suggest-policy.dto.ts) ## Key Functionality ### Policy CRUD Operations The system supports standard Create, Read, Update, and Delete (CRUD) operations for policies. * **Create Policy**: Initializes a new policy with its first draft version. * **Get All Policies**: Retrieves a list of all policies for an organization. * **Get Policy by ID**: Fetches details of a specific policy. * **Update Policy**: Modifies policy metadata. Content updates are restricted if the policy is not in `draft` status, requiring a new version to be created. * **Delete Policy**: Permanently removes a policy and all its associated versions and PDFs from S3. Policy content cannot be directly updated if the policy is in `published` or `needs_review` status. To modify content, a new version must be created and then updated. This ensures an auditable history of changes. Sources: [apps/api/src/policies/policies.service.ts:107-169](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L107-L169), [apps/api/src/policies/policies.service.ts:171-236](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L171-L236), [apps/api/src/policies/policies.service.ts:238-297](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L238-L297) ### Policy Versioning A core feature is the ability to manage multiple versions of a policy, providing a complete audit trail and control over policy evolution. * **Get Policy Versions**: Retrieves all versions for a given policy, ordered by version number. * **Get Policy Version by ID**: Fetches a specific version's content and metadata. * **Create Policy Version**: Creates a new draft version, typically based on the current active version or a specified source version. This process includes copying associated PDFs in S3. * **Update Version Content**: Allows modification of the content for non-published, non-pending versions. * **Delete Policy Version**: Removes a specific version, provided it is not the currently active or pending version. * **Publish Policy Version**: Promotes draft content to a new published version, updating the policy's `lastPublishedAt` and `status`. It can optionally set the new version as active. * **Set Active Policy Version**: Designates an existing version as the current active (published) version, updating the policy's main content and status. This also clears any pending approval states. * **Submit Version for Approval**: Marks a specific version as `pending_review` and assigns an approver. This prevents direct editing or publishing until the approval process is complete. Published and pending policy versions are immutable. Their content cannot be directly updated or deleted. To make changes, a new version must be created. Sources: [apps/api/src/policies/policies.service.ts:300-330](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L300-L330), [apps/api/src/policies/policies.service.ts:332-361](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L332-L361), [apps/api/src/policies/policies.service.ts:363-447](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L363-L447), [apps/api/src/policies/policies.service.ts:449-485](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L449-L485), [apps/api/src/policies/policies.service.ts:487-529](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L487-L529), [apps/api/src/policies/policies.service.ts:531-597](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L531-L597), [apps/api/src/policies/policies.service.ts:599-633](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L599-L633), [apps/api/src/policies/policies.service.ts:635-689](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L635-L689) ### AI Policy Suggestion The system includes an AI chat feature to assist users in editing and improving policies. Users can provide instructions, and the AI (powered by OpenAI's `gpt-5.1` model) will suggest changes, explain them, and provide the complete updated policy content in Markdown format. ```mermaid sequenceDiagram actor User participant Client participant PoliciesController participant PoliciesService participant OpenAI as AI Service User->>Client: Enters AI chat for policy Client->>PoliciesController: POST /policies/:id/ai-chat (AISuggestPolicyRequestDto) PoliciesController->>PoliciesService: findById(policyId, orgId) PoliciesService-->>PoliciesController: Policy details PoliciesController->>PoliciesController: convertPolicyContentToText() PoliciesController->>OpenAI: streamText(systemPrompt, messages) OpenAI-->>PoliciesController: Streaming AI response (text/event-stream) PoliciesController-->>Client: Streams AI response Client->>User: Displays AI suggestions ``` Sources: [apps/api/src/policies/policies.controller.ts:316-407](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.controller.ts#L316-L407), [apps/api/src/policies/dto/ai-suggest-policy.dto.ts:1-30](https://github.com/blade47/comp/blob/main/apps/api/src/policies/dto/ai-suggest-policy.dto.ts#L1-L30) ### PDF Generation and Download Policies can be rendered into PDF format, either individually or as a bundle of all published policies for an organization. * **Download All Policies PDF**: Generates a single PDF document containing all currently published and unarchived policies for an organization. This PDF includes organization branding (name, primary color) and page numbering. It fetches existing PDFs from S3 or renders them on-the-fly if not available. * The process involves: 1. Fetching organization details and all relevant policies. 2. Preparing policy PDFs in parallel (fetching from S3 or rendering from content). 3. Merging individual policy PDFs into a single `PDFDocument` sequentially. 4. Adding organizational headers, policy titles, and page numbers to the merged PDF. 5. Uploading the final PDF bundle to S3 and returning a presigned download URL. Sources: [apps/api/src/policies/policies.service.ts:720-888](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L720-L888), [apps/api/src/policies/policies.service.ts:691-700](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L691-L700), [apps/api/src/policies/policies.service.ts:702-718](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.service.ts#L702-L718) ## API Endpoints The following table summarizes the API endpoints exposed by the `PoliciesController`. | Method | Path | Description | Service Method Called | | :----- | :---------------------------------------- | :------------------------------------------- | :------------------------------ | | `GET` | `/policies` | Get all policies | `policiesService.findAll` | | `GET` | `/policies/download-all` | Download all published policies as PDF | `policiesService.downloadAllPoliciesPdf` | | `GET` | `/policies/:id` | Get policy by ID | `policiesService.findById` | | `POST` | `/policies` | Create a new policy | `policiesService.create` | | `PATCH`| `/policies/:id` | Update policy | `policiesService.updateById` | | `DELETE`| `/policies/:id` | Delete policy | `policiesService.deleteById` | | `GET` | `/policies/:id/versions` | Get policy versions | `policiesService.getVersions` | | `GET` | `/policies/:id/versions/:versionId` | Get policy version by ID | `policiesService.getVersionById`| | `POST` | `/policies/:id/versions` | Create policy version | `policiesService.createVersion` | | `PATCH`| `/policies/:id/versions/:versionId` | Update version content | `policiesService.updateVersionContent` | | `DELETE`| `/policies/:id/versions/:versionId` | Delete policy version | `policiesService.deleteVersion` | | `POST` | `/policies/:id/versions/publish` | Publish new policy version | `policiesService.publishVersion`| | `POST` | `/policies/:id/versions/:versionId/activate` | Set active policy version | `policiesService.setActiveVersion` | | `POST` | `/policies/:id/versions/:versionId/submit-for-approval` | Submit version for approval | `policiesService.submitForApproval` | | `POST` | `/policies/:id/ai-chat` | Chat with AI about a policy | `policiesService.findById` | Sources: [apps/api/src/policies/policies.controller.ts:27-360](https://github.com/blade47/comp/blob/main/apps/api/src/policies/policies.controller.ts#L27-L360) --- ## Technical docs: GET Get a browser automation by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-getautomation ## Parameters ## Responses ## Try It --- ## Technical docs: Questionnaires URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/questionnaires
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts) - [apps/api/src/questionnaire/questionnaire.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.controller.ts) - [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts) - [apps/api/src/questionnaire/utils/questionnaire-storage.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts) - [apps/api/src/questionnaire/utils/question-parser.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/question-parser.ts) - [apps/api/src/questionnaire/questionnaire.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.module.ts) - [apps/api/src/questionnaire/dto/auto-answer.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/auto-answer.dto.ts) - [apps/api/src/questionnaire/dto/upload-and-parse.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/upload-and-parse.dto.ts) - [apps/api/src/questionnaire/utils/deduplicate-sources.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/deduplicate-sources.ts) - [apps/api/src/questionnaire/utils/export-generator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/export-generator.ts)
The Questionnaire module provides a comprehensive solution for processing, answering, and managing security questionnaires. It enables users to upload various file formats (e.g., PDF, Excel, CSV, images), automatically extract questions and answers using AI, generate answers based on an organization's knowledge base, and export the results in multiple formats. This module is designed to streamline the often time-consuming process of responding to security questionnaires, leveraging advanced AI models and a robust data storage and retrieval system. It supports both internal users and external trust portal access for automated questionnaire processing. ## Architecture Overview The Questionnaire module is built around a service-controller pattern, utilizing several utility modules for specific tasks such as content extraction, question parsing, storage, and export generation. The core components include: - `QuestionnaireController`: Handles incoming API requests, authentication, and response formatting. - `QuestionnaireService`: Orchestrates the business logic, interacting with AI models, database, and S3 storage. - `ContentExtractor`: Responsible for extracting raw content from various file types and performing initial AI-powered question/answer parsing. - `QuestionnaireStorage`: Manages file uploads to S3 and persistence of questionnaire data (questions, answers, metadata) to the database. - `ExportGenerator`: Creates export files in different formats (XLSX, CSV, PDF). - `DeduplicateSources`: Utility for cleaning up and presenting RAG sources. Sources: [apps/api/src/questionnaire/questionnaire.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.controller.ts#L32-L36) [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L34-L46) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L43-L46) [apps/api/src/questionnaire/utils/questionnaire-storage.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L22-L25) [apps/api/src/questionnaire/utils/export-generator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/export-generator.ts#L17-L20) ## Questionnaire Parsing and Upload The module supports uploading questionnaire files in various formats and extracting their content, then parsing questions and answers using AI. ### File Upload and Content Extraction Users can upload files via dedicated API endpoints. The `QuestionnaireService` delegates the initial file handling to `QuestionnaireStorage` for S3 upload and then to `ContentExtractor` for processing. The `ContentExtractor` module is central to this process. It identifies the file type and employs different strategies: * **Excel (XLSX, XLS):** Uses `AdmZip` and `XLSX` libraries for raw content extraction, including custom logic to handle rich text and shared strings often missed by standard parsers. * **CSV:** Simple text extraction. * **Text:** Direct text extraction. * **PDF and Images (PNG, JPG):** Leverages OpenAI's Vision API (`gpt-4o`) to extract text and structure from visual documents. * **Word Documents (DOCX):** Currently not directly supported for parsing and advises conversion to PDF or image. After raw content extraction, `extractQuestionsWithAI` orchestrates the AI-powered parsing: * **Groq (`gpt-oss-120b`):** Primary and fastest model for parsing questions and answers from textual content, especially for Excel and CSV. It uses a chunking strategy for large files. * **Claude (`claude-3-5-sonnet-latest`):** Fallback for Groq, offering excellent quality with a larger context window. * **OpenAI (`gpt-4o-mini`):** Further fallback for general text parsing. * **OpenAI Vision (`gpt-4o`):** Used specifically for PDF and image files. The AI models are prompted to extract both traditional questions and form-style fields (e.g., "Vendor Name", "Contact Email") along with their corresponding answers. Sources: [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L56-L63) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L43-L121) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L125-L132) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L140-L144) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L160-L200) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L204-L215) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L220-L245) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L250-L275) ### API Endpoints for Parsing and Upload | Method | Endpoint | Description
The `question-parser.ts` file contains utilities for parsing questions and answers from content. While it defines interfaces and helper functions, the primary AI-powered parsing logic for the main questionnaire service flow is handled by `content-extractor.ts` through its `extractQuestionsWithAI` function, which internally utilizes various AI models. Sources: [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L56-L63) [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L104-L110) [apps/api/src/questionnaire/utils/content-extractor.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/content-extractor.ts#L125-L132) | Method | Endpoint | Description
classDiagram class QuestionnaireService { +parseQuestionnaire(dto: ParseQuestionnaireDto): ParsedQuestionnaireResult +autoAnswerAndExport(dto: ExportQuestionnaireDto): QuestionnaireExportResult +uploadAndParse(dto: UploadAndParseDto): { questionnaireId: string; totalQuestions: number } +answerSingleQuestion(dto: AnswerSingleQuestionDto): AnswerQuestionResult +saveAnswer(dto: SaveAnswerDto): { success: boolean; error?: string } +exportById(dto: ExportByIdDto): ExportResult +deleteAnswer(dto: DeleteAnswerDto): { success: boolean; error?: string } +saveGeneratedAnswerPublic(params: { questionnaireId: string; questionIndex: number; answer: string; sources?: AnswerQuestionResult['sources'] }): void -generateAnswersForQuestions(questionsAndAnswers: QuestionnaireAnswer[], organizationId: string): QuestionnaireAnswer[] } class QuestionnaireController { +parseQuestionnaire(dto: ParseQuestionnaireDto): ParsedQuestionnaireResult +answerSingleQuestion(dto: AnswerSingleQuestionDto): any +saveAnswer(dto: SaveAnswerDto): { success: boolean; error?: string } +deleteAnswer(dto: DeleteAnswerDto): { success: boolean; error?: string } +exportById(dto: ExportByIdDto, res: Response): Promise +uploadAndParse(dto: UploadAndParseDto): { questionnaireId: string; totalQuestions: number } +uploadAndParseUpload(file: Express.Multer.File, body: { organizationId: string; source?: 'internal' | 'external' }): any +parseQuestionnaireUpload(file: Express.Multer.File, body: { organizationId: string; format?: 'pdf' | 'csv' | 'xlsx'; source?: 'internal' | 'external' }, res: Response): Promise +parseQuestionnaireUploadByToken(file: Express.Multer.File, token: string, body: { format?: 'pdf' | 'csv' | 'xlsx' }, res: Response): Promise +autoAnswerAndExport(dto: ExportQuestionnaireDto, res: Response): Promise +autoAnswerAndExportUpload(file: Express.Multer.File, body: { organizationId: string; format?: 'pdf' | 'csv' | 'xlsx' }, res: Response): Promise +autoAnswer(dto: AutoAnswerDto, res: Response): Promise } class ParseQuestionnaireDto { +vendorName?: string +fileName?: string +fileType: string +fileData: string } class ExportQuestionnaireDto { +organizationId: string +fileData: string +fileType: string +fileName?: string +vendorName?: string +format: 'pdf' | 'csv' | 'xlsx' +source?: 'internal' | 'external' +exportInAllExtensions?: boolean } class AnswerSingleQuestionDto { +questionnaireId: string +organizationId: string +question: string +questionIndex: number +totalQuestions: number } class AutoAnswerDto { +organizationId: string +questionnaireId?: string +questionsAndAnswers: AutoAnswerQuestionDto[] } class AutoAnswerQuestionDto { +question: string +answer?: string | null +_originalIndex?: number } class SaveAnswerDto { +questionnaireId: string +organizationId: string +questionAnswerId?: string +questionIndex?: number +answer?: string | null +status: 'manual' | 'generated' +sources?: any } class DeleteAnswerDto { +questionnaireId: string +organizationId: string +questionAnswerId: string } class UploadAndParseDto { +organizationId: string +fileName: string +fileType: string +fileData: string +source?: 'internal' | 'external' } class ExportByIdDto { +questionnaireId: string +organizationId: string +format: 'pdf' | 'csv' | 'xlsx' } class QuestionnaireAnswer { +question: string +answer: string | null +sources?: any } class ParsedQuestionnaireResult { +vendorName?: string +fileName?: string +totalQuestions: number +questionsAndAnswers: QuestionnaireAnswer[] } class QuestionnaireExportResult { +fileBuffer: Buffer +mimeType: string +filename: string +questionsAndAnswers: QuestionnaireAnswer[] } QuestionnaireController --|> QuestionnaireService : uses QuestionnaireService ..> ParseQuestionnaireDto QuestionnaireService ..> ExportQuestionnaireDto QuestionnaireService ..> AnswerSingleQuestionDto QuestionnaireService ..> SaveAnswerDto QuestionnaireService ..> DeleteAnswerDto QuestionnaireService ..> UploadAndParseDto QuestionnaireService ..> ExportByIdDto QuestionnaireService ..> QuestionnaireAnswer QuestionnaireService ..> ParsedQuestionnaireResult QuestionnaireService ..> QuestionnaireExportResult AutoAnswerDto o-- AutoAnswerQuestionDto : contains ``` Sources: [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L34-L46) [apps/api/src/questionnaire/questionnaire.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.controller.ts#L32-L36) [apps/api/src/questionnaire/dto/parse-questionnaire.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/parse-questionnaire.dto.ts) [apps/api/src/questionnaire/dto/export-questionnaire.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/export-questionnaire.dto.ts) [apps/api/src/questionnaire/dto/answer-single-question.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/answer-single-question.dto.ts) [apps/api/src/questionnaire/dto/auto-answer.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/auto-answer.dto.ts) [apps/api/src/questionnaire/dto/save-answer.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/save-answer.dto.ts) [apps/api/src/questionnaire/dto/delete-answer.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/delete-answer.dto.ts) [apps/api/src/questionnaire/dto/upload-and-parse.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/upload-and-parse.dto.ts) [apps/api/src/questionnaire/dto/export-by-id.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/dto/export-by-id.dto.ts) ## Automatic Answering The module provides robust capabilities for automatically generating answers to questionnaire questions using a Retrieval Augmented Generation (RAG) approach. ### Answer Generation Process The `QuestionnaireService` orchestrates the automatic answering process: 1. **Sync Organization Embeddings:** Before generating answers, the system ensures that the organization's knowledge base (policies, manual answers, etc.) is synchronized with the vector store. This step is crucial for accurate retrieval. 2. **Batch Search:** For efficiency, questions are batched, and a single call to `findSimilarContentBatch` is made to retrieve relevant context from the vector store for all questions simultaneously. 3. **Answer Generation:** For each question, `generateAnswerFromContent` is called, which uses the retrieved context and an AI model (e.g., `generateAnswerWithRAGBatch` in the service) to formulate an answer. 4. **Save Answer:** Generated answers, along with their sources, are saved to the database. 5. **Update Answered Count:** The total count of answered questions for the questionnaire is updated. ### Streaming Auto-Answer (SSE) The `autoAnswer` endpoint in the `QuestionnaireController` provides a Server-Sent Events (SSE) stream to give real-time feedback on the answer generation progress. ### Establish SSE Connection The controller sets up SSE headers and creates a safe sender function to stream events back to the client. ### Sync Embeddings The `QuestionnaireService` first attempts to synchronize the organization's embeddings to ensure the vector store is up-to-date. Warnings are logged if this fails, but the process continues. ### Filter Unanswered Questions The incoming list of questions is filtered to identify those that still require an answer. ### Batch Context Search A progress event (`type: 'progress'`, `phase: 'searching'`) is sent. The system then performs a batch search (`findSimilarContentBatch`) against the vector store to retrieve relevant content for all unanswered questions. This is a critical optimization to reduce latency. ### Parallel Answer Generation Another progress event (`type: 'progress'`, `phase: 'generating'`) is sent. Answers are then generated in parallel for each question using the pre-fetched content (`generateAnswerFromContent`). ### Stream Individual Answers As each answer is generated, an `answer` event is streamed back to the client, including the question, generated answer, sources, and success status. ### Save Generated Answers Each generated answer is persisted to the database via `saveGeneratedAnswerPublic` in the `QuestionnaireService`. ### Complete Stream Once all questions are processed, a `complete` event is sent, summarizing the total and answered questions. The SSE connection is then closed. Sources: [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L225-L269) [apps/api/src/questionnaire/questionnaire.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.controller.ts#L368-L476) [apps/api/src/vector-store/lib/index.ts](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/index.ts) [apps/api/src/trigger/questionnaire/answer-question-helpers.ts](https://github.com/blade47/comp/blob/main/apps/api/src/trigger/questionnaire/answer-question-helpers.ts) ```mermaid sequenceDiagram actor Client participant Controller as QuestionnaireController participant Service as QuestionnaireService participant VectorStore as Vector Store participant AI as AI Models participant DB as Database participant S3 as S3 Storage Client->>Controller: POST /auto-answer (AutoAnswerDto) Controller->>Controller: setupSSEHeaders() Controller->>Service: syncOrganizationEmbeddings(orgId) Service->>VectorStore: syncOrganizationEmbeddings(orgId) VectorStore-->>Service: Sync Status Service-->>Controller: Controller->>Client: SSE: progress (phase: searching) Controller->>VectorStore: findSimilarContentBatch(questions, orgId) VectorStore-->>Controller: allSimilarContent[] Controller->>Client: SSE: progress (phase: generating) loop For each question Controller->>AI: generateAnswerFromContent(question, similarContent) AI-->>Controller: AnswerResult {answer, sources} Controller->>Service: saveGeneratedAnswerPublic(questionnaireId, questionIndex, answer, sources) Service->>DB: Update questionnaireQuestionAnswer DB-->>Service: Service->>QuestionnaireStorage: updateAnsweredCount(questionnaireId) QuestionnaireStorage->>DB: Update questionnaire.answeredQuestions DB-->>QuestionnaireStorage: QuestionnaireStorage-->>Service: Service-->>Controller: Controller->>Client: SSE: answer {questionIndex, answer, sources} end Controller->>Client: SSE: complete {total, answered, answers} Controller->>Client: Close SSE connection ``` Sources: [apps/api/src/questionnaire/questionnaire.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.controller.ts#L368-L476) [apps/api/src/questionnaire/questionnaire.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/questionnaire.service.ts#L225-L269) [apps/api/src/vector-store/lib/index.ts](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/index.ts) [apps/api/src/trigger/questionnaire/answer-question-helpers.ts](https://github.com/blade47/comp/blob/main/apps/api/src/trigger/questionnaire/answer-question-helpers.ts) [apps/api/src/questionnaire/utils/questionnaire-storage.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L22-L36) ### DTOs for Auto-Answering | DTO Class | Description ``` --- ## Technical docs: PATCH Update a browser automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-updateautomation ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: DELETE Delete a browser automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-deleteautomation ## Parameters ## Responses ## Try It --- ## Technical docs: Knowledge Base URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/knowledge-base
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/knowledge-base/knowledge-base.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts) - [apps/api/src/knowledge-base/knowledge-base.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts) - [apps/api/src/knowledge-base/utils/s3-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts) - [apps/api/src/knowledge-base/utils/constants.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/constants.ts) - [apps/api/src/knowledge-base/knowledge-base.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.module.ts) - [apps/api/src/knowledge-base/dto/process-documents.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/dto/process-documents.dto.ts) - [apps/api/src/knowledge-base/dto/upload-document.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/dto/upload-document.dto.ts)
The Knowledge Base module provides a robust system for managing organizational documents and manual answers, integrating file storage, database persistence, and asynchronous processing capabilities. It allows users to upload, list, retrieve, and delete documents, as well as manage manual answers, with support for vector database integration for intelligent search and retrieval. The module leverages Amazon S3 for secure file storage and Trigger.dev for orchestrating background processing tasks. This module is designed to handle various aspects of knowledge management, from initial document ingestion to their eventual processing and deletion, ensuring data consistency across storage, database, and vector store components. ## Architecture Overview The Knowledge Base module follows a standard NestJS architecture, with a Controller handling incoming API requests and a Service encapsulating the business logic. It interacts with external services such as S3 for file storage and Trigger.dev for asynchronous task orchestration, and persists metadata in a database. Sources: [apps/api/src/knowledge-base/knowledge-base.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.module.ts), [apps/api/src/knowledge-base/knowledge-base.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts), [apps/api/src/knowledge-base/knowledge-base.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts) ## API Endpoints The `KnowledgeBaseController` exposes a set of RESTful API endpoints for interacting with knowledge base documents and manual answers. | Method | Endpoint | Description | DTO / Parameters

The Knowledge Base module is a core component that manages the storage, processing, and retrieval of documents and manual answers for an organization. It integrates with Snbsp;S3 for file storage and Trigger.dev for asynchronous processing, providing a robust system for knowledge management.

Sources: [apps/api/src/knowledge-base/knowledge-base.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.module.ts), [apps/api/src/knowledge-base/knowledge-base.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts)

## Architecture Overview The Knowledge Base module follows a standard NestJS architecture, with a Controller handling incoming API requests and a Service encapsulating the business logic. It interacts with external services such as S3 for file storage and Trigger.dev for asynchronous task orchestration, and persists metadata in a database.

Sources: [apps/api/src/knowledge-base/knowledge-base.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.module.ts), [apps/api/src/knowledge-base/knowledge-base.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts), [apps/api/src/knowledge-base/knowledge-base.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts) ## API Endpoints The `KnowledgeBaseController` exposes a set of RESTful API endpoints for interacting with knowledge base documents and manual answers. | Method | Endpoint | Description | DTO / Parameters Sources: [apps/api/src/knowledge-base/knowledge-base.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts), [apps/api/src/knowledge-base/knowledge-base.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts), [apps/api/src/knowledge-base/utils/s3-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts) ### Listing Documents The `listDocuments` endpoint retrieves all knowledge base documents associated with a given `organizationId`. It fetches document metadata from the database, including `id`, `name`, `description`, `s3Key`, `fileType`, `fileSize`, `processingStatus`, `createdAt`, and `updatedAt`. ```typescript async listDocuments(organizationId: string) { return db.knowledgeBaseDocument.findMany({ where: { organizationId }, select: { id: true, name: true, description: true, s3Key: true, fileType: true, fileSize: true, processingStatus: true, createdAt: true, updatedAt: true, }, orderBy: { createdAt: 'desc' }, }); } ``` Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:18-32](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L18-L32), [apps/api/src/knowledge-base/knowledge-base.controller.ts:40-59](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L40-L59) ### Getting Signed URLs The module provides functionality to generate time-limited, signed URLs for both downloading and viewing documents directly in a browser. #### Download URL The `getDownloadUrl` method generates a signed URL that forces the browser to download the file. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:51-64](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L51-L64), [apps/api/src/knowledge-base/knowledge-base.controller.ts:76-92](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L76-L92) #### View URL The `getViewUrl` method generates a signed URL intended for inline viewing in the browser. It also indicates whether the file type is generally viewable in a browser based on predefined MIME types. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:66-82](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L66-L82), [apps/api/src/knowledge-base/knowledge-base.controller.ts:94-115](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L94-L115), [apps/api/src/knowledge-base/utils/constants.ts:30-32](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/constants.ts#L30-L32) ### Deleting Documents Deleting a document involves multiple steps to ensure consistency across S3, the database, and any associated vector store embeddings. This process is partially asynchronous to avoid blocking the API response. ```mermaid sequenceDiagram actor Client participant Controller as KBController participant Service as KBService participant DB as Database participant S3 as S3 Storage participant Trigger as Trigger.dev Client->>Controller: POST /documents/:id/delete { orgId } Controller->>Service: deleteDocument(dto) Service->>DB: findUnique(documentId, orgId) DB-->>Service: document Service->>Trigger: triggerVectorDeletion(documentId, orgId) Trigger-->>Service: runId (async) Service->>Trigger: createRunReadToken(runId) Trigger-->>Service: publicAccessToken Service->>S3: deleteFromS3(s3Key) S3-->>Service: s3Deleted (boolean) Service->>DB: delete(documentId) DB-->>Service: deleteResult Service-->>Controller: { success, vectorDeletionRunId, publicAccessToken } Controller-->>Client: 200 OK ``` Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:84-122](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L84-L122), [apps/api/src/knowledge-base/knowledge-base.controller.ts:117-142](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L117-L142), [apps/api/src/knowledge-base/utils/s3-operations.ts:130-143](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts#L130-L143) ### Processing Documents The `processDocuments` endpoint initiates the asynchronous processing of one or more knowledge base documents. This typically involves extracting content and generating vector embeddings for search. The service intelligently dispatches either a single document processing task or an orchestrator task for multiple documents. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:124-154](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L124-L154), [apps/api/src/knowledge-base/knowledge-base.controller.ts:144-162](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L144-L162), [apps/api/src/knowledge-base/dto/process-documents.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/dto/process-documents.dto.ts) Document processing tasks are handled asynchronously by Trigger.dev. The API immediately returns a `runId` and a `publicAccessToken` which can be used to monitor the status of the background job. ## Manual Answer Management The module also supports the management of "manual answers," which are likely pre-defined responses or knowledge entries. ### Deleting a Single Manual Answer The `deleteManualAnswer` method removes a specific manual answer from the system. It triggers an asynchronous task to delete associated vector embeddings before removing the record from the main database. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:175-199](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L175-L199), [apps/api/src/knowledge-base/knowledge-base.controller.ts:182-196](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L182-L196) ### Deleting All Manual Answers The `deleteAllManualAnswers` method allows for the bulk deletion of all manual answers belonging to a specific organization. It first identifies all relevant manual answer IDs and then triggers an orchestrator task for batch vector deletion before removing all records from the database. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:201-229](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L201-L229), [apps/api/src/knowledge-base/knowledge-base.controller.ts:198-207](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L198-L207) ## S3 Operations The `s3-operations.ts` utility file provides core functions for interacting with Amazon S3, specifically for the knowledge base bucket. ### Key Functions | Function Name | Description ```mermaid erDiagram knowledgeBaseDocument { string id string name string description string s3Key string fileType number fileSize string processingStatus string createdAt string updatedAt string organizationId } securityQuestionnaireManualAnswer { string id string organizationId } organization ||--o{ knowledgeBaseDocument : "manages" organization ||--o{ securityQuestionnaireManualAnswer : "manages" ``` Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:18-32](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L18-L32), [apps/api/src/knowledge-base/knowledge-base.service.ts:175-181](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L175-L181) ## Constants and Utilities The `constants.ts` file defines various configuration parameters and helper functions used across the Knowledge Base module. | Constant/Function Name | Description Sources: [apps/api/src/knowledge-base/knowledge-base.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts), [apps/api/src/knowledge-base/knowledge-base.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts), [apps/api/src/knowledge-base/utils/s3-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts) ### Listing Documents The `listDocuments` endpoint retrieves all knowledge base documents associated with a given `organizationId`. It fetches document metadata from the database, including `id`, `name`, `description`, `s3Key`, `fileType`, `fileSize`, `processingStatus`, `createdAt`, and `updatedAt`. ```typescript async listDocuments(organizationId: string) { return db.knowledgeBaseDocument.findMany({ where: { organizationId }, select: { id: true, name: true, description: true, s3Key: true, fileType: true, fileSize: true, processingStatus: true, createdAt: true, updatedAt: true, }, orderBy: { createdAt: 'desc' }, }); } ``` Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:18-32](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L18-L32), [apps/api/src/knowledge-base/knowledge-base.controller.ts:40-59](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L40-L59) ### Getting Signed URLs The module provides functionality to generate time-limited, signed URLs for both downloading and viewing documents directly in a browser. #### Download URL The `getDownloadUrl` method generates a signed URL that forces the browser to download the file. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:51-64](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L51-L64), [apps/api/src/knowledge-base/knowledge-base.controller.ts:76-92](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L76-L92) #### View URL The `getViewUrl` method generates a signed URL intended for inline viewing in the browser. It also indicates whether the file type is generally viewable in a browser based on predefined MIME types. Sources: [apps/api/src/knowledge-base/knowledge-base.service.ts:66-82](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.service.ts#L66-L82), [apps/api/src/knowledge-base/knowledge-base.controller.ts:94-115](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/knowledge-base.controller.ts#L94-L115), [apps/api/src/knowledge-base/utils/constants.ts:30-32](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/constants.ts#L30-L32) ### Deleting Documents Deleting a document involves multiple ``` --- ## Technical docs: Risk Management URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/risk-management
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/risks/schemas/risk-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/schemas/risk-operations.ts) - [apps/api/src/risks/dto/create-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/create-risk.dto.ts) - [apps/api/src/risks/risks.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.controller.ts) - [apps/api/src/risks/risks.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.service.ts) - [apps/api/src/risks/dto/update-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/update-risk.dto.ts) - [apps/api/src/risks/risks.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.module.ts)
The Risk Management module provides a robust API for organizations to manage their identified risks. It enables users to create, retrieve, update, and delete risk records, associating them with specific organizations and assignees. The module is designed with a clear separation of concerns, utilizing a controller for API exposure, a service for business logic, and Data Transfer Objects (DTOs) for data validation and schema definition. This system supports both API key and session-based authentication, ensuring secure access to risk data for the authenticated organization. It integrates with a database to persist risk information, including details like title, description, category, status, likelihood, impact, and treatment strategies. ## Architecture Overview The Risk Management module is built using the NestJS framework, following a modular architecture. It consists of a `RisksModule` that encapsulates the `RisksController` and `RisksService`, along with Data Transfer Objects (`CreateRiskDto`, `UpdateRiskDto`) for defining the structure of incoming and outgoing data. The `RisksModule` imports the `AuthModule` to leverage authentication mechanisms and provides the `RisksService` to handle all business logic related to risks. The `RisksController` exposes the API endpoints, delegating complex operations to the `RisksService`. Sources: [apps/api/src/risks/risks.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.module.ts#L1-L10), [apps/api/src/risks/risks.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.controller.ts#L1-L60), [apps/api/src/risks/risks.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.service.ts#L1-L10), [apps/api/src/risks/dto/create-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/create-risk.dto.ts#L1-L89), [apps/api/src/risks/dto/update-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/update-risk.dto.ts#L1-L4) ## API Endpoints The `RisksController` exposes a RESTful API for managing risks. All endpoints are protected by the `HybridAuthGuard` and require either an API key or session authentication with an `X-Organization-Id` header. Swagger documentation is integrated, providing detailed operation summaries, descriptions, parameters, and response schemas. All API endpoints require authentication. This can be achieved via an `X-API-Key` header for API key authentication or a combination of session cookies and an `X-Organization-Id` header for session authentication. ### Available Endpoints | Method | Path | Operation Summary | Description Risk Management is a crucial module within the system, designed to help organizations identify, assess, and manage risks effectively. It provides a comprehensive set of functionalities to track risks, assign responsibilities, monitor their status, and define treatment strategies. The module supports various risk attributes, including categories, departments, likelihood, impact, and residual risk, facilitating a structured approach to risk management. Sources: [apps/api/src/risks/schemas/risk-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/schemas/risk-operations.ts#L1-L30), [apps/api/src/risks/dto/create-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/create-risk.dto.ts#L1-L89) ### API Request Flow Example: Creating a Risk The following sequence diagram illustrates the typical flow for creating a new risk through the API. ```mermaid sequenceDiagram actor Client participant Controller as RisksController participant Service as RisksService participant DB as Database Client->>Controller: POST /risks (CreateRiskDto) activate Controller Controller->>Service: create(organizationId, createRiskDto) activate Service Service->>DB: db.risk.create(data: createRiskDto + organizationId) activate DB DB-->>Service: New Risk Record (id, title, etc.) deactivate DB Service-->>Controller: Created Risk Object deactivate Service Controller-->>Client: 201 Created (Risk Object + Auth Context) deactivate Controller ``` Sources: [apps/api/src/risks/risks.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.controller.ts#L80-L99), [apps/api/src/risks/risks.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.service.ts#L66-L82) ## Data Transfer Objects (DTOs) Data Transfer Objects (DTOs) are used to define the structure and validation rules for data exchanged between the client and the API. ### `CreateRiskDto` This DTO defines the required and optional fields for creating a new risk. It includes validation decorators (`@IsString`, `@IsNotEmpty`, `@IsOptional`, `@IsEnum`) to ensure data integrity. | Field | Type | Required | Description | Example | | :--------------------------- | :--------------- | :------- | :------------------------------------------------------------------------ | :---------------------------------------------------------------------- | | `title` | `string` | Yes | Risk title | `Data breach vulnerability in user authentication system` | | `description` | `string` | Yes | Detailed description of the risk | `Weak password requirements could lead to unauthorized access` | | `category` | `RiskCategory` | Yes | Risk category (e.g., `technology`, `financial`) | `RiskCategory.technology` | | `department` | `Departments?` | No | Department responsible for the risk (e.g., `it`, `hr`) | `Departments.it` | | `status` | `RiskStatus?` | No | Current status of the risk (e.g., `open`, `closed`) | `RiskStatus.open` | | `likelihood` | `Likelihood?` | No | Likelihood of the risk occurring (e.g., `possible`, `unlikely`) | `Likelihood.possible` | | `impact` | `Impact?` | No | Impact if the risk materializes (e.g., `major`, `minor`) | `Impact.major` | | `residualLikelihood` | `Likelihood?` | No | Residual likelihood after treatment | `Likelihood.unlikely` | | `residualImpact` | `Impact?` | No | Residual impact after treatment | `Impact.minor` | | `treatmentStrategyDescription` | `string?` | No | Description of the treatment strategy | `Implement multi-factor authentication` | | `treatmentStrategy` | `RiskTreatmentType?` | No | Risk treatment strategy (e.g., `mitigate`, `accept`) | `RiskTreatmentType.mitigate` | | `assigneeId` | `string?` | No | ID of the user assigned to this risk (e.g., `mem_abc123def456`) | `mem_abc123def456` | Sources: [apps/api/src/risks/dto/create-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/create-risk.dto.ts#L1-L89) ### `UpdateRiskDto` The `UpdateRiskDto` extends `PartialType(CreateRiskDto)`. This means all fields inherited from `CreateRiskDto` become optional, allowing for partial updates of a risk record. ```typescript import { PartialType } from '@nestjs/swagger'; import { CreateRiskDto } from './create-risk.dto'; export class UpdateRiskDto extends PartialType(CreateRiskDto) {} ``` Sources: [apps/api/src/risks/dto/update-risk.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/dto/update-risk.dto.ts#L1-L4) ## Service Layer Logic (`RisksService`) The `RisksService` encapsulates the core business logic for managing risks. It interacts directly with the database (`db.risk`) to perform CRUD operations and includes error handling and logging. ### Key Methods * `findAllByOrganization(organizationId: string)`: Retrieves all risks associated with a given organization ID, ordered by creation date. It includes assignee user details. * `findById(id: string, organizationId: string)`: Fetches a specific risk by its ID and organization ID. Throws `NotFoundException` if the risk does not exist or does not belong to the specified organization. * `create(organizationId: string, createRiskDto: CreateRiskDto)`: Creates a new risk record in the database, associating it with the provided organization ID. * `updateById(id: string, organizationId: string, updateRiskDto: UpdateRiskDto)`: Updates an existing risk. It first verifies the risk's existence and ownership using `findById` before performing the update. * `deleteById(id: string, organizationId: string)`: Deletes a risk. Similar to `updateById`, it first validates the risk's existence and ownership. ### Update/Delete Risk Flow The `updateById` and `deleteById` methods in `RisksService` follow a common pattern of first verifying the existence and ownership of a risk before proceeding with the modification or deletion. Sources: [apps/api/src/risks/risks.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/risks.service.ts#L12-L130) --- ## Technical docs: POST Start automation with live view URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-startautomationlive ## Parameters ## Responses ## Try It --- ## Technical docs: POST Execute automation on existing session URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-executeautomationonsession ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: SOA Workflow URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/soa-workflow
Relevant source files The following files were used as context for generating this wiki page: - No specific source files were provided for this topic. The content is generated based solely on the provided topic description: "Explains Statement of Applicability features including setup, answer generation, parsing, approval, submission, storage, and ISO configuration transforms."
This page details the Statement of Applicability (SOA) Workflow, outlining the key stages involved in managing an organization's compliance posture against various standards, particularly focusing on ISO configurations. The workflow encompasses the entire lifecycle from initial setup and data generation to final approval, submission, and secure storage of SOA artifacts. It also highlights the critical role of parsing and transformation mechanisms to ensure data integrity and compatibility with ISO standards. The SOA Workflow is designed to streamline the process of assessing, documenting, and maintaining an organization's applicability to security controls. By breaking down the process into distinct, manageable phases, it ensures accuracy, facilitates collaboration, and provides a clear audit trail for compliance activities. ## Overview of the SOA Workflow The SOA Workflow orchestrates a series of interconnected processes to manage the Statement of Applicability. It begins with foundational setup, proceeds through automated or semi-automated data generation and parsing, moves into human-centric approval, and concludes with formal submission and archival. A key aspect is the integration of ISO configuration transforms, ensuring that the generated SOA aligns with relevant international standards. The following diagram illustrates the high-level flow of the SOA Workflow: Sources: [Topic Description] ## Setup The setup phase involves configuring the environment and parameters necessary for the SOA workflow to function correctly. This typically includes defining the scope of the Statement of Applicability, selecting relevant control frameworks (e.g., ISO 27001, NIST), and configuring user roles and permissions for various stages of the workflow. Initial data sources, such as existing asset inventories or policy documents, may also be integrated during this phase. Proper initial setup is crucial for the accuracy and efficiency of the entire SOA workflow. Misconfigurations at this stage can lead to incorrect applicability assessments or compliance gaps. ### Key Setup Elements * **Control Framework Selection:** Identifying the specific standards (e.g., ISO 27001:2022) against which the SOA will be generated. * **Organizational Scope:** Defining the boundaries of the assessment, including departments, systems, and data in scope. * **User & Role Management:** Assigning responsibilities for answer generation, review, and approval. * **Integration Points:** Configuring connections to other systems that provide input data or consume SOA outputs. Sources: [Topic Description] ## Answer Generation Answer generation is the process where responses to control questions or applicability statements are collected. This can involve automated data collection from integrated systems, manual input from subject matter experts, or a combination of both. The goal is to gather comprehensive and accurate information regarding the implementation status and applicability of each control within the defined scope. ### Methods of Answer Generation * **Automated Data Collection:** Pulling data from configuration management databases (CMDBs), security tools, or other IT systems to automatically answer control questions. * **Questionnaires & Surveys:** Distributing structured questionnaires to relevant stakeholders for manual input. * **Interview & Workshops:** Facilitating discussions with experts to gather qualitative data and insights. Sources: [Topic Description] ## Parsing Once answers are generated, the parsing stage involves processing and interpreting the collected data. This ensures that the information is in a consistent, structured format suitable for further analysis, reporting, and transformation. Parsing may include data validation, normalization, and extraction of key attributes from various input formats. ### Data Validation Check generated answers against predefined rules, data types, and constraints to ensure accuracy and completeness. This might involve checking for mandatory fields, valid date formats, or acceptable value ranges. ### Data Normalization Transforming data into a standardized format. For example, converting different representations of "yes/no" (e.g., "Y", "True", "1") into a single, consistent value. ### Attribute Extraction Identifying and extracting specific pieces of information from free-text fields or complex data structures for structured storage and analysis. Sources: [Topic Description] ## Approval The approval phase is a critical human-centric step where generated and parsed SOA data is reviewed by designated stakeholders. This typically involves compliance officers, risk managers, and senior management. Approvers verify the accuracy, completeness, and appropriateness of the applicability statements and control implementation details before the SOA can be formally submitted. ### Approval Process The approval process often follows a multi-level hierarchy, ensuring that all relevant parties have signed off on the Statement of Applicability. ```mermaid sequenceDiagram actor Stakeholder participant System as SOA System participant Reviewer as Compliance Officer participant Approver as Senior Management Stakeholder->>System: Submit Generated Answers System->>Reviewer: Notify for Review (Parsed SOA Data) Reviewer->>System: Review SOA Data alt Reviewer Approves Reviewer->>System: Approve Review System->>Approver: Notify for Final Approval Approver->>System: Review SOA Data alt Approver Approves Approver->>System: Final Approval System-->>Stakeholder: SOA Approved else Approver Rejects Approver->>System: Request Revisions (with feedback) System-->>Reviewer: Notify for Revisions Reviewer->>Stakeholder: Request Revisions end else Reviewer Rejects Reviewer->>System: Request Revisions (with feedback) System-->>Stakeholder: Notify for Revisions end ``` Sources: [Topic Description] ## Submission Upon successful approval, the SOA is formally submitted. This typically means making the final, approved document available to relevant internal and external parties. For internal purposes, it might be published to a central compliance repository. For external audits or certifications, it would be provided to auditors or certification bodies. ### Submission Channels * **Internal Compliance Portal:** Publishing the SOA for internal stakeholders. * **Auditor Portals:** Uploading the SOA to secure platforms provided by external auditors. * **Certification Bodies:** Submitting the SOA as part of an ISO certification process. Sources: [Topic Description] ## Storage The storage phase involves securely archiving the approved and submitted SOA documents and associated data. This ensures that historical records are maintained for audit purposes, future reference, and continuous improvement. Storage solutions must comply with data retention policies and security requirements. ### Storage Considerations | Aspect | Description | | :-------------- | :-------------------------------------------------------------------------- | | **Security** | Encrypted storage, access controls, and regular backups. | | **Retention** | Adherence to legal and regulatory data retention periods. | | **Accessibility** | Easy retrieval for authorized personnel during audits or reviews. | | **Integrity** | Mechanisms to ensure the data remains unaltered and authentic over time. | | **Versioning** | Ability to track changes and retrieve previous versions of the SOA. | Sources: [Topic Description] ## ISO Configuration Transforms A critical feature of the SOA Workflow is the ability to perform ISO configuration transforms. This involves converting or mapping the generated and approved SOA data into a format that aligns precisely with specific ISO standards (e.g., ISO 27001 Annex A controls). These transforms ensure that the SOA is not just a generic statement but a tailored document that directly addresses the requirements of the chosen ISO framework. ### Purpose of Transforms * **Standard Alignment:** Ensuring the SOA directly maps to ISO control objectives and controls. * **Reporting:** Generating reports that are compliant with ISO documentation requirements. * **Audit Readiness:** Providing auditors with a clear, ISO-specific view of the organization's applicability. * **Interoperability:** Facilitating the exchange of SOA data with other ISO-compliant systems or tools. An organization might have internal controls like "Access Control Policy" and "User Account Management Procedure." An ISO configuration transform would map these to specific ISO 27001:2022 Annex A controls, such as A.5.1 (Policies for information security), A.5.15 (Access control), and A.5.16 (Identity management). This ensures that the SOA explicitly states how the organization meets each ISO requirement. Sources: [Topic Description] --- ## Technical docs: People Directory URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/people-directory
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/people/people.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.service.ts) - [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts) - [apps/api/src/people/utils/member-queries.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/utils/member-queries.ts) - [apps/api/src/people/utils/member-validator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/utils/member-validator.ts) - [apps/api/src/people/dto/create-people.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/dto/create-people.dto.ts) - [apps/api/src/people/dto/bulk-create-people.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/dto/bulk-create-people.dto.ts) - [apps/api/src/people/people.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.module.ts)
The People Directory module provides a robust API for managing members within an organization. It allows for the creation, retrieval, updating, and deletion of individual members, as well as bulk creation operations. This module integrates user management with device management capabilities, enabling the association of members with devices and the ability to unlink or remove specific hosts. Designed as a NestJS module, it follows a clear separation of concerns, with a controller handling API requests, a service encapsulating business logic, and dedicated utility classes for database queries and data validation. This structure ensures maintainability, scalability, and adherence to best practices for API development. ## Architecture Overview The People Directory module is structured around the standard NestJS pattern of Controllers, Services, and Modules, augmented by specialized utility classes for database interactions and validation. This layered architecture ensures that business logic is decoupled from HTTP concerns and data access. - **`PeopleController`**: Handles incoming HTTP requests, routes them to the appropriate service methods, and formats responses. - **`PeopleService`**: Contains the core business logic for member management, orchestrating interactions with validators, query helpers, and external services like `FleetService`. - **`MemberValidator`**: Provides methods to validate the existence of organizations, users, and member relationships, ensuring data integrity before operations proceed. - **`MemberQueries`**: Encapsulates all direct database interactions related to members, using Prisma ORM. - **`FleetService`**: An external dependency used by `PeopleService` to manage devices (hosts) associated with members in FleetDM. The following diagram illustrates the high-level request flow within the People Directory module: Sources: [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts#L36-L40) [apps/api/src/people/people.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.service.ts#L10-L15) [apps/api/src/people/utils/member-validator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/utils/member-validator.ts#L3-L4) [apps/api/src/people/utils/member-queries.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/utils/member-queries.ts#L3-L4) ## API Endpoints The `PeopleController` exposes a comprehensive set of RESTful API endpoints for managing organizational members. All endpoints are protected by `HybridAuthGuard` and require an `X-Organization-Id` header (or API key authentication). All endpoints are secured using `HybridAuthGuard`, which supports both session-based and API key authentication. The `X-Organization-Id` header is crucial for scoping operations to a specific organization. The `DELETE /:id/host/:hostId` endpoint further enforces role-based access control, requiring the authenticated user to have an 'owner' role. Sources: [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts#L36-L40), [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts#L220) | Method | Path | Description | Request Body (DTO) | Response DTO | Required Roles | | :----- | :------------------- | :--------------------------------------------- | :------------------------- | :------------------------- | :------------- | | `GET` | `/people` | Retrieve all members in an organization | N/A | `PeopleResponseDto[]` | N/A | | `POST` | `/people` | Create a new member | `CreatePeopleDto` | `PeopleResponseDto` | N/A | | `POST` | `/people/bulk` | Bulk create multiple members | `BulkCreatePeopleDto` | `{ created: [], errors: [], summary: {} }` | N/A | | `GET` | `/people/:id` | Retrieve a member by ID | N/A | `PeopleResponseDto` | N/A | | `PATCH`| `/people/:id` | Update an existing member | `UpdatePeopleDto` | `PeopleResponseDto` | N/A | | `DELETE`| `/people/:id/host/:hostId` | Remove a specific host from a member's devices | N/A | `{ success: true }` | `owner` | | `DELETE`| `/people/:id` | Delete a member | N/A | `{ success: true, deletedMember: {} }` | N/A | | `PATCH`| `/people/:id/unlink-device` | Unlink all devices from a member | N/A | `PeopleResponseDto` | N/A | Sources: [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts#L43-L280) ## Core Services and Logic ### PeopleService The `PeopleService` is the central component for all business logic related to member management. It orchestrates operations by calling `MemberValidator` for data integrity checks, `MemberQueries` for database interactions, and `FleetService` for device management. Key methods include: * `findAllByOrganization(organizationId: string)`: Retrieves all active members for a given organization. * `findById(memberId: string, organizationId: string)`: Fetches a single member by their ID within an organization. * `create(organizationId: string, createData: CreatePeopleDto)`: Creates a new member after validating the organization, user, and ensuring the user is not already a member. * `bulkCreate(organizationId: string, bulkCreateData: BulkCreatePeopleDto)`: Handles the creation of multiple members, performing individual validations and then a bulk database insert for valid entries. It returns a summary of successful and failed creations. * `updateById(memberId: string, organizationId: string, updateData: UpdatePeopleDto)`: Updates an existing member's details. Includes validation for `userId` changes to prevent duplicate memberships. * `deleteById(memberId: string, organizationId: string)`: Deactivates or removes a member from an organization. * `unlinkDevice(memberId: string, organizationId: string)`: Disassociates all devices from a member. This involves removing hosts from FleetDM based on the member's `fleetDmLabelId` and deleting associated `Device` records from the local database. * `removeHostById(memberId: string, organizationId: string, hostId: number)`: Removes a specific host from a member's associated devices in FleetDM. Sources: [apps/api/src/people/people.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.service.ts#L17-L255) ### MemberValidator The `MemberValidator` class provides static methods to ensure the validity of entities and relationships before performing operations. This prevents common data integrity issues and provides clear error messages. * `validateOrganization(organizationId: string)`: Checks if an organization with the given ID exists. Throws `NotFoundException` if not found. * `validateUser(userId: string)`: Checks if a user with the given ID exists. Throws `NotFoundException` if not found. * `validateMemberExists(memberId: string, organizationId: string)`: Confirms that a member exists and is active within the specified organization. Throws `NotFoundException` if not found. * `validateUserNotMember(userId: string, organizationId: string, excludeMemberId?: string)`: Ensures that a user is not already an active member of the organization. An optional `excludeMemberId` allows this check to be used during updates where the member's own ID should be ignored. Throws `BadRequestException` if the user is already a member. Sources: [apps/api/src/people/utils/member-validator.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/utils/member-validator.ts#L3-L59) ### MemberQueries The `MemberQueries` class acts as a data access layer, abstracting direct Prisma ORM calls for member-related operations. It defines a standard `MEMBER_SELECT` object to ensure consistent data retrieval across different queries. * `MEMBER_SELECT`: A constant object defining the fields to be selected when querying member data, including nested user information. * `findAllByOrganization(organizationId: string)`: Retrieves all members for an organization, ordered by creation date. * `findByIdInOrganization(memberId: string, organizationId: string)`: Finds a specific member by ID within an organization. * `createMember(organizationId: string, createData: CreatePeopleDto)`: Inserts a new member record into the database. * `updateMember(memberId: string, updateData: UpdatePeopleDto)`: Updates an existing member record. Handles `fleetDmLabelId` specifically to allow setting it to `null`. * `findMemberForDeletion(memberId: string, organizationId: string)`: Retrieves minimal member and user information specifically for the deletion process. * `deleteMember(memberId: string)`: Deletes a member record from the database. * `unlinkDevice(memberId: string)`: Updates a member's record by setting `fleetDmLabelId` to `null`. * `bulkCreateMembers(organizationId: string, memberData: CreatePeopleDto[])`: Performs a `createMany` operation for multiple members, then fetches the newly created members for the response. `skipDuplicates` is used to prevent errors if a user is already a member. Sources: [apps/api/src/people/utils/member-queries.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/utils/member-queries.ts#L7-L135) ## Data Transfer Objects (DTOs) The module uses DTOs for defining the structure of data exchanged between the client and the API, ensuring strong typing and validation. Sources: [apps/api/src/people/dto/create-people.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/dto/create-people.dto.ts#L7-L49) [apps/api/src/people/dto/bulk-create-people.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/dto/bulk-create-people.dto.ts#L7-L35) ### `CreatePeopleDto` This DTO defines the data required to create a single new member. ```typescript export class CreatePeopleDto { userId: string; role: string; department?: Departments; isActive?: boolean; fleetDmLabelId?: number; jobTitle?: string; } ``` Sources: [apps/api/src/people/dto/create-people.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/dto/create-people.dto.ts#L7-L49) ### `BulkCreatePeopleDto` This DTO is used for the bulk creation endpoint and contains an array of `CreatePeopleDto` objects. It includes validation for array size. ```typescript export class BulkCreatePeopleDto { @IsArray() @ArrayMinSize(1) @ArrayMaxSize(1000) @ValidateNested({ each: true }) @Type(() => CreatePeopleDto) members: CreatePeopleDto[]; } ``` Sources: [apps/api/src/people/dto/bulk-create-people.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/dto/bulk-create-people.dto.ts#L7-L35) ## Request Flows ### Create Member Flow This sequence diagram illustrates the process of creating a new member through the API. ```mermaid sequenceDiagram participant Client participant Controller as PeopleController participant Service as PeopleService participant Validator as MemberValidator participant Queries as MemberQueries participant DB as Database Client->>Controller: POST /people (CreatePeopleDto) Controller->>Service: create(orgId, createData) Service->>Validator: validateOrganization(orgId) Validator->>DB: Query Organization DB-->>Validator: Organization exists Validator-->>Service: Success Service->>Validator: validateUser(userId) Validator->>DB: Query User DB-->>Validator: User exists Validator-->>Service: Success Service->>Validator: validateUserNotMember(userId, orgId) Validator->>DB: Query Member by userId & orgId DB-->>Validator: No existing member Validator-->>Service: Success Service->>Queries: createMember(orgId, createData) Queries->>DB: Insert new Member record DB-->>Queries: New Member record Queries-->>Service: PeopleResponseDto Service-->>Controller: PeopleResponseDto Controller-->>Client: 201 Created (PeopleResponseDto) ``` Sources: [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts#L90-L107), [apps/api/src/people/people.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.service.ts#L78-L106) ### Unlink Device Flow This sequence diagram details the process of unlinking devices from a member, which involves interactions with both the local database and the external FleetDM system. ```mermaid sequenceDiagram participant Client participant Controller as PeopleController participant Service as PeopleService participant Queries as MemberQueries participant FleetService participant DB as Database participant FleetDM as FleetDM System Client->>Controller: PATCH /people/:id/unlink-device Controller->>Service: unlinkDevice(memberId, orgId) Service->>Queries: findByIdInOrganization(memberId, orgId) Queries->>DB: Query Member DB-->>Queries: Member record (with fleetDmLabelId) Queries-->>Service: PeopleResponseDto alt Member has fleetDmLabelId Service->>FleetService: removeHostsByLabel(fleetDmLabelId) FleetService->>FleetDM: API Call to remove hosts FleetDM-->>FleetService: Removal Result FleetService-->>Service: Removal Result end Service->>DB: Delete Device records for memberId DB-->>Service: Deletion Result Service->>Queries: unlinkDevice(memberId) Queries->>DB: Update Member (set fleetDmLabelId = null) DB-->>Queries: Updated Member record Queries-->>Service: PeopleResponseDto Service-->>Controller: PeopleResponseDto Controller-->>Client: 200 OK (PeopleResponseDto) ``` Sources: [apps/api/src/people/people.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.controller.ts#L263-L280), [apps/api/src/people/people.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.service.ts#L190-L255) ## People Module Configuration The `PeopleModule` is a standard NestJS module that aggregates the `PeopleController` and `PeopleService`. It also imports `AuthModule` for authentication capabilities and provides `FleetService` as a dependency to `PeopleService`. ```typescript import { Module } from '@nestjs/common'; import { AuthModule } from '../auth/auth.module'; import { FleetService } from '../lib/fleet.service'; import { PeopleController } from './people.controller'; import { PeopleService } from './people.service'; @Module({ imports: [AuthModule], controllers: [PeopleController], providers: [PeopleService, FleetService], exports: [PeopleService], }) export class PeopleModule {} ``` The module exports `PeopleService`, making it available for injection into other modules if needed. Sources: [apps/api/src/people/people.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/people.module.ts#L1-L14) --- ## Technical docs: POST Run a browser automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-runautomation ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get run history for an automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-getautomationruns ## Parameters ## Responses ## Try It --- ## Technical docs: Organization Admin URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/organization-admin
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/organization/organization.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts) - [apps/api/src/org-chart/org-chart.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts) - [apps/api/src/organization/organization.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts) - [apps/api/src/context/context.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.controller.ts) - [apps/api/src/org-chart/org-chart.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts) - [apps/api/src/organization/dto/transfer-ownership.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/organization/dto/transfer-ownership.dto.ts) - [apps/api/src/context/context.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.service.ts) - [apps/api/src/context/schemas/context-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/context/schemas/context-operations.ts)
This page outlines the functionalities and architecture related to "Organization Admin" within the API, focusing on managing organization-level settings, organizational charts, and contextual data. It covers the API endpoints, service logic, and data structures involved in these administrative tasks, providing a comprehensive overview for developers and administrators. The core components for organization administration are handled by the `OrganizationController` and `OrganizationService`, which manage details like organization name, logo, and ownership. Additionally, the `OrgChartController` and `OrgChartService` facilitate the creation, update, and deletion of organizational charts, including image uploads. The `ContextController` and `ContextService` provide mechanisms for managing organization-specific contextual data. All administrative endpoints generally require authentication, typically handled by the `HybridAuthGuard`. This guard supports both API key authentication (via `X-API-Key` header) and session-based JWT authentication. For session-based authentication, the `X-Organization-Id` header is often required to specify the target organization. ## Organization Management The `OrganizationController` exposes API endpoints for managing an organization's core properties, including retrieving details, updating information, transferring ownership, and deleting the organization. The `OrganizationService` encapsulates the business logic and database interactions for these operations. ### API Endpoints The following table summarizes the API endpoints available for organization management: | Method | Path | Description | Authentication | | :----- | :------------------------- | :-------------------------------------------- | :------------- | | `GET` | `/organization` | Retrieve details of the authenticated organization. | Required | | `PATCH`| `/organization` | Update specific properties of the organization. | Required | | `POST` | `/organization/transfer-ownership` | Transfer ownership of the organization to another member. | Required | | `DELETE`| `/organization` | Delete the authenticated organization. | Required | | `GET` | `/organization/primary-color` | Retrieve the organization's primary color. Can use an access token for public access. | Optional (token) | Sources: [apps/api/src/organization/organization.controller.ts:20-21](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L20-L21), [apps/api/src/organization/organization.controller.ts:31-33](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L31-L33), [apps/api/src/organization/organization.controller.ts:54-56](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L54-L56), [apps/api/src/organization/organization.controller.ts:80-82](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L80-L82), [apps/api/src/organization/organization.controller.ts:133-135](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L133-L135), [apps/api/src/organization/organization.controller.ts:153-155](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L153-L155) ### Service Logic The `OrganizationService` handles the core business logic for organization operations: * **`findById(id: string)`**: Retrieves an organization by its ID, selecting specific fields such as `id`, `name`, `slug`, `logo`, `metadata`, `website`, `primaryColor`, and more. Throws `NotFoundException` if the organization does not exist. * **`updateById(id: string, updateData: UpdateOrganizationDto)`**: Updates an existing organization's details. It first verifies the organization's existence and then applies the provided `updateData`. * **`deleteById(id: string)`**: Deletes an organization after verifying its existence. * **`transferOwnership(organizationId: string, currentUserId: string, newOwnerId: string)`**: This critical operation transfers the `owner` role from the `currentUserId` to `newOwnerId` within the specified `organizationId`. It performs several validations: * Ensures `newOwnerId` is provided. * Verifies the `currentUserId` is a member of the organization. * Confirms the `currentUserId` holds the `owner` role. * Checks that the `newOwnerId` corresponds to an active member of the organization. * Prevents transferring ownership to the current owner. * Updates roles for both members in a database transaction: the current owner loses `owner` and gains `admin` (if not already present), and the new owner gains `owner`. * **`getPrimaryColor(organizationId: string, token?: string)`**: Retrieves the `primaryColor` of an organization. It supports an optional `token` parameter for public access, which resolves the organization ID via an access grant. If a token is provided and valid, it bypasses standard authentication. Sources: [apps/api/src/organization/organization.service.ts:19-42](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts#L19-L42), [apps/api/src/organization/organization.service.ts:44-84](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts#L44-L84), [apps/api/src/organization/organization.service.ts:86-110](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts#L86-L110), [apps/api/src/organization/organization.service.ts:112-211](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts#L112-L211), [apps/api/src/organization/organization.service.ts:212-261](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts#L212-L261) ### Ownership Transfer Flow The ownership transfer process involves several steps, including validation and role updates, ensuring that only authorized users can perform this critical action. Sources: [apps/api/src/organization/organization.controller.ts:80-131](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.controller.ts#L80-L131), [apps/api/src/organization/organization.service.ts:112-211](https://github.com/blade47/comp/blob/main/apps/api/src/organization/organization.service.ts#L112-L211) ### Data Transfer Objects The `TransferOwnershipDto` defines the request body for transferring ownership, while `TransferOwnershipResponseDto` describes the response structure. Sources: [apps/api/src/organization/dto/transfer-ownership.dto.ts:1-19](https://github.com/blade47/comp/blob/main/apps/api/src/organization/dto/transfer-ownership.dto.ts#L1-L19) ## Org Chart Management The `OrgChartController` provides endpoints for managing an organization's chart, allowing for both interactive chart data and image uploads. The `OrgChartService` handles the storage and retrieval, including integration with AWS S3 for image assets. ### API Endpoints | Method | Path | Description | Authentication | | :----- | :------------------------- | :-------------------------------------------- | :------------- | | `GET` | `/org-chart` | Retrieve the organization chart. | Required | | `PUT` | `/org-chart` | Create or update an interactive organization chart (nodes/edges). | Required | | `POST` | `/org-chart/upload` | Upload an image to be used as the organization chart. | Required | | `DELETE`| `/org-chart` | Delete the organization chart. | Required | Sources: [apps/api/src/org-chart/org-chart.controller.ts:20-22](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts#L20-L22), [apps/api/src/org-chart/org-chart.controller.ts:28-30](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts#L28-L30), [apps/api/src/org-chart/org-chart.controller.ts:33-35](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts#L33-L35), [apps/api/src/org-chart/org-chart.controller.ts:48-50](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts#L48-L50), [apps/api/src/org-chart/org-chart.controller.ts:61-63](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts#L61-L63) ### Service Logic and S3 Integration The `OrgChartService` manages the lifecycle of organization charts, distinguishing between `interactive` charts (stored as nodes and edges) and `uploaded` charts (stored as images in S3). * **`findByOrganization(organizationId: string)`**: Retrieves the organization chart for a given organization. If the chart is an `uploaded` type with an `uploadedImageUrl`, it generates a presigned S3 URL for temporary access to the image. * **`upsertInteractive(organizationId: string, data: UpsertOrgChartDto)`**: Creates or updates an interactive chart. If a previous chart was an uploaded image, it triggers the deletion of the old S3 object *after* the database update succeeds to prevent orphaned S3 files. * **`uploadImage(organizationId: string, data: UploadOrgChartDto)`**: Handles the upload of an image file to S3. * Validates the file type against `ALLOWED_UPLOAD_MIME_TYPES` (PNG, JPEG, GIF, WebP, SVG, BMP, TIFF, PDF). * Enforces a `MAX_FILE_SIZE_BYTES` limit (100MB). * Deletes any existing uploaded image from S3 before uploading the new one. * Uploads the base64 encoded image data to S3, generating a unique key. * Updates the database record to reflect the `uploaded` chart type and the S3 key. * Returns a presigned URL for the newly uploaded image. * **`delete(organizationId: string)`**: Deletes the organization chart record from the database. If an S3 image was associated, it also deletes the corresponding object from S3. * **`getSignedUrl(s3Key: string)`**: Private helper method to generate a presigned URL for an S3 object, expiring in 15 minutes (`SIGNED_URL_EXPIRY`). * **`deleteS3Object(s3Key: string)`**: Private helper method to delete an object from S3. Sources: [apps/api/src/org-chart/org-chart.service.ts:20-27](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L20-L27), [apps/api/src/org-chart/org-chart.service.ts:32-53](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L32-L53), [apps/api/src/org-chart/org-chart.service.ts:55-97](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L55-L97), [apps/api/src/org-chart/org-chart.service.ts:99-166](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L99-L166), [apps/api/src/org-chart/org-chart.service.ts:168-193](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L168-L193), [apps/api/src/org-chart/org-chart.service.ts:195-209](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L195-L209), [apps/api/src/org-chart/org-chart.service.ts:211-224](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L211-L224) ### Org Chart Image Upload Flow The process for uploading an organizational chart image involves client-side preparation, API interaction, and S3 storage. Sources: [apps/api/src/org-chart/org-chart.controller.ts:61-69](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.controller.ts#L61-L69), [apps/api/src/org-chart/org-chart.service.ts:99-166](https://github.com/blade47/comp/blob/main/apps/api/src/org-chart/org-chart.service.ts#L99-L166) ## Context Management The `ContextController` and `ContextService` provide a way to manage organization-specific contextual data. While not strictly "admin" in the sense of managing the organization itself, it allows administrators to define and manage data relevant to their organization's operations. ### API Endpoints | Method | Path | Description | Authentication | | :----- | :------------------------- | :-------------------------------------------- | :------------- | | `GET` | `/context` | Retrieve all context entries for the organization. | Required | | `GET` | `/context/:id` | Retrieve a specific context entry by ID. | Required | | `POST` | `/context` | Create a new context entry. | Required | | `PATCH`| `/context/:id` | Update an existing context entry. | Required | | `DELETE`| `/context/:id` | Delete a context entry. | Required | Sources: [apps/api/src/context/context.controller.ts:20-22](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.controller.ts#L20-L22), [apps/api/src/context/context.controller.ts:28-30](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.controller.ts#L28-L30), [apps/api/src/context/schemas/context-operations.ts:5-29](https://github.com/blade47/comp/blob/main/apps/api/src/context/schemas/context-operations.ts#L5-L29) ### Service Logic The `ContextService` provides standard CRUD operations for context entries: * **`findAllByOrganization(organizationId: string)`**: Fetches all context entries associated with a given `organizationId`, ordered by creation date. * **`findById(id: string, organizationId: string)`**: Retrieves a single context entry by its ID, ensuring it belongs to the specified `organizationId`. Throws `NotFoundException` if not found. * **`create(organizationId: string, createContextDto: CreateContextDto)`**: Creates a new context entry, associating it with the `organizationId`. * **`updateById(id: string, organizationId: string, updateContextDto: UpdateContextDto)`**: Updates an existing context entry. It first validates the entry's existence and ownership before applying updates. * **`deleteById(id: string, organizationId: string)`**: Deletes a context entry after verifying its existence and ownership. Sources: [apps/api/src/context/context.service.ts:13-25](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.service.ts#L13-L25), [apps/api/src/context/context.service.ts:27-46](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.service.ts#L27-L46), [apps/api/src/context/context.service.ts:48-63](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.service.ts#L48-L63), [apps/api/src/context/context.service.ts:65-85](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.service.ts#L65-L85), [apps/api/src/context/context.service.ts:87-109](https://github.com/blade47/comp/blob/main/apps/api/src/context/context.service.ts#L87-L109) --- ## Technical docs: GET Get a specific run by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/browserbase/browserbasecontroller-getrunbyid ## Parameters ## Responses ## Try It --- ## Technical docs: Prisma Layer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-4/prisma-layer
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/customPrismaExtension.ts](https://github.com/blade47/comp/blob/main/apps/api/customPrismaExtension.ts) - [apps/api/prisma/index.js](https://github.com/blade47/comp/blob/main/apps/api/prisma/index.js) - [apps/api/prisma/index.ts](https://github.com/blade47/comp/blob/main/apps/api/prisma/index.ts)
The Prisma Layer primarily refers to the `PrismaExtension` class, a build extension designed for the Trigger.dev platform. Its main purpose is to automate the discovery, generation, and deployment of the Prisma client and schema within a build process, especially when the Prisma schema is sourced from a published package like `@trycompai/db`. This layer ensures that the correct Prisma client is generated both locally during development and within the deployment environment, handling schema resolution, dependency management, and environment variable configuration for database connections. It abstracts away the complexities of integrating Prisma into a serverless or containerized build pipeline. ## PrismaExtension Overview The `PrismaExtension` class is a core component that integrates Prisma into the build process. It implements the `BuildExtension` interface, providing hooks for `onBuildStart` and `onBuildComplete` to manage Prisma-related tasks. ### Configuration Options The behavior of the `PrismaExtension` can be customized through the `PrismaExtensionOptions` interface. | Option Name | Type | Description | | :------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `version` | `string` | Optional. The Prisma client version to use. If not specified, it attempts to determine the version from the build manifest. --- ## Technical docs: Storage Flows URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-4/storage-flows
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/attachments/attachments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts) - [apps/api/src/questionnaire/utils/questionnaire-storage.ts](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts) - [apps/api/src/knowledge-base/utils/s3-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts) - [apps/api/src/attachments/attachments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.controller.ts) - [apps/api/src/attachments/upload-attachment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/upload-attachment.dto.ts) - [apps/api/src/app/s3.ts](https://github.com/blade47/comp/blob/main/apps/api/src/app/s3.ts)
This page details the various storage flows within the application, primarily focusing on how files and data are managed using Amazon S3. It covers the core S3 client configuration, and specific implementations for handling attachments, questionnaire uploads, and knowledge base documents. The system leverages S3 for secure, scalable object storage and uses signed URLs for controlled access to private content. The architecture ensures data segregation by organization and entity, robust security validations for file uploads, and persistence of metadata in a database alongside the S3 object storage. ## Core S3 Configuration and Client The application initializes a global S3 client (`s3Client`) for all S3 interactions. This client is configured based on environment variables and is crucial for connecting to AWS S3 services. ### S3 Client Initialization The `s3Client` is initialized once at application startup. It requires several environment variables to be set for proper functioning, including AWS credentials, region, and the default bucket name. If any critical configuration is missing, the client initialization fails, and a dummy client is created, indicating that S3 operations will not work. The S3 client relies on the following environment variables. If these are not correctly set, S3 operations will fail: - `APP_AWS_REGION` - `APP_AWS_ACCESS_KEY_ID` - `APP_AWS_SECRET_ACCESS_KEY` - `APP_AWS_BUCKET_NAME` (aliased as `BUCKET_NAME`) - `APP_AWS_ENDPOINT` (optional, for custom S3 endpoints) Sources: [apps/api/src/app/s3.ts:10-44](https://github.com/blade47/comp/blob/main/apps/api/src/app/s3.ts#L10-L44) ### S3 Key Extraction and Validation A utility function, `extractS3KeyFromUrl`, is provided to safely parse an S3 URL and extract its corresponding S3 key. This function includes security checks to prevent path traversal attacks and validates the S3 host. ```mermaid sequenceDiagram participant Caller participant S3Utils as S3 Utilities (app/s3.ts) Caller->>S3Utils: extractS3KeyFromUrl(url) S3Utils->>S3Utils: Parse URL alt URL is valid S3Utils->>S3Utils: isValidS3Host(parsedUrl.host) alt Host is valid S3 host S3Utils->>S3Utils: Decode URI component from pathname S3Utils->>S3Utils: Check for path traversal (../) S3Utils-->>Caller: Return S3 Key else Host is not valid S3 host S3Utils-->>Caller: Throw "Invalid URL: Not a valid S3 endpoint" end else URL is malformed or not a URL S3Utils->>S3Utils: Check for domain-like patterns alt Domain-like pattern found S3Utils-->>Caller: Throw "Invalid input: Domain-like pattern detected" else No domain-like pattern S3Utils->>S3Utils: Check for path traversal (../) S3Utils-->>Caller: Return S3 Key (after '/' removal if present) end end ``` Sources: [apps/api/src/app/s3.ts:50-98](https://github.com/blade47/comp/blob/main/apps/api/src/app/s3.ts#L50-L98) ## Attachment Storage Flows The `AttachmentsService` handles all operations related to file attachments, such as uploading, retrieving, and deleting files associated with various entities (e.g., tasks, policies). ### Attachment Upload Process The `uploadAttachment` method is responsible for taking a base64 encoded file, validating it, uploading it to S3, and creating a corresponding record in the database. **Key Steps:** 1. **Validation:** Checks for blocked file extensions and MIME types, and enforces a maximum file size (100MB). 2. **S3 Key Generation:** A unique S3 key is generated using the organization ID, entity type, entity ID, a timestamp, a random ID, and a sanitized file name. Special handling exists for `task_item` entity types to construct a more specific path. * General pattern: `{organizationId}/attachments/{entityType}/{entityId}/{timestamp}-{fileId}-{sanitizedFileName}` * Task Item pattern: `{organizationId}/attachments/task-item/{taskItemEntityType}/{taskItemEntityId}/{timestamp}-{fileId}-{sanitizedFileName}` 3. **S3 Upload:** The file buffer is uploaded to the configured S3 bucket using `PutObjectCommand`. Metadata such as `originalFileName`, `organizationId`, `entityId`, `entityType`, and `uploadedBy` are attached to the S3 object. 4. **Database Record:** A new record is created in the `db.attachment` table, storing the attachment's name, S3 URL (key), type (mapped from MIME type), entity ID, entity type, and organization ID. 5. **Signed URL Generation:** A temporary, signed download URL is generated for immediate access, expiring after 15 minutes (`SIGNED_URL_EXPIRY`). Sources: [apps/api/src/attachments/attachments.service.ts:32-132](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L32-L132) #### UploadAttachmentDto This DTO defines the structure for attachment upload requests, including validation rules. | Field | Type | Description This document is based on the provided source code files. Any information not explicitly present in these files, such as detailed database schemas or external configurations not referenced, is outside the scope of this wiki page. ## Introduction This document outlines the storage flows implemented within the API, focusing on how various types of files and data are managed using Amazon S3. The primary goal is to provide a robust, secure, and scalable solution for handling user-uploaded content, system-generated documents, and knowledge base assets. The system utilizes S3 for object storage, coupled with database records for metadata management, and employs signed URLs for controlled access to private resources. The storage architecture is designed to support different application domains, including attachments for tasks and policies, questionnaire uploads, and knowledge base documents, each with its specific S3 key structure and access patterns. Security measures, such as file type validation and path traversal prevention, are integrated throughout these flows. ## S3 Client and Configuration The application's interaction with Amazon S3 is centralized through a singleton `S3Client` instance, initialized in `apps/api/src/app/s3.ts`. This client is configured using environment variables, ensuring flexibility across different deployment environments. ### S3 Client Initialization Details The `S3Client` is instantiated with the following parameters: * `endpoint`: Optional, used for custom S3-compatible services. * `region`: The AWS region where the S3 bucket resides, e.g., `us-east-1`. * `credentials`: AWS access key ID and secret access key for authentication. * `forcePathStyle`: Set to `true` if `APP_AWS_ENDPOINT` is provided, which is common for local S3 emulators. A `Logger` is used to report initialization status and errors. If essential environment variables (`APP_AWS_ACCESS_KEY_ID`, `APP_AWS_SECRET_ACCESS_KEY`, `BUCKET_NAME`, `APP_AWS_REGION`) are missing, the S3 client will not be properly initialized, leading to a fallback to a dummy client and logging an error. **Key Configuration Variables:** * `BUCKET_NAME`: The default S3 bucket for general attachments. * `APP_AWS_QUESTIONNAIRE_UPLOAD_BUCKET`: Specific bucket for questionnaire uploads. * `APP_AWS_KNOWLEDGE_BASE_BUCKET`: Specific bucket for knowledge base documents. * `APP_AWS_ORG_ASSETS_BUCKET`: Bucket for organization-specific assets. Sources: [apps/api/src/app/s3.ts:10-44](https://github.com/blade47/comp/blob/main/apps/api/src/app/s3.ts#L10-L44) ### S3 Key Extraction and Validation The `extractS3KeyFromUrl` function provides a secure way to obtain an S3 object key from a given URL. It performs several checks: * **URL Parsing:** Attempts to parse the input as a URL. * **S3 Host Validation:** Uses `isValidS3Host` to ensure the URL's host belongs to a legitimate AWS S3 domain. * **Path Traversal Prevention:** Checks for `../` or `..\` patterns in the extracted key to prevent directory traversal vulnerabilities. * **Empty Key Check:** Ensures the extracted key is not empty. This function is critical for securely handling S3 URLs provided by external sources or users. Sources: [apps/api/src/app/s3.ts:50-98](https://github.com/blade47/comp/blob/main/apps/api/src/app/s3.ts#L50-L98) ## Attachment Management The `AttachmentsService` (`apps/api/src/attachments/attachments.service.ts`) is responsible for managing file attachments across various entities within the application. This includes uploading, retrieving, and deleting attachments, as well as generating secure download URLs. ### Attachment Upload Flow The `uploadAttachment` method handles the end-to-end process of storing a new attachment. Sources: - [apps/api/src/attachments/attachments.service.ts:32-132](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L32-L132) - [apps/api/src/attachments/attachments.controller.ts:20-20](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.controller.ts#L20-L20) #### File Validation The service implements strict validation for uploaded files: * **Blocked Extensions:** A list of executable or potentially dangerous file extensions (e.g., `.exe`, `.bat`, `.js`, `.sh`) is blocked. * **Blocked MIME Types:** A list of dangerous MIME types (e.g., `application/x-msdownload`, `application/javascript`) is blocked. * **File Size Limit:** Files are limited to `100 MB` (`MAX_FILE_SIZE_BYTES`). Sources: [apps/api/src/attachments/attachments.service.ts:39-77](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L39-L77) #### S3 Key Structure The S3 key for attachments follows a structured path to ensure organization and easy retrieval: * General: `{organizationId}/attachments/{entityType}/{entityId}/{timestamp}-{fileId}-{sanitizedFileName}` * For `task_item` entity type: `{organizationId}/attachments/task-item/{taskItemEntityType}/{taskItemEntityId}/{timestamp}-{fileId}-{sanitizedFileName}`. The `taskItemEntityType` and `taskItemEntityId` are extracted from the `description` field of the `UploadAttachmentDto`. Sources: [apps/api/src/attachments/attachments.service.ts:80-92](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L80-L92) #### UploadAttachmentDto The data transfer object for attachment uploads includes: | Field | Type | Description ### Attachment Download Flow The `AttachmentsController` exposes an endpoint to generate a signed URL for an attachment. ```mermaid sequenceDiagram participant Client participant AttachmentsController participant AttachmentsService participant S3Client as AWS S3 Client->>AttachmentsController: GET /attachments/:attachmentId/download AttachmentsController->>AttachmentsService: getAttachmentDownloadUrl(orgId, attachmentId) AttachmentsService->>db: findFirst({ id: attachmentId, organizationId }) db-->>AttachmentsService: Attachment Record alt Attachment not found AttachmentsService-->>AttachmentsController: Throw BadRequestException AttachmentsController-->>Client: 400 Bad Request else Attachment found AttachmentsService->>AttachmentsService: generateSignedUrl(attachment.url) AttachmentsService->>S3Client: getSignedUrl(GetObjectCommand) S3Client-->>AttachmentsService: Signed URL AttachmentsService-->>AttachmentsController: { downloadUrl, expiresIn } AttachmentsController-->>Client: 200 OK { downloadUrl, expiresIn } end ``` Sources: - [apps/api/src/attachments/attachments.controller.ts:39-60](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.controller.ts#L39-L60) - [apps/api/src/attachments/attachments.service.ts:149-178](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L149-L178) #### Signed URL Generation The `generateSignedUrl` private method uses `@aws-sdk/s3-request-presigner` to create temporary URLs for `GetObjectCommand` requests. These URLs allow direct download from S3 without requiring AWS credentials, and they expire after a predefined duration (`SIGNED_URL_EXPIRY`, 15 minutes). The `getPresignedDownloadUrlWithFilename` method allows specifying a custom filename for the download. Sources: [apps/api/src/attachments/attachments.service.ts:249-256](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L249-L256), [apps/api/src/attachments/attachments.service.ts:265-277](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L265-L277) ### Other Attachment Operations * **`getAttachments`**: Retrieves all attachment metadata for a given entity, including generated signed URLs for each. * **`getAttachmentMetadata`**: Retrieves attachment metadata without generating signed URLs, useful for displaying lists of attachments. * **`deleteAttachment`**: Deletes an attachment from both S3 and the database. * **`copyPolicyVersionPdf`**: Copies an S3 object (policy PDF) to a new key, used for versioning. * **`deletePolicyVersionPdf`**: Deletes a specific policy version PDF from S3. * **`uploadToS3`**: A generic S3 upload method used by other services (e.g., `policies.service.ts`, `evidence-forms.service.ts`). * **`getObjectBuffer`**: Retrieves an S3 object's content as a Buffer. Sources: [apps/api/src/attachments/attachments.service.ts:135-246](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L135-L246), [apps/api/src/attachments/attachments.service.ts:258-261](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L258-L261), [apps/api/src/attachments/attachments.service.ts:279-293](https://github.com/blade47/comp/blob/main/apps/api/src/attachments/attachments.service.ts#L279-L293) ## Questionnaire Storage Flows The `questionnaire-storage.ts` utility file provides functions for handling questionnaire file uploads to S3 and persisting questionnaire results and answers to the database. ### Questionnaire File Upload The `uploadQuestionnaireFile` function handles the storage of questionnaire files. Sources: [apps/api/src/questionnaire/utils/questionnaire-storage.ts:90-129](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L90-L129) **S3 Key Structure:** The S3 key for questionnaire uploads follows the pattern: `{organizationId}/questionnaire-uploads/{timestamp}-{fileId}-{sanitizedFileName}`. Sources: [apps/api/src/questionnaire/utils/questionnaire-storage.ts:114-114](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L114-L114) ### Questionnaire Result Persistence The `persistQuestionnaireResult` function saves the parsed questionnaire data and answers to the database. Sources: [apps/api/src/questionnaire/utils/questionnaire-storage.ts:48-87](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L48-L87) ### Answer Management * **`saveGeneratedAnswer`**: Updates an existing question's answer or creates a new one in the `questionnaireQuestionAnswer` table. * **`updateAnsweredCount`**: Recalculates and updates the `answeredQuestions` count for a given questionnaire in the `questionnaire` table. Sources: [apps/api/src/questionnaire/utils/questionnaire-storage.ts:132-172](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L132-L172), [apps/api/src/questionnaire/utils/questionnaire-storage.ts:34-45](https://github.com/blade47/comp/blob/main/apps/api/src/questionnaire/utils/questionnaire-storage.ts#L34-L45) ## Knowledge Base Storage Flows The `s3-operations.ts` file within the knowledge base module provides dedicated functions for managing knowledge base documents in S3. ### Knowledge Base Document Upload The `uploadToS3` function handles the upload of knowledge base documents. Sources: [apps/api/src/knowledge-base/utils/s3-operations.ts:34-66](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts#L34-L66) **Key Configuration:** * `APP_AWS_KNOWLEDGE_BASE_BUCKET`: The dedicated S3 bucket for knowledge base documents. * `MAX_FILE_SIZE_BYTES`: Maximum allowed file size for knowledge base documents. Sources: [apps/api/src/knowledge-base/utils/s3-operations.ts:13-13](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts#L13-L13), [apps/api/src/knowledge-base/utils/s3-operations.ts:10-10](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts#L10-L10) ### Knowledge Base Document Access and Deletion * **`generateDownloadUrl`**: Creates a signed URL for downloading a knowledge base document. The `ResponseContentDisposition` is set to `attachment` to prompt a download. * **`generateViewUrl`**: Creates a signed URL for viewing a knowledge base document directly in the browser. The `ResponseContentDisposition` is set to `inline`. * **`deleteFromS3`**: Deletes a document from the `APP_AWS_KNOWLEDGE_BASE_BUCKET`. It returns `true` on success and `false` on error, without throwing exceptions. * **`validateS3Config`**: Ensures that the S3 client is initialized and the `APP_AWS_KNOWLEDGE_BASE_BUCKET` environment variable is set. Sources: [apps/api/src/knowledge-base/utils/s3-operations.ts:69-122](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts#L69-L122), [apps/api/src/knowledge-base/utils/s3-operations.ts:24-32](https://github.com/blade47/comp/blob/main/apps/api/src/knowledge-base/utils/s3-operations.ts#L24-L32) --- ## Technical docs: POST Create :ConnectionId URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/cloudsecuritycontroller-scan ## Parameters ## Responses ## Try It --- ## Technical docs: Validation Schemas URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-4/validation-schemas
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/common/pipes/zod-validation.pipe.ts](https://github.com/blade47/comp/blob/main/apps/api/src/common/pipes/zod-validation.pipe.ts) - [apps/api/src/context/schemas/context-bodies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/context/schemas/context-bodies.ts) - [apps/api/src/policies/schemas/policy-bodies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/policies/schemas/policy-bodies.ts) - [apps/api/src/risks/schemas/risk-bodies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/risks/schemas/risk-bodies.ts) - [apps/api/src/organization/schemas/organization-api-bodies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/organization/schemas/organization-api-bodies.ts) - [apps/api/src/people/schemas/people-bodies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/people/schemas/people-bodies.ts) - [apps/api/src/framework-editor/task-template/schemas/task-template-bodies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/schemas/task-template-bodies.ts)
Validation schemas are a critical component of the API, serving two primary purposes: ensuring data integrity at runtime and providing clear, machine-readable API specifications for documentation. This system leverages Zod for robust runtime validation within NestJS pipes and `ApiBodyOptions` from `@nestjs/swagger` to generate comprehensive OpenAPI documentation. This dual approach guarantees that incoming data conforms to expected structures and types, preventing common errors and security vulnerabilities, while simultaneously offering developers an accurate and up-to-date reference for API interactions. ## Zod Validation Pipe The `ZodValidationPipe` is a custom NestJS `PipeTransform` designed to validate incoming request payloads against a specified Zod schema. This pipe intercepts the request body before it reaches the controller method, ensuring that the data adheres to the defined schema. ### How it Works 1. **Instantiation**: The pipe is instantiated with a `ZodSchema` object, which defines the expected structure and types of the data. 2. **Transformation**: The `transform` method receives the incoming `value` (request body) and attempts to parse it using the provided `ZodSchema`. 3. **Error Handling**: If the `schema.parse()` operation fails (meaning the `value` does not conform to the schema), a `BadRequestException` is thrown, immediately stopping the request processing and returning a 400 Bad Request error to the client. If successful, the parsed (and potentially type-coerced) value is returned. This pipe ensures that only valid data structures proceed to the business logic layer, enhancing API reliability and security. ```typescript import { ArgumentMetadata, BadRequestException, PipeTransform, } from '@nestjs/common'; import { ZodSchema } from 'zod'; export class ZodValidationPipe implements PipeTransform { constructor(private schema: ZodSchema) {} transform(value: unknown, metadata: ArgumentMetadata) { try { const parsedValue = this.schema.parse(value); return parsedValue; } catch (error) { throw new BadRequestException('Validation failed'); } } } ``` Sources: [apps/api/src/common/pipes/zod-validation.pipe.ts:1-17](https://github.com/blade47/comp/blob/main/apps/api/src/common/pipes/zod-validation.pipe.ts#L1-L17) ### Validation Flow The following diagram illustrates the data flow through the `ZodValidationPipe`: ## API Body Schemas for Documentation In addition to runtime validation, the API utilizes `ApiBodyOptions` from `@nestjs/swagger` to define the structure of request bodies for OpenAPI documentation. These schemas are crucial for generating interactive API documentation (e.g., Swagger UI) that clearly outlines expected input formats, types, and examples. These `ApiBodyOptions` are typically exported as constants in dedicated `*-bodies.ts` files and are referenced in controller methods using the `@ApiBody()` decorator. ### Common Structure Most API body schemas follow a pattern of defining `ApiBodyOptions` for `create` and `update` operations, often referencing specific Data Transfer Objects (DTOs). ```typescript import type { ApiBodyOptions } from '@nestjs/swagger'; // ... import DTOs export const ENTITY_BODIES: Record = { createEntity: { description: 'Entity creation data', type: CreateEntityDto, }, updateEntity: { description: 'Entity update data', type: UpdateEntityDto, }, }; ``` ### Detailed Schema Definitions #### Context Schemas The `CONTEXT_BODIES` object defines `ApiBodyOptions` for creating and updating context entries, providing detailed examples for Swagger documentation. ```typescript export const CONTEXT_BODIES: Record = { createContext: { description: 'Context entry data', type: CreateContextDto, examples: { 'Authentication Context': { /* ... */ }, 'Database Context': { /* ... */ }, }, }, updateContext: { description: 'Partial context entry data to update', type: UpdateContextDto, examples: { 'Update Tags': { /* ... */ }, 'Update Answer': { /* ... */ }, }, }, }; ``` Sources: [apps/api/src/context/schemas/context-bodies.ts:4-39](https://github.com/blade47/comp/blob/main/apps/api/src/context/schemas/context-bodies.ts#L4-L39) #### Policy Schemas `POLICY_BODIES` defines the expected request bodies for policy creation and updates. ```typescript export const POLICY_BODIES: Record = { createPolicy: { description: 'Policy creation data', type: CreatePolicyDto, }, updatePolicy: { description: 'Policy update data', type: UpdatePolicyDto, }, }; ``` Sources: [apps/api/src/policies/schemas/policy-bodies.ts:4-13](https://github.com/blade47/comp/blob/main/apps/api/src/policies/schemas/policy-bodies.ts#L4-L13) #### Risk Schemas `RISK_BODIES` specifies the request body structures for creating and updating risks. ```typescript export const RISK_BODIES: Record = { createRisk: { description: 'Risk creation data', type: CreateRiskDto, }, updateRisk: { description: 'Risk update data', }, }; ``` Sources: [apps/api/src/risks/schemas/risk-bodies.ts:4-13](https://github.com/blade47/comp/blob/main/apps/api/src/risks/schemas/risk-bodies.ts#L4-L13) #### Organization Schemas The organization module uses specific `ApiBodyOptions` for updating organization details and transferring ownership. These schemas define properties directly rather than referencing DTOs. ##### `UPDATE_ORGANIZATION_BODY` | Property | Type | Description | Example | | :------------------ | :-------- | :---------------------------------------- | :---------------------------- | | `name` | `string` | Organization name | `New Acme Corporation` | | `slug` | `string` | Organization slug | `new-acme-corp` | | `logo` | `string` | Organization logo URL | `https://example.com/logo.png`| | `metadata` | `string` | Additional metadata in JSON format | `{"theme": "dark"}` | | `website` | `string` | Organization website URL | `https://acme-corp.com` | | `onboardingCompleted`| `boolean` | Whether onboarding is completed | `true` | | `hasAccess` | `boolean` | Whether organization has access to platform| `true` | | `fleetDmLabelId` | `integer` | FleetDM label ID for device management | `123` | | `isFleetSetupCompleted`| `boolean` | Whether FleetDM setup is completed | `false` | | `primaryColor` | `string` | Organization primary color in hex format | `#3B82F6` | Sources: [apps/api/src/organization/schemas/organization-api-bodies.ts:4-58](https://github.com/blade47/comp/blob/main/apps/api/src/organization/schemas/organization-api-bodies.ts#L4-L58) ##### `TRANSFER_OWNERSHIP_BODY` | Property | Type | Description | Example | Required | | :----------- | :-------- | :-------------------------------------------------------------------------- | :------------------ | :------- | | `newOwnerId` | `string` | Member ID of the new owner | `mem_xyz789` | Yes | | `userId` | `string` | User ID of the current owner initiating the transfer (required for API key auth, ignored for JWT auth)| `usr_abc123def456` | No | Sources: [apps/api/src/organization/schemas/organization-api-bodies.ts:60-78](https://github.com/blade47/comp/blob/main/apps/api/src/organization/schemas/organization-api-bodies.ts#L60-L78) #### People Schemas `PEOPLE_BODIES` defines schemas for creating single members, bulk creating members, and updating member information. ```typescript export const PEOPLE_BODIES: Record = { createMember: { description: 'Member creation data', type: CreatePeopleDto, }, bulkCreateMembers: { description: 'Bulk member creation data', type: BulkCreatePeopleDto, }, updateMember: { description: 'Member update data', type: UpdatePeopleDto, }, }; ``` Sources: [apps/api/src/people/schemas/people-bodies.ts:6-19](https://github.com/blade47/comp/blob/main/apps/api/src/people/schemas/people-bodies.ts#L6-L19) #### Task Template Schemas `TASK_TEMPLATE_BODIES` provides the schema for updating task templates within the framework editor. ```typescript export const TASK_TEMPLATE_BODIES = { updateTaskTemplate: { type: UpdateTaskTemplateDto, description: 'Update framework editor task template data', }, }; ``` Sources: [apps/api/src/framework-editor/task-template/schemas/task-template-bodies.ts:3-7](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/schemas/task-template-bodies.ts#L3-L7) ### Relationship between ApiBodyOptions and DTOs `ApiBodyOptions` often reference DTO (Data Transfer Object) classes to describe the expected request body. This provides a clear link between the runtime data structure (defined by the DTO) and its documentation representation. ## Overall API Request Processing with Validation The following diagram illustrates how validation schemas fit into the broader API request processing pipeline, from client request to response. --- ## Technical docs: POST Create :ConnectionId URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/cloudsecuritycontroller-triggerscan ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get :RunId URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/cloudsecuritycontroller-getrunstatus ## Parameters ## Responses ## Try It --- ## Technical docs: Platform Integrations URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-5/platform-integrations
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/integration-platform/controllers/task-integrations.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/task-integrations.controller.ts) - [apps/api/src/integration-platform/controllers/connections.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts) - [apps/api/src/integration-platform/controllers/checks.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/checks.controller.ts) - [apps/api/src/integration-platform/controllers/admin-integrations.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/admin-integrations.controller.ts) - [apps/api/src/integration-platform/controllers/oauth-apps.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/oauth-apps.controller.ts) - [apps/api/src/integration-platform/controllers/oauth.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/oauth.controller.ts) - [apps/api/src/integration-platform/controllers/sync.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/sync.controller.ts) - [apps/api/src/integration-platform/controllers/variables.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/variables.controller.ts) - [apps/api/src/integration-platform/controllers/webhook.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/webhook.controller.ts) - [apps/api/src/integration-platform/services/connection.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts) - [apps/api/src/integration-platform/services/auto-check-runner.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/auto-check-runner.service.ts) - [apps/api/src/integration-platform/services/credential-vault.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts) - [apps/api/src/integration-platform/repositories/provider.repository.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/repositories/provider.repository.ts) - [apps/api/src/integration-platform/utils/credential-utils.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/utils/credential-utils.ts)
The Platform Integrations module provides a robust framework for connecting to external services, managing credentials securely, performing automated checks, synchronizing employee data, and handling webhooks. It abstracts the complexities of various authentication mechanisms (OAuth2, API Key, Custom) and offers a standardized way to interact with diverse third-party platforms. The system is designed to be extensible, allowing new integrations to be added via "manifests" that define their capabilities, authentication methods, and checks. At its core, the module facilitates the creation and management of `Connections` between an organization and an `IntegrationProvider`. It ensures that sensitive `Credentials` are encrypted and handled safely, automatically refreshing OAuth tokens when necessary. Automated `Checks` can be run against these connections to validate configurations or monitor compliance, with results stored and associated with specific tasks. Additionally, the platform supports `Employee Synchronization` from HRIS/IDP systems and processes incoming `Webhooks` to react to external events. ## 1. Integration Providers and Manifests Integration providers represent external services (e.g., AWS, Google Workspace, Rippling) that the platform can connect to. Each provider is defined by a "manifest" which outlines its capabilities, authentication requirements, available checks, and other metadata. The system dynamically loads these manifests to present available integrations and configure their behavior. ### 1.1 Provider Data Model The `ProviderRepository` interacts with the `IntegrationProvider` Prisma model to store metadata about each provider, such as its slug, name, category, capabilities, and whether it's active. This allows the system to persist information about available integrations independently of their manifest definitions. Sources: [apps/api/src/integration-platform/repositories/provider.repository.ts:10-40](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/repositories/provider.repository.ts#L10-L40), [apps/api/src/integration-platform/controllers/connections.controller.ts:40-45](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L40-L45) ### 1.2 Provider Listing and Details The `ConnectionsController` exposes endpoints to list all available integration providers or retrieve details for a specific one. These endpoints aggregate information from the loaded manifests and, for OAuth providers, check if platform-level credentials have been configured. #### API Endpoints | Method | Path | Description | | :----- | :----------------------------------- | :-------------------------------------------- | | `GET` | `/integrations/connections/providers` | List all available integration providers. | | `GET` | `/integrations/connections/providers/:slug` | Get details for a specific provider. | Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:47-147](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L47-L147) ## 2. Connection Management Connections represent an active link between an organization and an integration provider. The `ConnectionService` and `ConnectionRepository` manage the lifecycle and state of these connections. ### 2.1 Connection Lifecycle A connection can transition through various states: `active`, `paused`, `error`, and `disconnected`. The system provides explicit actions to manage these states. Sources: [apps/api/src/integration-platform/services/connection.service.ts:69-95](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L69-L95) ### 2.2 Connection Creation and Updates Creating a connection involves validating the provider, handling different authentication types (OAuth2, API Key, Custom), and storing credentials securely. For custom integrations like AWS, specific validation steps are performed before the connection is activated. Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:182-259](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L182-L259), [apps/api/src/integration-platform/services/connection.service.ts:50-67](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L50-L67) #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :----------------------------------------------------------------------- | | `GET` | `/integrations/connections` | List connections for an organization. | | `GET` | `/integrations/connections/:id` | Get details for a specific connection. | | `POST` | `/integrations/connections` | Create a new connection (API Key/Custom auth). | | `POST` | `/integrations/connections/:id/pause` | Pause a connection. | | `POST` | `/integrations/connections/:id/resume` | Resume a paused connection. | | `POST` | `/integrations/connections/:id/disconnect` | Disconnect (soft delete) a connection. | | `DELETE` | `/integrations/connections/:id` | Delete a connection permanently. | | `PATCH` | `/integrations/connections/:id` | Update connection metadata (e.g., `connectionName`, `regions`). | | `POST` | `/integrations/connections/:id/test` | Test a connection's credentials. | | `POST` | `/integrations/connections/:id/ensure-valid-credentials` | Ensure credentials are valid, refreshing OAuth tokens if needed. | | `PUT` | `/integrations/connections/:id/credentials` | Update credentials for a custom auth connection. | Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:150-484](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L150-L484) For AWS connections, the `ConnectionsController` includes a specialized `validateAwsCredentials` method. This method attempts to assume an IAM role and verify Security Hub enablement across specified regions before a connection is established or updated. This ensures that the provided AWS credentials have the necessary permissions and that the required AWS services are active. Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:262-390](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L262-L390) ## 3. Credential Management and Security The `CredentialVaultService` is responsible for the secure storage, retrieval, and lifecycle management of integration credentials. It employs strong encryption and handles OAuth token refreshing. ### 3.1 Encryption Mechanism All sensitive credentials are encrypted using AES-256-GCM with a derived key. This ensures that credentials are never stored in plain text. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:20-77](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L20-L77) ### 3.2 Credential Storage and Retrieval The `CredentialVaultService` provides methods to store both OAuth tokens and API key/custom credentials. It manages credential versions, keeping a history and marking old versions as rotated. #### Key Functions * `storeOAuthTokens(connectionId, tokens)`: Stores encrypted OAuth access and refresh tokens, along with their expiry. * `storeApiKeyCredentials(connectionId, credentials)`: Stores encrypted API key or custom credentials. * `getDecryptedCredentials(connectionId)`: Retrieves and decrypts the latest credentials for a given connection. * `rotateCredentials(connectionId, newCredentials)`: Marks current credentials as rotated and stores new ones. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:80-164](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L80-L164) ### 3.3 OAuth Token Refresh For OAuth2 integrations, the `CredentialVaultService` automatically handles token refreshing when an access token is expired or nearing expiry. This ensures continuous operation without manual re-authentication. ```mermaid sequenceDiagram participant App as "Application/Service" participant CV as "CredentialVaultService" participant ConnRepo as "ConnectionRepository" participant OAuthProvider as "OAuth Provider API" App->>CV: getValidAccessToken(connId, refreshConfig) CV->>CV: needsRefresh(connId)? alt Token needs refresh & refreshConfig provided CV->>CV: getRefreshToken(connId) CV->>OAuthProvider: POST /token (grant_type=refresh_token) OAuthProvider-->>CV: New Access/Refresh Tokens CV->>CV: storeOAuthTokens(connId, newTokens) CV->>ConnRepo: update(connId, {status: 'active'}) CV-->>App: New Access Token else Token valid or refresh failed CV->>CV: getDecryptedCredentials(connId) CV-->>App: Current Access Token (or null if failed) end ``` Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:192-299](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L192-L299) ### 3.4 Credential Utilities The `credential-utils.ts` file provides helper functions for normalizing credential values, especially when dealing with fields that might be single strings or arrays of strings. * `getStringValue(value)`: Extracts the first string from a `string | string[]` value. * `toStringCredentials(credentials)`: Converts a `{ [key: string]: string | string[] }` object to `{ [key: string]: string }`. Sources: [apps/api/src/integration-platform/utils/credential-utils.ts:1-26](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/utils/credential-utils.ts#L1-L26) ## 4. OAuth Flow Management The `OAuthController` orchestrates the OAuth 2.0 authorization code flow, enabling users to grant the platform access to their external accounts. This involves redirecting users to the OAuth provider, handling callbacks, and securely exchanging authorization codes for tokens. ### 4.1 OAuth State and Credentials * `OAuthStateRepository`: Stores temporary state parameters (`providerSlug`, `organizationId`, `userId`, `codeVerifier`, `redirectUrl`) during the OAuth flow to prevent CSRF attacks and maintain context. * `OAuthCredentialsService`: Manages platform-level (admin-configured) and organization-level (custom app) OAuth client credentials (`clientId`, `clientSecret`, `scopes`). ### 4.2 Starting the OAuth Flow The `startOAuth` endpoint initiates the process by generating a unique state, constructing the authorization URL, and redirecting the user. ```mermaid sequenceDiagram actor User participant App as "Client Application" participant API as "OAuthController" participant OCS as "OAuthCredentialsService" participant OSR as "OAuthStateRepository" participant OAuthProvider as "External OAuth Provider" User->>App: Click "Connect Integration" App->>API: POST /oauth/start {providerSlug, orgId, userId} API->>OCS: getCredentials(providerSlug, orgId) OCS-->>API: {clientId, clientSecret, scopes} API->>OSR: createOAuthState({providerSlug, orgId, userId, codeVerifier}) OSR-->>API: {state, codeVerifier} API->>API: Build Authorization URL API-->>App: {authorizationUrl} App->>User: Redirect to authorizationUrl User->>OAuthProvider: Authorize App OAuthProvider-->>User: Redirect to callbackUrl with code & state ``` Sources: [apps/api/src/integration-platform/controllers/oauth.controller.ts:60-149](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/oauth.controller.ts#L60-L149) ### 4.3 OAuth Callback Handling The `oauthCallback` endpoint receives the authorization code from the OAuth provider, validates the state, exchanges the code for access and refresh tokens, stores them, and then redirects the user back to the application. ```mermaid sequenceDiagram actor User participant OAuthProvider as "External OAuth Provider" participant API as "OAuthController" participant OSR as "OAuthStateRepository" participant OCS as "OAuthCredentialsService" participant CVS as "CredentialVaultService" participant ConnS as "ConnectionService" participant ACR as "AutoCheckRunnerService" participant App as "Client Application" OAuthProvider->>API: GET /oauth/callback {code, state, error?} API->>OSR: findByState(state) OSR-->>API: OAuthState (or null) alt Invalid/Expired State or Error API->>API: Build Error Redirect URL API-->>User: Redirect to Error URL else Valid State API->>OCS: getCredentials(providerSlug, orgId) OCS-->>API: {clientId, clientSecret, scopes} API->>OAuthProvider: POST /token {code, redirect_uri, client_id, client_secret, code_verifier} OAuthProvider-->>API: Access/Refresh Tokens API->>ConnS: createConnection() or findByProviderAndOrg() ConnS-->>API: Connection API->>CVS: storeOAuthTokens(connection.id, tokens) API->>ACR: tryAutoRunChecks(connection.id) API->>API: Build Success Redirect URL API-->>User: Redirect to Success URL end ``` Sources: [apps/api/src/integration-platform/controllers/oauth.controller.ts:152-297](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/oauth.controller.ts#L152-L297) ### 4.4 Managing Custom OAuth Apps The `OAuthAppsController` allows organizations to configure their own OAuth application credentials for a provider, overriding platform-level credentials. This is useful for providers where custom app creation is common or required. #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :------------------------------------------------ | | `GET` | `/integrations/oauth-apps` | List custom OAuth apps for an organization. | | `GET` | `/integrations/oauth-apps/setup/:providerSlug` | Get OAuth app setup info for a provider. | | `POST` | `/integrations/oauth-apps` | Save custom OAuth app credentials for an organization. | | `DELETE` | `/integrations/oauth-apps/:providerSlug` | Delete custom OAuth app credentials. | Sources: [apps/api/src/integration-platform/controllers/oauth-apps.controller.ts:16-96](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/oauth-apps.controller.ts#L16-L96) ### 4.5 Admin-level OAuth Configuration The `AdminIntegrationsController` provides administrative functions to configure platform-wide OAuth client credentials for providers. This is typically done once by platform administrators. #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :------------------------------------------------ | | `GET` | `/admin/integrations` | List all integrations with credential status. | | `GET` | `/admin/integrations/:providerSlug` | Get details for a specific integration. | | `POST` | `/admin/integrations/credentials` | Save platform credentials for an integration. | | `DELETE` | `/admin/integrations/credentials/:providerSlug` | Delete platform credentials for an integration. | Sources: [apps/api/src/integration-platform/controllers/admin-integrations.controller.ts:19-140](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/admin-integrations.controller.ts#L19-L140) ## 5. Automated Checks The platform can run automated checks against integrated services to verify configurations, monitor compliance, or validate specific conditions. These checks are defined within the integration manifests. ### 5.1 Check Definition and Listing Checks are defined within the `manifest.checks` array, often mapping to specific task templates. The `ChecksController` and `TaskIntegrationsController` provide ways to discover and list these checks. #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :------------------------------------------------ | | `GET` | `/integrations/checks/providers/:providerSlug` | List available checks for a provider. | | `GET` | `/integrations/checks/connections/:connectionId` | List available checks for a connection. | | `GET` | `/integrations/tasks/template/:templateId/checks` | Get checks for a specific task template. | | `GET` | `/integrations/tasks/:taskId/checks` | Get checks for a specific task. | | `GET` | `/integrations/tasks/:taskId/runs` | Get check run history for a task. | Sources: [apps/api/src/integration-platform/controllers/checks.controller.ts:19-74](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/checks.controller.ts#L19-L74), [apps/api/src/integration-platform/controllers/task-integrations.controller.ts:35-132](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/task-integrations.controller.ts#L35-L132) ### 5.2 Running Checks Checks can be triggered manually or automatically. The `runCheckForTask` and `runConnectionChecks` methods handle the execution, credential retrieval, and result storage. Sources: [apps/api/src/integration-platform/controllers/task-integrations.controller.ts:135-309](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/task-integrations.controller.ts#L135-L309), [apps/api/src/integration-platform/controllers/checks.controller.ts:77-210](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/checks.controller.ts#L77-L210) ### 5.3 Auto-Check Runner The `AutoCheckRunnerService` determines if checks can be automatically run for a connection (e.g., after creation or credential update) and triggers a background task via `Trigger.dev` for reliable execution. #### Key Functions * `canAutoRunChecks(connectionId)`: Checks if a connection has checks defined and all required variables are configured. * `tryAutoRunChecks(connectionId)`: Triggers the `run-connection-checks` task if `canAutoRunChecks` returns true. Sources: [apps/api/src/integration-platform/services/auto-check-runner.service.ts:12-89](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/auto-check-runner.service.ts#L12-L89) ## 6. Variable Management Integrations can define variables that allow users to customize check behavior or provide configuration values. These variables can have static options or dynamic options fetched from the external service. ### 6.1 Variable Definition and Values Variables are defined in the integration manifest at both the provider and check levels. The `VariablesController` allows retrieving these definitions and managing their values for a specific connection. #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :------------------------------------------------ | | `GET` | `/integrations/variables/providers/:providerSlug` | Get all variables required for a provider's checks. | | `GET` | `/integrations/variables/connections/:connectionId` | Get variables for a specific connection (with current values). | | `POST` | `/integrations/variables/connections/:connectionId` | Save variable values for a connection. | Sources: [apps/api/src/integration-platform/controllers/variables.controller.ts:32-132](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/variables.controller.ts#L32-L132) ### 6.2 Dynamic Options Fetching For variables with dynamic options, the `VariablesController` can fetch these options from the external service using the connection's credentials. This is useful for populating dropdowns with values like AWS regions, user groups, or other configurable entities. Sources: [apps/api/src/integration-platform/controllers/variables.controller.ts:135-249](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/variables.controller.ts#L135-L249) ## 7. Employee Synchronization The `SyncController` provides functionality to synchronize employee data from various HRIS/IDP systems (e.g., Google Workspace, Rippling, Ramp, JumpCloud) into the platform. This ensures that the platform's user base is kept up-to-date with external systems. ### 7.1 Synchronization Process The synchronization process typically involves: 1. Retrieving valid credentials for the connection (refreshing OAuth tokens if necessary). 2. Fetching a list of users from the external service. 3. Identifying active, inactive, or suspended users. 4. Creating new users and members in the platform for active external users. 5. Reactivating existing members if they were previously deactivated but are now active externally. 6. Deactivating members in the platform if they are inactive, suspended, or removed from the external system. Sources: [apps/api/src/integration-platform/controllers/sync.controller.ts:25-885](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/sync.controller.ts#L25-L885) ### 7.2 Supported Sync Providers The `SyncController` explicitly supports the following employee synchronization providers: * **Endpoint**: `POST /integrations/sync/google-workspace/employees` * **Status Check**: `POST /integrations/sync/google-workspace/status` * **Details**: Fetches users via Admin SDK Directory API, handles OAuth token refresh, and manages user/member lifecycle based on Google Workspace user status (active/suspended). * **Endpoint**: `POST /integrations/sync/rippling/employees` * **Status Check**: `POST /integrations/sync/rippling/status` * **Details**: Fetches workers via Rippling V2 REST API, handles OAuth token refresh, and manages user/member lifecycle based on Rippling worker status. Includes a specific call to `mark_app_installed` as required by Rippling. * **Endpoint**: `POST /integrations/sync/ramp/employees` * **Status Check**: `POST /integrations/sync/ramp/status` * **Details**: Fetches users via Ramp Developer API, handles OAuth token refresh, and manages user/member lifecycle based on Ramp user status (active/inactive/suspended). * **Endpoint**: `POST /integrations/sync/jumpcloud/employees` * **Status Check**: `POST /integrations/sync/jumpcloud/status` * **Details**: Fetches users and their associated systems via JumpCloud API (v1 and v2), uses API key authentication, and manages user/member lifecycle based on JumpCloud user state. Sources: [apps/api/src/integration-platform/controllers/sync.controller.ts:25-885](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/sync.controller.ts#L25-L885) ### 7.3 Setting Employee Sync Provider Organizations can configure which external system acts as their primary source for employee synchronization. #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :------------------------------------------------ | | `GET` | `/integrations/sync/employee-sync-provider` | Get the current employee sync provider for an organization. | | `POST` | `/integrations/sync/employee-sync-provider` | Set the employee sync provider for an organization. | Sources: [apps/api/src/integration-platform/controllers/sync.controller.ts:888-963](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/sync.controller.ts#L888-L963) ## 8. Webhook Handling The `WebhookController` is responsible for receiving and processing incoming webhooks from integrated services. It includes mechanisms for signature verification to ensure the authenticity and integrity of webhook payloads. ### 8.1 Webhook Processing Flow When a webhook is received, the system first identifies the provider, verifies the connection, and then, if configured, validates the webhook's signature using a shared secret. If the signature is valid, the webhook payload is passed to the integration's custom handler for processing. Sources: [apps/api/src/integration-platform/controllers/webhook.controller.ts:33-100](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/webhook.controller.ts#L33-L100) ### 8.2 Signature Verification The `WebhookController` implements a robust signature verification process using HMAC. This protects against tampering and ensures that webhooks originate from trusted sources. #### Key Functions * `extractSignature(headers, headerName)`: Extracts the signature string from request headers. * `parseSignatureValue(signature)`: Parses signature values that might include prefixes (e.g., `sha256=...`). * `verifyHmac(rawBody, secret, algorithm, providedSignature)`: Performs a timing-safe HMAC verification against the raw request body and a stored secret. Using `timingSafeEqual` for comparing HMAC signatures is crucial to prevent timing attacks, where an attacker could deduce parts of the secret by measuring the time it takes for the comparison function to return. Sources: [apps/api/src/integration-platform/controllers/webhook.controller.ts:18-30](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/webhook.controller.ts#L18-L30), [apps/api/src/integration-platform/controllers/webhook.controller.ts:102-132](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/webhook.controller.ts#L102-L132) #### API Endpoints | Method | Path | Description | | :----- | :------------------------------------- | :------------------------------------------------ | | `POST` | `/integrations/webhooks/:providerSlug/:connectionId` | Receives and processes incoming webhooks for a specific connection. | Sources: [apps/api/src/integration-platform/controllers/webhook.controller.ts:33-100](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/webhook.controller.ts#L33-L100) --- ## Technical docs: GET Get comments for an entity URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/comments/commentscontroller-getcomments ## Parameters ## Responses ## Try It --- ## Technical docs: Cloud Security URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-5/cloud-security
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/cloud-security/cloud-security.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts) - [apps/api/src/cloud-security/providers/azure-security.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/azure-security.service.ts) - [apps/api/src/cloud-security/providers/aws-security.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/aws-security.service.ts) - [apps/api/src/cloud-security/cloud-security.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.controller.ts) - [apps/api/src/cloud-security/providers/gcp-security.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/gcp-security.service.ts) - [apps/api/src/cloud-security/cloud-security.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.module.ts)
The Cloud Security module provides functionality to scan various cloud providers (AWS, Azure, GCP) for security findings. It integrates with the system's credential management to securely access cloud resources, orchestrates scan tasks, and stores the collected security findings in the database. This module is crucial for maintaining a continuous security posture across integrated cloud environments. At a high level, the module exposes API endpoints to trigger and monitor security scans. The core logic handles authentication, delegates to provider-specific services for actual scanning, and then processes and persists the results. ## Architecture Overview The Cloud Security module is structured around a central `CloudSecurityService` which orchestrates the scanning process, and provider-specific services (`AWSSecurityService`, `AzureSecurityService`, `GCPSecurityService`) that handle the unique API interactions for each cloud platform. The `CloudSecurityController` exposes the external API for initiating and monitoring scans. Sources: [apps/api/src/cloud-security/cloud-security.module.ts:1-17](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.module.ts#L1-L17), [apps/api/src/cloud-security/cloud-security.service.ts:20-30](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L20-L30), [apps/api/src/cloud-security/cloud-security.controller.ts:13-16](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.controller.ts#L13-L16) ## Data Structures The module defines key interfaces for representing security findings and scan results. ### SecurityFinding The `SecurityFinding` interface represents a single security issue identified during a scan. | Field | Type | Description | | :------------- | :----------------------------------- | :------------------------------------------------------------------------ | | `id` | `string` | Unique identifier for the finding. | | `title` | `string` | A brief title for the finding. | | `description` | `string` | Detailed description of the finding. | | `severity` | `'info' \| 'low' \| 'medium' \| 'high' \| 'critical'` | The severity level of the finding. | | `resourceType` | `string` | The type of cloud resource affected (e.g., `EC2 Instance`, `Storage Account`). | | `resourceId` | `string` | The identifier of the affected resource. | | `remediation` | `string?` | Optional steps to remediate the finding. | | `evidence` | `Record?` | Optional additional context or raw data related to the finding. | | `createdAt` | `string` | Timestamp when the finding was created or observed. | | `passed` | `boolean?` | Indicates if this is a passing check (default: `false`). | Sources: [apps/api/src/cloud-security/cloud-security.service.ts:10-20](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L10-L20) ### ScanResult The `ScanResult` interface encapsulates the outcome of a security scan for a given connection. | Field | Type | Description | | :---------- | :------------------- | :--------------------------------------------- | | `success` | `boolean` | Indicates if the scan completed successfully. | | `provider` | `string` | The cloud provider that was scanned. | | `findings` | `SecurityFinding[]` | An array of security findings discovered. | | `scannedAt` | `string` | Timestamp when the scan was performed. | | `error` | `string?` | Optional error message if the scan failed. | Sources: [apps/api/src/cloud-security/cloud-security.service.ts:22-29](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L22-L29) ## Cloud Security Service (`CloudSecurityService`) The `CloudSecurityService` is the core service responsible for orchestrating cloud security scans. It handles connection validation, credential retrieval (including OAuth token refresh), delegation to provider-specific scanning logic, and persistence of scan results. ### Scan Process (`scan` method) The `scan` method initiates a security scan for a given `connectionId` and `organizationId`. Sources: [apps/api/src/cloud-security/cloud-security.service.ts:32-167](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L32-L167) #### Credential Management The service dynamically handles credential retrieval based on the integration provider's authentication type. ```mermaid sequenceDiagram participant CloudSecurityService participant CredentialVaultService participant OAuthCredentialsService participant IntegrationPlatform CloudSecurityService->>IntegrationPlatform: getManifest(providerSlug) alt If OAuth2 CloudSecurityService->>OAuthCredentialsService: getCredentials(providerSlug, orgId) OAuthCredentialsService-->>CloudSecurityService: oauthCreds CloudSecurityService->>CredentialVaultService: getValidAccessToken(connectionId, oauthConfig) CredentialVaultService-->>CloudSecurityService: accessToken CloudSecurityService->>CredentialVaultService: getDecryptedCredentials(connectionId) CredentialVaultService-->>CloudSecurityService: decryptedCreds CloudSecurityService->>CloudSecurityService: Combine decryptedCreds + accessToken else If Non-OAuth CloudSecurityService->>CredentialVaultService: getDecryptedCredentials(connectionId) CredentialVaultService-->>CloudSecurityService: decryptedCreds CloudSecurityService->>CloudSecurityService: Use decryptedCreds directly end CloudSecurityService-->>CloudSecurityService: Credentials ready for provider scan ``` Sources: [apps/api/src/cloud-security/cloud-security.service.ts:60-99](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L60-L99) ### Triggering and Monitoring Scans The `CloudSecurityService` also provides methods to trigger scans asynchronously and monitor their status using `@trigger.dev/sdk`. - **`triggerScan(connectionId: string, organizationId: string)`**: Initiates an asynchronous scan by triggering a `run-cloud-security-scan` task. This returns a `runId` to track the task's progress. - **`getRunStatus(runId: string, connectionId: string, organizationId: string)`**: Retrieves the status of a previously triggered scan run. It verifies the connection's ownership and fetches the run status from the `@trigger.dev/sdk`. The `triggerScan` method leverages an external task orchestration system (`@trigger.dev/sdk`) to execute the scan asynchronously. This prevents long-running HTTP requests and allows for more robust background processing. Sources: [apps/api/src/cloud-security/cloud-security.service.ts:170-218](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L170-L218) ### Storing Findings (`storeFindings` method) After a scan, the `storeFindings` private method persists the `SecurityFinding` objects into the database. It creates an `IntegrationCheckRun` record and then `IntegrationCheckResult` records for each finding within a database transaction to ensure data consistency. ```typescript // Example of storing findings await db.$transaction(async (tx) => { const scanRun = await tx.integrationCheckRun.create({ data: { connectionId, checkId: `${provider}-security-scan`, // ... other run details }, }); if (findings.length > 0) { await tx.integrationCheckResult.createMany({ data: findings.map((finding) => ({ checkRunId: scanRun.id, passed: finding.passed ?? false, // ... other finding details })), }); } }); ``` Sources: [apps/api/src/cloud-security/cloud-security.service.ts:220-256](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.service.ts#L220-L256) ## Cloud Security Controller (`CloudSecurityController`) The `CloudSecurityController` exposes the REST API endpoints for interacting with the Cloud Security module. | Method | Path | Guard | Description --- ### Cloud Security Module The `CloudSecurityModule` is responsible for setting up the Cloud Security feature. It imports necessary modules, registers controllers, and provides the services required for cloud security scanning. ```typescript @Module({ imports: [IntegrationPlatformModule, AuthModule], controllers: [CloudSecurityController], providers: [ CloudSecurityService, GCPSecurityService, AWSSecurityService, AzureSecurityService, ], exports: [CloudSecurityService], }) export class CloudSecurityModule {} ``` Sources: [apps/api/src/cloud-security/cloud-security.module.ts:6-17](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/cloud-security.module.ts#L6-L17) ## Provider-Specific Security Services Each cloud provider has a dedicated service to handle its unique API interactions for security scanning. ### AWS Security Service (`AWSSecurityService`) The `AWSSecurityService` is responsible for scanning AWS environments for security findings, primarily leveraging AWS Security Hub. #### Key Features: - **Credential Handling**: Supports both IAM Role assumption (two-hop process) and direct Access Key authentication. - **Region Awareness**: Scans multiple AWS regions, determined from connection credentials or variables, defaulting to `us-east-1`. - **Security Hub Integration**: Fetches findings from AWS Security Hub. - **Error Tolerance**: Handles per-region failures gracefully (e.g., Security Hub not enabled in a region) by logging warnings and continuing with other regions. #### IAM Role Assumption Flow When using IAM Role authentication, the service performs a two-hop role assumption: 1. Assumes an internal `SECURITY_HUB_ROLE_ASSUMER_ARN` role. 2. Using the credentials from the first hop, assumes the customer's specified `customerRoleArn` with an `externalId`. ```mermaid sequenceDiagram participant AppService as CloudSecurityService participant STSClientBase as AWS STS (Base) participant STSClientAssumer as AWS STS (Assumer) participant CustomerAWS as Customer AWS Account AppService->>STSClientBase: AssumeRoleCommand (RoleAssumer ARN) STSClientBase-->>AppService: Temp Creds (for RoleAssumer) AppService->>STSClientAssumer: AssumeRoleCommand (Customer Role ARN, External ID) STSClientAssumer-->>AppService: Temp Creds (for Customer Role) AppService->>CustomerAWS: Perform Security Hub Scan (using Customer Role Temp Creds) CustomerAWS-->>AppService: Security Findings ``` Sources: [apps/api/src/cloud-security/providers/aws-security.service.ts:133-184](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/aws-security.service.ts#L133-L184) #### Finding Mapping AWS Security Hub findings are mapped to the generic `SecurityFinding` interface, including severity mapping and region appending to the title for clarity. Sources: [apps/api/src/cloud-security/providers/aws-security.service.ts:230-267](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/aws-security.service.ts#L230-L267) ### Azure Security Service (`AzureSecurityService`) The `AzureSecurityService` focuses on collecting security alerts and assessments from Azure subscriptions. #### Key Features: - **OAuth2 Authentication**: Obtains an access token using client credentials flow (`tenantId`, `clientId`, `clientSecret`). - **Microsoft Defender for Cloud Integration**: Fetches security alerts and assessments. - **Pagination**: Handles paginated API responses to retrieve all available findings. - **Permission Handling**: Provides specific remediation advice if 403 (AuthorizationFailed) errors are encountered, suggesting the "Security Reader" role. Sources: [apps/api/src/cloud-security/providers/azure-security.service.ts:32-192](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/azure-security.service.ts#L32-L192) ### GCP Security Service (`GCPSecurityService`) The `GCPSecurityService` integrates with Google Cloud Security Command Center to retrieve security findings. #### Key Features: - **OAuth2 Authentication**: Requires an access token (obtained via the `CloudSecurityService`'s credential flow). - **Organization-Level Scan**: Scans findings at the GCP organization level. - **Security Command Center Integration**: Queries the Security Command Center API for active findings. - **Pagination**: Iterates through paginated results to collect all findings. - **Permission Handling**: Provides specific remediation advice for `PERMISSION_DENIED` errors, suggesting the "Security Center Findings Viewer" role. Sources: [apps/api/src/cloud-security/providers/gcp-security.service.ts:20-109](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/gcp-security.service.ts#L20-L109) When integrating with cloud providers, correct permissions are critical. The services are designed to provide specific feedback for common permission-related issues: - **AWS**: If Security Hub is not enabled in a region or `AccessDenied` errors occur, the service logs a warning and skips that region. For role assumption, ensure the `SECURITY_HUB_ROLE_ASSUMER_ARN` is configured and the customer's IAM role trust policy allows assumption by the `roleAssumer`. Sources: [apps/api/src/cloud-security/providers/aws-security.service.ts:109-112](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/aws-security.service.ts#L109-L112), [apps/api/src/cloud-security/providers/aws-security.service.ts:140-143](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/aws-security.service.ts#L140-L143) - **Azure**: For 403 or `AuthorizationFailed` errors when fetching alerts or assessments, the service adds a `SecurityFinding` indicating "Unable to access Security Alerts/Assessments" with a remediation step: "Assign the 'Security Reader' role to your App Registration on the subscription." Sources: [apps/api/src/cloud-security/providers/azure-security.service.ts:80-92](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/azure-security.service.ts#L80-L92), [apps/api/src/cloud-security/providers/azure-security.service.ts:133-145](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/azure-security.service.ts#L133-L145) - **GCP**: For `ACCESS_TOKEN_SCOPE_INSUFFICIENT` or `PERMISSION_DENIED` (403) errors, the service throws errors with specific messages: "OAuth scopes insufficient. Please disconnect and reconnect the GCP integration." or "Permission denied. Grant the 'Security Center Findings Viewer' role to your Google account at the organization level." Sources: [apps/api/src/cloud-security/providers/gcp-security.service.ts:80-93](https://github.com/blade47/comp/blob/main/apps/api/src/cloud-security/providers/gcp-security.service.ts#L80-L93) --- ## Technical docs: Notifications URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-5/notifications
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/comments/comment-mention-notifier.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comment-mention-notifier.service.ts) - [apps/api/src/notifications/novu.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/notifications/novu.service.ts) - [apps/api/src/email/templates/finding-notification.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/finding-notification.tsx) - [apps/api/src/email/templates/comment-mentioned.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/comment-mentioned.tsx) - [apps/api/src/email/resend.ts](https://github.com/blade47/comp/blob/main/apps/api/src/email/resend.ts) - [apps/api/src/email/components/footer.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/footer.tsx) - [apps/api/src/email/components/logo.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/logo.tsx) - [apps/api/src/email/templates/task-status-changed.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-status-changed.tsx)
The notification system provides mechanisms for alerting users about significant events within the application, such as mentions in comments, changes in task status, or new findings. It leverages both email and in-app notifications to ensure timely communication. The system is designed to be flexible, allowing for different notification types and user-specific preferences, including unsubscribe options. At its core, the notification architecture integrates with external services like Novu for in-app notifications and Resend for email delivery, while utilizing React-based templates for consistent and branded email content. ## Notification Architecture Overview The notification system is composed of several key services and components that work together to deliver alerts to users. This includes a dedicated service for handling in-app notifications via Novu, a utility for sending emails via Resend, and various React components for rendering email templates. A primary example of its usage is the `CommentMentionNotifierService`, which orchestrates the process of notifying users when they are mentioned in a comment. Sources: [apps/api/src/comments/comment-mention-notifier.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comment-mention-notifier.service.ts#L1-L269), [apps/api/src/notifications/novu.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/notifications/novu.service.ts#L1-L57), [apps/api/src/email/resend.ts](https://github.com/blade47/comp/blob/main/apps/api/src/email/resend.ts#L1-L89) ## In-App Notifications with Novu The `NovuService` is responsible for sending in-app notifications by interacting with the Novu API. It provides a `trigger` method that allows other services to initiate notification workflows. ### NovuService Structure The `NovuService` is an injectable NestJS service that encapsulates the logic for calling the Novu API. ```typescript @Injectable() export class NovuService { private readonly logger = new Logger(NovuService.name); async trigger(params: { workflowId: string; subscriberId: string; email: string; payload: Record; }): Promise { // ... implementation ... } } ``` Sources: [apps/api/src/notifications/novu.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/notifications/novu.service.ts#L3-L12) ### Triggering Novu Workflows The `trigger` method sends a POST request to the Novu API endpoint `/v1/events/trigger`. It requires a `workflowId`, `subscriberId`, `email`, and a `payload` containing dynamic data for the notification. The `NOVU_API_KEY` environment variable is essential for authentication. If it's not configured, a warning is logged, and the notification is skipped. The `NOVU_API_KEY` environment variable must be configured for Novu in-app notifications to function. Without it, the `NovuService` will log a warning and skip triggering any workflows. ```mermaid sequenceDiagram participant Caller as Calling Service participant NovuS as NovuService participant NovuAPI as Novu API Caller->>NovuS: trigger({workflowId, subscriberId, email, payload}) alt NOVU_API_KEY is missing NovuS-->>Caller: Logs warning, returns else NOVU_API_KEY is present NovuS->>NovuAPI: POST /v1/events/trigger
Headers: Authorization, Content-Type
Body: {name: workflowId, to: {subscriberId, email}, payload} alt API call fails NovuAPI--xNovuS: HTTP Error Response (e.g., 4xx, 5xx) NovuS-->>Caller: Logs error, returns else API call succeeds NovuAPI-->>NovuS: HTTP 200 OK NovuS-->>Caller: Logs success, returns end end ``` Sources: [apps/api/src/notifications/novu.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/notifications/novu.service.ts#L14-L57) ## Email Notifications with Resend Email notifications are handled through the `sendEmail` utility, which integrates with the Resend email service. This utility allows for sending rich HTML emails using React components as templates. ### Resend Configuration The `resend` client is initialized using the `RESEND_API_KEY` environment variable. If this key is not present, the `resend` object will be `null`, and any attempt to send an email will result in an error. ```typescript export const resend = process.env.RESEND_API_KEY ? new Resend(process.env.RESEND_API_KEY) : null; ``` Sources: [apps/api/src/email/resend.ts](https://github.com/blade47/comp/blob/main/apps/api/src/email/resend.ts#L4-L6) ### The `sendEmail` Function The `sendEmail` function is a central utility for dispatching emails. It takes various parameters, including the recipient, subject, and a React component for the email body. It also supports different `from` addresses based on whether the email is `marketing` or `system` related. | Parameter | Type | Description Sources: [apps/api/src/notifications/novu.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/notifications/novu.service.ts#L3-L57), [apps/api/src/email/resend.ts](https://github.com/blade47/comp/blob/main/apps/api/src/email/resend.ts#L1-L89), [apps/api/src/comments/comment-mention-notifier.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comment-mention-notifier.service.ts#L1-L269), [apps/api/src/email/templates/comment-mentioned.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/comment-mentioned.tsx#L1-L105), [apps/api/src/email/templates/finding-notification.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/finding-notification.tsx#L1-L127), [apps/api/src/email/templates/task-status-changed.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-status-changed.tsx#L1-L103), [apps/api/src/email/components/footer.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/footer.tsx#L1-L12), [apps/api/src/email/components/logo.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/logo.tsx#L1-L10) ## Email Templates The system uses React components to define email templates, ensuring a consistent look and feel across different notification types. These templates leverage `@react-email/components` for structuring the email content and Tailwind CSS for styling. ### Common Email Components All email templates utilize shared components for branding and consistency: * **`Logo`**: Displays the Comp AI logo at the top of the email. * **`Footer`**: Contains standard footer information, including a link to Comp AI and unsubscribe options. Sources: [apps/api/src/email/components/logo.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/logo.tsx#L1-L10), [apps/api/src/email/components/footer.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/footer.tsx#L1-L12) ### Specific Email Templates #### `CommentMentionedEmail` This template is used when a user is mentioned in a comment. It displays who mentioned the user, the entity where the mention occurred, and a snippet of the comment content. It also provides a direct link to view the comment. ```typescript interface Props { toName: string; toEmail: string; commentContent: string; mentionedByName: string; entityName: string; entityRoutePath: string; entityId: string; organizationId: string; commentUrl: string; } ``` The `CommentMentionedEmail` component includes a `getPlainText` utility to extract readable text from TipTap JSON content, which is then used for the email preview and display. Sources: [apps/api/src/email/templates/comment-mentioned.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/comment-mentioned.tsx#L14-L44) #### `FindingNotificationEmail` This template is used for notifications related to findings, such as new findings or status updates. It includes details like the organization, task title, finding type, content, and a link to view the finding. ```typescript interface Props { toName: string; toEmail: string; heading: string; message: string; taskTitle: string; organizationName: string; findingType: string; findingContent: string; newStatus?: string; findingUrl: string; } ``` Sources: [apps/api/src/email/templates/finding-notification.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/finding-notification.tsx#L14-L24) #### `TaskStatusChangedEmail` This template informs users when the status of a task has changed. It specifies the old and new statuses, who made the change, and provides a link to the task. ```typescript interface Props { toName: string; toEmail: string; taskTitle: string; oldStatus: string; newStatus: string; changedByName: string; organizationName: string; taskUrl: string; } ``` Sources: [apps/api/src/email/templates/task-status-changed.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-status-changed.tsx#L14-L23) ## Comment Mention Notification Flow The `CommentMentionNotifierService` is a concrete implementation of the notification system, specifically designed to handle mentions within comments. It ensures that mentioned users receive both email and in-app notifications, provided they have not unsubscribed. ### `notifyMentionedUsers` Method This method orchestrates the entire process of notifying users mentioned in a comment. ### Extract Mentioned User IDs The `extractMentionedUserIds` function parses the comment content (expected to be in a JSON format, potentially from a rich text editor like TipTap) to identify all unique user IDs that have been mentioned. ### Retrieve User Information It fetches details for the user who made the mention (`mentionedByUserId`) and all the mentioned users (`mentionedUserIds`) from the database. ### Normalize Context URL and Build Fallback The system attempts to normalize the provided `contextUrl` to ensure it's a valid and safe URL within the application's allowed origins and organization. If no valid `contextUrl` is provided or it's invalid, `buildFallbackCommentContext` generates a default URL based on the comment's `entityType` and `entityId` (e.g., task, vendor, risk, policy). This ensures notifications always link to a relevant page. ### Check Unsubscribe Status Before sending any notification, the system checks if the recipient user has unsubscribed from "task mentions" (currently used as the preference for comment mentions). If unsubscribed, the notification is skipped for that user. ### Send Email Notification For each eligible mentioned user, an email is sent using the `sendEmail` utility with the `CommentMentionedEmail` React component. The email includes details about the mention, the entity, and a direct link to the comment. ### Send In-App Notification Concurrently, an in-app notification is triggered via the `NovuService` for each eligible mentioned user. This notification uses the `comment-mentioned` workflow and includes relevant payload data. Sources: [apps/api/src/comments/comment-mention-notifier.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comment-mention-notifier.service.ts#L1-L269) ### URL Context Resolution The notification system includes robust logic to construct valid and secure URLs for linking to specific entities within the application. * **`getAppBaseUrl()`**: Retrieves the base URL for the application, prioritizing `NEXT_PUBLIC_APP_URL`, then `BETTER_AUTH_URL`, and falling back to `https://app.trycomp.ai`. * **`getAllowedOrigins()`**: Gathers a list of allowed origins from environment variables to validate incoming `contextUrl`s. * **`tryNormalizeContextUrl()`**: Validates a provided `contextUrl` against allowed origins and ensures it belongs to the correct organization to prevent malicious deep-linking. * **`buildFallbackCommentContext()`**: If a `contextUrl` is not provided or invalid, this function constructs a URL based on the `entityType` (e.g., `task`, `vendor`, `risk`, `policy`) and `entityId`, querying the database to retrieve relevant entity names and routes. The `tryNormalizeContextUrl` and `buildFallbackCommentContext` functions are critical for security, ensuring that notification links point to valid, internal application pages and prevent potential path traversal or phishing attempts by validating against allowed origins and organization IDs. Sources: [apps/api/src/comments/comment-mention-notifier.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comment-mention-notifier.service.ts#L41-L150) ## Unsubscribe Mechanism The system integrates with an unsubscribe mechanism (`isUserUnsubscribed` from `@trycompai/email`) to respect user preferences. When sending notifications, it checks if a user has opted out of specific notification types. For comment mentions, the `taskMentions` preference is currently used. Sources: [apps/api/src/comments/comment-mention-notifier.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comment-mention-notifier.service.ts#L187-L191) --- ## Technical docs: POST Create a new comment URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/comments/commentscontroller-createcomment ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: PUT Update a comment URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/comments/commentscontroller-updatecomment ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: Comments System URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-5/comments-system
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts) - [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts) - [apps/api/src/comments/dto/comment-responses.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/comment-responses.dto.ts) - [apps/api/src/comments/comments.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.module.ts) - [apps/api/src/comments/dto/update-comment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/update-comment.dto.ts) - [apps/api/src/comments/dto/create-comment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/create-comment.dto.ts) - [apps/api/src/comments/dto/delete-comment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/delete-comment.dto.ts)
The Comments System provides a robust API for managing comments associated with various entities within the application, such as tasks, policies, vendors, and risks. It supports creating, retrieving, updating, and deleting comments, including handling file attachments and user mentions. The system is designed to ensure data consistency through transactions and integrates with an attachment service for file management and a notification service for user mentions. ## Architecture Overview The Comments System is implemented as a NestJS module, following a standard Controller-Service pattern. * **`CommentsController`**: Handles incoming HTTP requests, validates input, and delegates business logic to the `CommentsService`. It defines the API endpoints for comment operations. * **`CommentsService`**: Contains the core business logic for managing comments, interacting with the database, `AttachmentsService`, and `CommentMentionNotifierService`. It also includes access validation for entities. * **DTOs (Data Transfer Objects)**: Define the structure for request payloads and API responses, ensuring clear data contracts. * **`CommentsModule`**: Orchestrates the components, declares providers and controllers, and manages dependencies. The system leverages `HybridAuthGuard` for flexible authentication (JWT or API Key) and uses `AuthContext` to determine the authenticated user and organization. Sources: [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts#L22-L30), [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L21-L24), [apps/api/src/comments/comments.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.module.ts#L6-L12) ## Data Transfer Objects (DTOs) The Comments System uses several DTOs to structure data for requests and responses. ### Request DTOs * **`CreateCommentDto`**: Used when creating a new comment. * `content`: The text content of the comment (max 2000 characters). * `entityId`: The ID of the entity the comment belongs to. * `entityType`: The type of entity (`task`, `policy`, `vendor`, `risk`). * `contextUrl?`: Optional URL for deep-linking in notifications. * `attachments?`: An array of `UploadAttachmentDto` for files to be attached. * `userId?`: Required for API key authentication to specify the author. * **`UpdateCommentDto`**: Used when updating an existing comment. * `content`: The new text content of the comment (max 2000 characters). * `contextUrl?`: Optional updated URL for deep-linking. * `userId?`: Required for API key authentication to specify the author. * **`DeleteCommentDto`**: Used when deleting a comment. * `userId?`: Required for API key authentication to specify the user performing the deletion. Sources: [apps/api/src/comments/dto/create-comment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/create-comment.dto.ts#L9-L55), [apps/api/src/comments/dto/update-comment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/update-comment.dto.ts#L6-L34), [apps/api/src/comments/dto/delete-comment.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/delete-comment.dto.ts#L5-L15) ### Response DTOs The primary response DTO is `CommentResponseDto`, which includes nested DTOs for author information and attachment metadata. * **`CommentResponseDto`**: Represents a single comment returned by the API. * `id`: Unique identifier for the comment. * `content`: The comment's text content. * `author`: An `AuthorResponseDto` object containing details about the comment's author. * `attachments`: An array of `AttachmentMetadataDto` objects, providing metadata about attached files (without download URLs, which are generated on-demand). * `createdAt`: Timestamp of when the comment was created. * **`AuthorResponseDto`**: Details about the user who authored the comment. * `id`, `name`, `email`, `image`, `deactivated`. * **`AttachmentMetadataDto`**: Basic metadata for an attachment associated with a comment. * `id`, `name`, `type`, `createdAt`. * **`AttachmentResponseDto`**: Similar to `AttachmentMetadataDto` but includes a `downloadUrl` and `size`. This is used internally by the service when handling attachments, but `AttachmentMetadataDto` is returned in `CommentResponseDto`. Sources: [apps/api/src/comments/dto/comment-responses.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/dto/comment-responses.dto.ts#L4-L95) ## API Endpoints The `CommentsController` exposes the following REST API endpoints: | Method | Path | Description | Request Body | Response Type | Authentication | | :----- | :-------------------- | :------------------------------------------------------------------------ | :-------------------- | :------------------- | :------------- | | `GET` | `/comments` | Retrieve all comments for a specific entity. | Query: `entityId`, `entityType` | `CommentResponseDto[]` | HybridAuthGuard | | `POST` | `/comments` | Create a new comment on an entity with optional attachments. | `CreateCommentDto` | `CommentResponseDto` | HybridAuthGuard | | `PUT` | `/comments/:commentId` | Update the content of an existing comment (author only). | `UpdateCommentDto` | `CommentResponseDto` | HybridAuthGuard | | `DELETE` | `/comments/:commentId` | Delete a comment and all its attachments (author only). | `DeleteCommentDto` | `{ success: boolean, deletedCommentId: string, message: string }` | HybridAuthGuard | All endpoints require an `X-Organization-Id` header for session authentication, which is optional for API key authentication. Sources: [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts#L22-L218) ## Core Logic: `CommentsService` The `CommentsService` encapsulates the business logic for comment management. ### Entity Access Validation Before performing any comment operation, the service validates that the target entity exists within the specified organization and that the user has access. This is handled by the `validateEntityAccess` method. The supported `CommentEntityType` values are: * `task`: Checks for `TaskItem` first, then `Task`. * `policy`: Checks for `Policy`. * `vendor`: Checks for `Vendor`. Includes logging if a vendor exists in a different organization. * `risk`: Checks for `Risk`. Sources: [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L40-L124) ### Creating a Comment The `createComment` method handles the creation of new comments, including optional attachments and user mention notifications. ### Validate Entity Access The system first calls `validateEntityAccess` to ensure the `entityId` and `entityType` are valid and accessible within the `organizationId`. ### Verify Member It retrieves the `Member` record for the `userId` within the `organizationId` to confirm the user is an active member. ### Create Comment and Attachments in Transaction A database transaction is used to ensure atomicity. 1. The comment record is created in the database. 2. If `createCommentDto.attachments` are provided, each attachment is uploaded via `AttachmentsService.uploadAttachment` and associated with the new comment. ### Notify Mentioned Users After the comment is successfully created, the `extractMentionedUserIds` utility parses the comment content for user mentions. If any users are mentioned, `CommentMentionNotifierService.notifyMentionedUsers` is called asynchronously to send notifications. Sources: [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L162-L253) ```mermaid sequenceDiagram participant Client participant CommentsController participant CommentsService participant AttachmentsService participant CommentMentionNotifierService participant Database Client->>CommentsController: POST /comments (CreateCommentDto) CommentsController->>CommentsService: createComment(orgId, userId, dto) CommentsService->>CommentsService: validateEntityAccess(orgId, dto.entityId, dto.entityType) CommentsService->>Database: Find Member (userId, orgId) alt Member not found CommentsService-->>CommentsController: BadRequestException CommentsController-->>Client: 400 Bad Request else Member found CommentsService->>Database: Begin Transaction CommentsService->>Database: Create Comment opt Attachments present loop For each attachment CommentsService->>AttachmentsService: uploadAttachment(orgId, commentId, type, attachmentDto, userId) AttachmentsService-->>CommentsService: AttachmentResponseDto end end CommentsService->>Database: Commit Transaction CommentsService->>CommentsService: extractMentionedUserIds(content) opt Users mentioned CommentsService->>CommentMentionNotifierService: notifyMentionedUsers(notificationData) end CommentsService-->>CommentsController: CommentResponseDto CommentsController-->>Client: 201 Created (CommentResponseDto) end ``` ### Retrieving Comments The `getComments` method fetches all comments for a given entity. 1. It first validates entity access using `validateEntityAccess`. 2. It queries the database for comments matching the `organizationId`, `entityId`, and `entityType`, ordering them by creation date (descending). 3. For each comment, it retrieves attachment metadata using `AttachmentsService.getAttachmentMetadata`. 4. The results are mapped to `CommentResponseDto` objects, including author details and attachment metadata. Sources: [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L127-L160) ### Updating a Comment The `updateComment` method allows modifying the content of an existing comment. 1. It retrieves the existing comment and verifies that the `userId` is the author of the comment. 2. The comment's `content` is updated in the database. 3. Existing attachments are retrieved using `AttachmentsService.getAttachments`. 4. It compares the newly mentioned users with previously mentioned users in the comment content. Only newly mentioned users are notified via `CommentMentionNotifierService`. Sources: [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L256-L338) ### Deleting a Comment The `deleteComment` method removes a comment and its associated attachments. 1. It retrieves the existing comment and verifies that the `userId` is the author of the comment. 2. A database transaction is initiated. 3. All attachments linked to the comment are retrieved. 4. Each attachment is deleted from storage via `AttachmentsService.deleteAttachment`. 5. Finally, the comment record is deleted from the database. Sources: [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L341-L397) ## Mention Notification The system includes functionality to notify users who are mentioned in a comment. The `extractMentionedUserIds` utility function parses the comment content (expected to be JSON) to find user IDs marked as 'mention' nodes. When a comment is created or updated, if new mentions are detected, the `CommentMentionNotifierService` is used to send notifications to the mentioned users. This process is fire-and-forget to avoid blocking comment operations. Sources: [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L10-L33), [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L225-L242), [apps/api/src/comments/comments.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.service.ts#L310-L327) ## Authentication and Authorization The `CommentsController` uses `HybridAuthGuard` to support both JWT (session-based) and API key authentication. The `@AuthContext()` decorator provides an `AuthContextType` object, which indicates whether the request originated from an API key (`isApiKey`) and provides the `userId`. When using API key authentication, the `userId` must be explicitly provided in the request body (`CreateCommentDto`, `UpdateCommentDto`, `DeleteCommentDto`). For JWT authentication, the `userId` is extracted directly from the authenticated session. This ensures that the correct user context is always available for authorization checks (e.g., verifying comment authorship). Sources: [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts#L26-L30), [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts#L86-L101), [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts#L130-L145), [apps/api/src/comments/comments.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.controller.ts#L191-L206) ## Module Structure The `CommentsModule` integrates all necessary components for the Comments System. ```typescript @Module({ imports: [AuthModule, AttachmentsModule], controllers: [CommentsController], providers: [CommentsService, CommentMentionNotifierService, NovuService], exports: [CommentsService], }) export class CommentsModule {} ``` * **`imports`**: * `AuthModule`: Provides authentication-related services and guards, including `HybridAuthGuard`. * `AttachmentsModule`: Provides `AttachmentsService` for handling file uploads and management. * **`controllers`**: Registers `CommentsController` to handle API routes. * **`providers`**: Registers `CommentsService`, `CommentMentionNotifierService`, and `NovuService` as injectable services. * **`exports`**: Makes `CommentsService` available for injection into other modules if needed. Sources: [apps/api/src/comments/comments.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/comments/comments.module.ts#L6-L12) --- ## Technical docs: Operations Endpoints URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-5/operations-endpoints
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/browserbase/browserbase.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/browserbase.service.ts) - [apps/api/src/browserbase/browserbase.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/browserbase.controller.ts) - [apps/api/src/device-agent/schemas/device-agent-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/device-agent/schemas/device-agent-operations.ts) - [apps/api/src/browserbase/dto/browserbase.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/dto/browserbase.dto.ts) - [apps/api/src/device-agent/device-agent.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/device-agent/device-agent.controller.ts) - [apps/api/src/device-agent/device-agent.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/device-agent/device-agent.service.ts) - [apps/api/src/health/health.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/health/health.controller.ts) - [apps/api/src/health/health.module.ts](https://github.com/blade4s/comp/blob/main/apps/api/src/health/health.module.ts) - [apps/api/src/device-agent/scripts/common.ts](https://github.com/blade47/comp/blob/main/apps/api/src/device-agent/scripts/common.ts) - [apps/api/src/devices/devices.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/devices/devices.controller.ts) - [apps/api/src/devices/devices.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/devices/devices.service.ts) - [apps/api/src/lib/fleet.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/lib/fleet.service.ts)
This document outlines the various operational endpoints exposed by the API, covering browser automation, device agent management, device listing, and health checks. These endpoints facilitate interaction with external services like Browserbase HQ and internal device management systems, providing functionalities ranging from automated browser tasks to device monitoring and agent distribution. The API is structured using NestJS controllers and services, with authentication handled by `HybridAuthGuard` and organization context managed via `X-Organization-Id` headers or API keys. ## Browser Automation Endpoints The Browser Automation endpoints provide a comprehensive interface for managing and executing automated browser tasks using Browserbase HQ. This includes managing organization-specific browser contexts, controlling browser sessions, performing navigation, and handling the lifecycle of browser automations and their execution runs. ### Architecture The `BrowserbaseController` exposes the API endpoints, which delegate business logic to the `BrowserbaseService`. The service interacts with the `@browserbasehq/sdk` and `@browserbasehq/stagehand` libraries, as well as an S3 client for screenshot storage and a Prisma client (`@trycompai/db`) for persistence of automation configurations and run history. A Browserbase context represents a persistent browser environment for an organization. It allows sessions to share cookies, local storage, and other browser data, enabling consistent authentication and state across multiple automation runs. ### API Endpoints The `BrowserbaseController` (`/browserbase`) provides the following endpoints: | Method | Path | Summary | Description | DTOs (Request/Response) | |---|----------------------------------------|--------------------------------------------------|--------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | `/browserbase/org-context` | `POST` | Get or create organization browser context | Gets the existing browser context for the org or creates a new one. | Request: `{}` (Implicitly uses `X-Organization-Id` header)
Response: `ContextResponseDto` --- ## Technical docs: DELETE Delete a comment URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/comments/commentscontroller-deletecomment ## Parameters ## Request Body Delete comment request body ## Responses ## Try It --- ## Technical docs: GET Get all context entries URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/context/getallcontext ## Parameters ## Responses ## Try It --- ## Technical docs: UI Surfaces URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-6/ui-surfaces
Relevant source files The following files were used as context for generating this wiki page: - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [apps/api/src/email/components/footer.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/footer.tsx) - [apps/api/src/email/components/logo.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/logo.tsx) - [apps/api/src/email/templates/access-granted.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/access-granted.tsx) - [apps/api/src/email/templates/task-item-assigned.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-item-assigned.tsx)
The "UI Surfaces" within the Comp AI project primarily refer to the email templates and reusable components designed for transactional communications. These surfaces are built using React for Email (`@react-email/components`) and styled with Tailwind CSS, enabling a consistent and branded user experience across various automated email notifications. They are located within the `apps/api/src/email` directory, indicating their role in the API application's communication layer. These UI surfaces serve to inform users about critical events, such as granting access to compliance documentation or assigning tasks. By leveraging a component-based approach, the system ensures maintainability, reusability, and a standardized look and feel for all outgoing emails. ## Email Components The email UI surfaces utilize a set of foundational React components to construct the email layouts. These components encapsulate common visual elements and styling, promoting consistency across different email templates. ### Logo Component The `Logo` component is a simple, reusable element responsible for displaying the Comp AI brand logo at the top of email communications. It uses an `Img` tag from `@react-email/components` to embed the logo image. ```tsx import { Img, Section } from '@react-email/components'; export function Logo() { return (
Comp AI
); } ``` Sources: [apps/api/src/email/components/logo.tsx:1-14](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/logo.tsx#L1-L14) ### Footer Component The `Footer` component provides standard legal and branding information at the bottom of email templates. It includes a link to the Comp AI website and the company's physical address. ```tsx import { Hr, Link, Section, Text } from '@react-email/components'; export function Footer() { return (

AI that handles compliance for you -{' '} Comp AI. Comp AI | 2261 Market Street, San Francisco, CA 94114
); } ``` Sources: [apps/api/src/email/components/footer.tsx:1-18](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/footer.tsx#L1-L18) ## Email Templates The project includes specific email templates for different transactional purposes, each designed to convey particular information to the recipient. These templates integrate the reusable `Logo` and `Footer` components. ### Access Granted Email The `AccessGrantedEmail` template is used to notify a user that they have been granted access to an organization's policy documentation. It provides details about the access, including the organization name, expiration date, and a direct link to view the documents. #### Props The `AccessGrantedEmail` component expects the following properties: | Prop Name | Type | Description | | :--------------- | :------- | :---------------------------------------------- | | `toName` | `string` | The name of the recipient. | | `organizationName` | `string` | The name of the organization. | | `expiresAt` | `Date` | The date when the access will expire. | | `portalUrl` | `string` | The URL to the portal where documents can be viewed. | Sources: [apps/api/src/email/templates/access-granted.tsx:13-18](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/access-granted.tsx#L13-L18) ### Task Item Assigned Email The `TaskItemAssignedEmail` template is sent to a user when they are assigned a new task within an organization. It includes information about the task, who assigned it, and a direct link to the task. It also provides an option for the user to manage their email preferences. #### Props The `TaskItemAssignedEmail` component expects the following properties: | Prop Name | Type | Description | | :--------------- | :------- | :---------------------------------------------- | | `toName` | `string` | The name of the recipient. | | `toEmail` | `string` | The email address of the recipient, used for unsubscribe links. | | `taskTitle` | `string` | The title of the assigned task. | | `assignedByName` | `string` | The name of the user who assigned the task. | | `organizationName` | `string` | The name of the organization where the task was assigned. | | `taskUrl` | `string` | The URL to view the assigned task. | The template also utilizes the `getUnsubscribeUrl` function from the `@trycompai/email` package to generate a dynamic unsubscribe link. Sources: [apps/api/src/email/templates/task-item-assigned.tsx:17-24](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-item-assigned.tsx#L17-L24), [apps/api/src/email/templates/task-item-assigned.tsx:26](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-item-assigned.tsx#L26) ## Architecture and Design The email UI surfaces are built upon a modern web development stack tailored for email rendering: * **@react-email/components**: This library allows developers to write email templates using React, providing a familiar component-based approach and abstracting away the complexities of cross-client email compatibility. * **Tailwind CSS**: Integrated via the `Tailwind` component from `@react-email/components`, it enables utility-first styling directly within the React components, ensuring responsive and consistent designs. * **Custom Fonts**: The `Geist` font is specified for use in the emails, with `Helvetica` as a fallback, to maintain brand aesthetics. * **Monorepo Structure**: The email components and templates are part of the `apps/api` application, suggesting they are rendered server-side as part of API-triggered workflows. ### Email Template Composition The following diagram illustrates how the email templates are composed from shared components. Sources: [apps/api/src/email/templates/access-granted.tsx:1-18](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/access-granted.tsx#L1-L18), [apps/api/src/email/templates/task-item-assigned.tsx:1-24](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-item-assigned.tsx#L1-L24), [apps/api/src/email/components/logo.tsx:1-14](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/logo.tsx#L1-L14), [apps/api/src/email/components/footer.tsx:1-18](https://github.com/blade47/comp/blob/main/apps/api/src/email/components/footer.tsx#L1-L18) ### Email Rendering Flow The general flow for rendering and preparing an email for dispatch involves several steps, from data provision to final HTML generation. Sources: [apps/api/src/email/templates/access-granted.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/access-granted.tsx), [apps/api/src/email/templates/task-item-assigned.tsx](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-item-assigned.tsx) The `TaskItemAssignedEmail` template imports `getUnsubscribeUrl` from `@trycompai/email`. This indicates the presence of a dedicated package for email-related utilities, which likely handles common email functionalities beyond just rendering, such as generating unsubscribe links. Sources: [apps/api/src/email/templates/task-item-assigned.tsx:10](https://github.com/blade47/comp/blob/main/apps/api/src/email/templates/task-item-assigned.tsx#L10) --- ## Technical docs: GET Get context entry by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/context/getcontextbyid ## Parameters ## Responses ## Try It --- ## Technical docs: Deployment Guide URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-7/deployment-guide
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/buildspec.yml](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml) - [apps/api/docker-compose.yml](https://github.com/blade47/comp/blob/main/apps/api/docker-compose.yml) - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [apps/api/src/config/load-env.ts](https://github.com/blade47/comp/blob/main/apps/api/src/config/load-env.ts)
This guide provides comprehensive instructions for deploying and running the Comp AI platform, covering both cloud-based CI/CD processes for the API and local development setups. It details the steps for building, packaging, and deploying the API service using AWS CodeBuild, as well as configuring a local development environment with Docker Compose, database setup, and environment variable management. The document consolidates information from various configuration and setup files to offer a unified view of the deployment landscape for the Comp AI project. ## Cloud Deployment: AWS CodeBuild for API The `apps/api` service utilizes an AWS CodeBuild pipeline for its continuous integration and deployment process. This pipeline automates the building of the application, creation of Docker images, and deployment to Amazon Elastic Container Registry (ECR) and Amazon Elastic Container Service (ECS). ### CodeBuild Pipeline Overview The CodeBuild process is divided into three main phases: `pre_build`, `build`, and `post_build`, each executing a series of commands to prepare, build, and deploy the application. Sources: [apps/api/buildspec.yml:1-85](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L1-L85) ### Pre-Build Phase This phase focuses on initial setup and authentication required before the main build process begins. - **ECR Login**: Authenticates with Amazon ECR using AWS credentials to allow pushing and pulling Docker images. - **Variable Setup**: Defines `REPOSITORY_URI`, `COMMIT_HASH`, and `IMAGE_TAG` based on ECR repository URI and the Git commit hash. The `IMAGE_TAG` defaults to `latest` if no commit hash is available. - **Dependency Manager Installation**: Installs `bun`, the JavaScript runtime and package manager used across the project. Sources: [apps/api/buildspec.yml:4-12](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L4-L12) ### Build Phase The core of the pipeline, where the application is built, packaged, and a Docker image is created. #### Environment Setup and Validation Critical environment variables are set and validated to ensure the build environment is correctly configured. The build will fail if any of these required variables are not present. The following environment variables are critical for the API build and deployment. Their absence will cause the CodeBuild process to fail. | Environment Variable | Description | | :---------------------------- | :----------------------------------------------------------------------- | | `DATABASE_URL` | Connection string for the PostgreSQL database. | | `BASE_URL` | Base URL for the application. | | `BETTER_AUTH_URL` | URL for the authentication service. | | `TRUST_APP_URL` | URL for the trust application. | | `APP_AWS_BUCKET_NAME` | AWS S3 bucket name for application assets. | | `APP_AWS_ACCESS_KEY_ID` | AWS access key ID for S3 access. | | `APP_AWS_SECRET_ACCESS_KEY` | AWS secret access key for S3 access. | Other environment variables set during this phase include: - `PATH`: Updated to include Bun's binary directory. - `PGSSLMODE`: Set to `require` for PostgreSQL SSL. - `NODE_ENV`: Set to `production`. - `NEXT_TELEMETRY_DISABLED`: Set to `1` to disable Next.js telemetry. - `UV_THREADPOOL_SIZE`: Set to `36`. - `NODE_OPTIONS`: Set to `--max-old-space-size=65536` to increase Node.js memory limit. Sources: [apps/api/buildspec.yml:15-30](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L15-L30) #### Application Build Process 1. **Dependency Installation**: Installs only the API workspace dependencies using `bun install --filter=@comp/api`. 2. **Workspace Package Build**: Builds shared packages (`packages/db`, `packages/integration-platform`) that the API depends on. 3. **NestJS Application Build**: Navigates to `apps/api` and executes `bun run build` to compile the NestJS application. 4. **Build Output Handling**: Copies the compiled API application files (`dist/`) into a temporary `../docker-build` directory, handling potential variations in the output structure (`dist/apps/api/src` or `dist/src`). 5. **Prisma Schema Copy**: Copies the `prisma` directory to the Docker build context. 6. **Node Modules & Workspace Symlink Resolution**: * Copies the root `node_modules` directory. * Removes workspace symlinks for `@trycompai/utils`, `@trycompai/db`, and `@comp/integration-platform`. * Replaces these symlinks with the actual built output and `package.json` files from their respective `packages/` directories. 7. **Dockerfile Preparation**: Copies the `Dockerfile` to the Docker build context and modifies `package.json` to remove the workspace dependency for `@comp/integration-platform` (as it's handled manually). 8. **Docker Image Build**: Constructs the Docker image using the prepared `../docker-build` context and tags it with the ECR repository URI and the generated `IMAGE_TAG`. It also tags the image with `latest`. Sources: [apps/api/buildspec.yml:33-77](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L33-L77) ### Post-Build Phase This phase handles the final deployment steps after the Docker image is successfully built. - **ECR Push**: Pushes the newly built Docker image (both tagged and `latest`) to Amazon ECR. - **ECS Service Update**: Triggers a forced new deployment for the specified ECS service, ensuring the ECS cluster pulls the latest image. - **Image Definitions**: Generates an `imagedefinitions.json` file, which is used by AWS CodePipeline or other services to specify the image URI for the deployed container. Sources: [apps/api/buildspec.yml:80-85](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L80-L85) ### Caching and Artifacts The CodeBuild configuration includes caching paths for `node_modules` and Bun's install cache to speed up subsequent builds. The `imagedefinitions.json` file is specified as a build artifact. Sources: [apps/api/buildspec.yml:87-95](https://github.com/blade47/comp/blob/main/apps/api/buildspec.yml#L87-L95) ## Local Development & Testing Setting up the Comp AI project for local development involves several steps, including installing prerequisites, configuring environment variables, and initializing the database. ### Prerequisites To run Comp AI locally, ensure you have the following installed: - **Node.js**: Version `>=20.x` - **Bun**: Version `>=1.1.36` - **Postgres**: Version `>=15.x` Sources: [README.md:94-98](https://github.com/blade47/comp/blob/main/README.md#L94-L98) ### Initial Setup ### Clone the Repository Clone the Comp AI repository from GitHub. ```sh git clone https://github.com/trycompai/comp.git cd comp ``` ### Install Dependencies Install all project dependencies using Bun. ```sh bun install ``` ### Prepare Environment Files Copy the example environment files for the `app`, `portal`, and `db` workspaces. ```sh cp apps/app/.env.example apps/app/.env cp apps/portal/.env.example apps/portal/.env cp packages/db/.env.example packages/db/.env ``` ```cmd copy apps\app\.env.example apps\app\.env copy apps\portal\.env.example apps\portal\.env copy packages\db\.env.example packages\db\.env ``` ```powershell Copy-Item apps\app\.env.example -Destination apps\app\.env Copy-Item apps\portal\.env.example -Destination apps\portal\.env Copy-Item packages\db\.env.example -Destination packages\db\.env ``` ### Generate Prisma Types Navigate to each application directory and generate the Prisma client. ```sh cd apps/app bun run db:generate cd ../portal bun run db:generate cd ../api bun run db:generate ``` Sources: [README.md:104-142](https://github.com/blade47/comp/blob/main/README.md#L104-L142) ### Environment Variables After copying the `.env.example` files, you must fill them with your credentials. Additionally, ensure the following variables are present in `comp/apps/app/.env`: | Variable | Description | Example Value | | :------------------------ | :------------------------------------------------------------------------------------------------------ | :------------------------------------------- | | `AUTH_SECRET` | Secret key for authentication. Generate using `openssl rand -base64 32`. | `your_auth_secret` | | `DATABASE_URL` | PostgreSQL connection string. | `postgresql://user:password@host:port/database` | | `RESEND_API_KEY` | API key for Resend email service. | `re_your_resend_api_key` | | `NEXT_PUBLIC_PORTAL_URL` | Public URL for the portal application. | `http://localhost:3002` | | `REVALIDATION_SECRET` | Secret key for revalidation. Generate using `openssl rand -base64 32`. | `your_revalidation_secret` | Some environment variables might not load correctly from `.env` files. In such cases, you may need to hard-code their values directly into the relevant source files as indicated in the "Cloud & Auth Configuration" section. Sources: [README.md:144-166](https://github.com/blade47/comp/blob/main/README.md#L144-L166) ### Cloud & Authentication Configuration Several external services require specific configuration for local development. #### Trigger.dev 1. Create an account on [https://cloud.trigger.dev](https://cloud.trigger.dev). 2. Create a project and copy its Project ID. 3. Update `comp/apps/app/trigger.config.ts` with your Project ID: ```typescript project: 'proj_****az***ywb**ob*'; ``` Sources: [README.md:170-176](https://github.com/blade47/comp/blob/main/README.md#L170-L176) #### Google OAuth 1. Go to [Google Cloud OAuth Console](https://console.cloud.google.com/auth/clients). 2. Create an OAuth client of type "Web Application". 3. Add the following Authorized Redirect URIs: - `http://localhost` - `http://localhost:3000` - `http://localhost:3002` - `http://localhost:3000/api/auth/callback/google` - `http://localhost:3002/api/auth/callback/google` - `http://localhost:3000/auth` - `http://localhost:3002/auth` 4. Copy the `GOOGLE_ID` and `GOOGLE_SECRET` and add them to your `.env` files. 5. If environment variables are not recognized, hard-code them in `comp/apps/portal/src/app/lib/auth.ts`. Sources: [README.md:178-197](https://github.com/blade47/comp/blob/main/README.md#L178-L197) #### Redis (Upstash) 1. Go to [https://console.upstash.com](https://console.upstash.com). 2. Create a Redis database. 3. Copy the Redis URL and TOKEN. 4. Add them to your `.env` file. 5. If environment variables are not recognized, hard-code them in `comp/packages/kv/src/index.ts`. Sources: [README.md:199-207](https://github.com/blade47/comp/blob/main/README.md#L199-L207) ### Database Setup The project uses PostgreSQL, managed with Prisma. Docker is used to run the database locally. ### Start Database Container Navigate to the `packages/db` directory and start the PostgreSQL container. ```sh cd packages/db bun docker:up ``` Default credentials: - Database name: `comp` - Username: `postgres` - Password: `postgres` ### Change Default Password (Optional) To change the default `postgres` user password: ```sql ALTER USER postgres WITH PASSWORD 'new_password'; ``` ### Fix Function Definition Error (If encountered) If you see a "No function matches the given name and argument types..." error, run the following fix: ```sh psql "postgresql://postgres:@localhost:5432/comp" -f ./packages/db/prisma/functionDefinition.sql ``` ### Apply Schema and Seed Data Generate the Prisma client, push the schema to the database, and optionally seed with initial data. ```sh bun db:generate # Generate Prisma client bun db:push # Push the schema to the database bun db:seed # Optional: Seed the database with initial data ``` - `bun db:studio`: Open Prisma Studio to view/edit data. - `bun db:migrate`: Run database migrations. - `bun docker:down`: Stop the database container. - `bun docker:clean`: Remove the database container and volume. Sources: [README.md:211-256](https://github.com/blade47/comp/blob/main/README.md#L211-L256) ### Starting Development Servers Once all configurations are complete, you can start the development servers. ```sh bun run dev ``` Alternatively, if you have Turbo installed globally, you can use the Turbo repo script: ```sh turbo dev ``` Sources: [README.md:258-267](https://github.com/blade47/comp/blob/main/README.md#L258-L267) ### Docker Compose for Local API Testing The `apps/api/docker-compose.yml` file is provided **for local testing only**. It defines a service to build and run the API in a Docker container. The `api` service is configured as follows: | Configuration Item | Value / Description Logo

Comp AI

The open-source compliance platform.
Learn more »

Discord · Website · Documentation · Issues · Roadmap

Product Hunt Github Stars License Commits-per-month

## About ### AI that handles compliance for you in hours. Comp AI is the fastest way to get compliant with frameworks like SOC 2, ISO 27001, HIPAA and GDPR. Comp AI automates evidence collection, policy management, and control implementation while keeping you in control of your data and infrastructure. ## Recognition #### [ProductHunt](https://www.producthunt.com/posts/comp-ai) Comp AI - The open source Vanta & Drata alternative | Product Hunt #### [Vercel](https://vercel.com/) Vercel OSS Program ### Built With - [Next.js](https://nextjs.org/?ref=trycomp.ai) - [Trigger.dev](https://trigger.dev/?ref=trycomp.ai) - [Prisma](https://prisma.io/?ref=trycomp.ai) - [Tailwind CSS](https://tailwindcss.com/?ref=trycomp.ai) - [Upstash](https://upstash.com/?ref=trycomp.ai) - [Vercel](https://vercel.com/?ref=trycomp.ai) ## Contact us Contact our founders at hello@trycomp.ai to learn more about how we can help you achieve compliance. ## Stay Up-to-Date Get access to the cloud hosted version of [Comp AI](https://trycomp.ai). ## Getting Started To get a local copy up and running, please follow these simple steps. ### Prerequisites Here is what you need to be able to run Comp AI. - Node.js (Version: >=20.x) - Bun (Version: >=1.1.36) - Postgres (Version: >=15.x) ## Development To get the project working locally with all integrations, follow these extended development steps ### Setup ## Add environment variables and fill them out with your credentials ```sh cp apps/app/.env.example apps/app/.env cp apps/portal/.env.example apps/portal/.env cp packages/db/.env.example packages/db/.env ``` ## Get code running locally 1. Clone the repo ```sh git clone https://github.com/trycompai/comp.git ``` 2. Navigate to the project directory ```sh cd comp ``` 3. Install dependencies using Bun ```sh bun install ``` 4. Get Database Running ```sh cd packages/db bun run docker:up # Spin up docker container bun run db:migrate # Run migrations ``` 5. Generate Prisma Types for each app ```sh cd apps/app bun run db:generate cd ../ ``` --- ## Technical docs: POST Create a new context entry URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/context/createcontext ## Parameters ## Request Body Data for creating a new context entry. ## Responses ## Try It --- ## Technical docs: Third-party Services URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-7/third-party-services
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/browserbase/browserbase.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/browserbase.service.ts) - [apps/api/src/assistant-chat/upstash-redis.client.ts](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/upstash-redis.client.ts) - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [apps/api/src/email/resend.ts](https://github.com/blade47/comp/blob/main/apps/api/src/email/resend.ts) - [apps/api/src/config/aws.config.ts](https://github.com/blade47/comp/blob/main/apps/api/src/config/aws.config.ts)
The project leverages several third-party services to provide core functionalities such as browser automation, email communication, caching, and cloud storage. These integrations enhance the application's capabilities, allowing for complex operations like automated web interactions and efficient data management. This document outlines the key third-party services integrated into the application, detailing their purpose, configuration, and how they are utilized within the codebase. ## Browser Automation with Browserbase The `BrowserbaseService` (`apps/api/src/browserbase/browserbase.service.ts`) is responsible for orchestrating browser automation tasks using the Browserbase SDK and Stagehand. This service enables functionalities like creating and managing browser sessions, navigating to URLs, checking login status, and executing complex automation instructions. It also integrates with AWS S3 for storing screenshots generated during automation runs. ### Key Components and Functionality * **Browserbase SDK**: Used for creating and managing browser contexts and sessions. * **Stagehand**: An AI agent framework that interacts with the browser to execute instructions and extract data. * **Organization Context Management**: The service manages `BrowserbaseContext` records in the database, ensuring each organization has a persistent browser context for automations. The `getOrCreateOrgContext` method handles the creation and retrieval of these contexts, including a retry mechanism for concurrent creation attempts. * **Session Management**: `createSessionWithContext` establishes a new browser session linked to an organization's context, providing a `liveViewUrl` for real-time monitoring. `closeSession` is used to terminate sessions. * **Browser Actions**: * `navigateToUrl`: Directs a browser session to a specified URL. * `checkLoginStatus`: Verifies if a user is logged into a website within a session by extracting page elements. * `executeAutomation`: The core method that uses Stagehand to perform a sequence of actions based on given instructions and a target URL. It includes logic for checking authentication status and capturing screenshots. * **Automation CRUD**: Provides methods for creating, retrieving, updating, and deleting browser automation definitions stored in the database (`db.browserAutomation`). * **Automation Execution**: * `startAutomationWithLiveView`: Initiates an automation run, creates a live session, and returns a URL for live monitoring. * `executeAutomationOnSession`: Executes a predefined automation within an existing live session. * `runBrowserAutomation`: Executes an automation in a non-live session, handling session creation and closure internally. * **Screenshot Management**: Integrates with AWS S3 to upload and retrieve presigned URLs for screenshots captured during automation runs. ### Browserbase Context Creation Flow The `getOrCreateOrgContext` method ensures that a unique Browserbase context exists for each organization, handling potential race conditions during creation. Sources: [apps/api/src/browserbase/browserbase.service.ts:40-104](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/browserbase.service.ts#L40-L104) ### Browser Automation Execution Flow The `runBrowserAutomation` method orchestrates the full lifecycle of a browser automation, from session creation to execution and cleanup. ```mermaid sequenceDiagram participant API as API Service participant DB as Database participant BB as Browserbase SDK participant Stagehand as Stagehand Agent participant S3 as AWS S3 API->>DB: Get Browser Automation details API->>DB: Get Organization Context alt No Org Context API-->>API: Return needsReauth error end API->>DB: Create BrowserAutomationRun record (status: running) API->>BB: Create Session with Context (createSessionWithContext) BB-->>API: sessionId, liveViewUrl API->>Stagehand: Create Stagehand instance (createStagehand) Stagehand->>Stagehand: Initialize API->>Stagehand: Ensure Active Page (ensureActivePage) API->>Stagehand: Navigate to targetUrl (page.goto) API->>Stagehand: Check for login status (stagehand.extract) alt Not Logged In API-->>API: Return needsReauth error end API->>Stagehand: Execute automation instruction (stagehand.agent().execute) Stagehand-->>API: Automation result API->>Stagehand: Capture screenshot (page.screenshot) API->>S3: Upload screenshot (uploadScreenshot) S3-->>API: Screenshot key API->>DB: Update BrowserAutomationRun (status: completed, screenshotUrl, evaluation) API->>BB: Close Session (closeSession) API->>Stagehand: Safe Close Stagehand (safeCloseStagehand) API-->>API: Return success result alt Error during execution API->>DB: Update BrowserAutomationRun (status: failed, error) API-->>API: Return error result end ``` Sources: [apps/api/src/browserbase/browserbase.service.ts:167-393](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/browserbase.service.ts#L167-L393) ## Email Service with Resend The application uses Resend for sending emails. The `resend.ts` file (`apps/api/src/email/resend.ts`) provides a utility function `sendEmail` to abstract the email sending process. ### Key Components and Functionality * **Resend Client**: Initialized with `RESEND_API_KEY` from environment variables. If the API key is missing, the client is `null`, and `sendEmail` will throw an error. * **`sendEmail` Function**: * Takes parameters like `to`, `subject`, `react` (for React-based email templates), `marketing`, `system`, `test`, `cc`, `scheduledAt`, and `attachments`. * Dynamically determines the `from` and `to` addresses based on `marketing`, `system`, or `test` flags and corresponding environment variables (`RESEND_FROM_MARKETING`, `RESEND_FROM_SYSTEM`, `RESEND_FROM_DEFAULT`, `RESEND_TO_TEST`). * Supports attachments by converting `EmailAttachment` objects into the format expected by the Resend SDK. * Includes error handling for API calls and missing environment variables. ### Email Sending Logic Sources: [apps/api/src/email/resend.ts:1-74](https://github.com/blade47/comp/blob/main/apps/api/src/email/resend.ts#L1-L74) ## Caching and Key-Value Store with Upstash Redis The `upstash-redis.client.ts` file (`apps/api/src/assistant-chat/upstash-redis.client.ts`) provides a client for a key-value store, primarily used for caching and managing state, particularly for assistant chat history. ### Key Components and Functionality * **Upstash Redis**: A serverless Redis solution used for persistent key-value storage. * **`InMemoryRedis`**: A local, in-memory implementation of a Redis-like client. This is used as a fallback when Upstash Redis configuration is not provided, making the application runnable without external Redis. It supports `get`, `set`, and `del` operations with optional expiration. * **`assistantChatRedisClient`**: This is the exported client instance. It is conditionally initialized: * If `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` environment variables are present, it uses the `@upstash/redis` SDK. * Otherwise, it defaults to the `InMemoryRedis` instance. * **Purpose**: Used by services like `AssistantChatService` to save and clear chat history. ### Redis Client Initialization Flow Sources: [apps/api/src/assistant-chat/upstash-redis.client.ts:1-35](https://github.com/blade47/comp/blob/main/apps/api/src/assistant-chat/upstash-redis.client.ts#L1-L35) ## Cloud Storage with AWS S3 AWS S3 is utilized for storing large binary objects, specifically screenshots generated during browser automation runs. The `BrowserbaseService` interacts with S3 for this purpose, and the `aws.config.ts` file (`apps/api/src/config/aws.config.ts`) defines the configuration for AWS services. ### Key Components and Functionality * **`S3Client`**: An instance of the AWS SDK S3 client, configured with region and credentials. * **`bucketName`**: Configured via `APP_AWS_BUCKET_NAME` environment variable, defaulting to `comp-attachments`. * **`uploadScreenshot`**: Uploads a base64 encoded screenshot to a specified S3 key. * **`getPresignedUrl`**: Generates a temporary, time-limited URL for accessing private S3 objects, ensuring secure access to screenshots. * **`awsConfig`**: A configuration object (`apps/api/src/config/aws.config.ts`) that registers AWS settings, including `region`, `accessKeyId`, `secretAccessKey`, and `bucketName`. It uses Zod for schema validation of these environment variables at application startup. ### AWS Configuration The `awsConfig` is registered using `@nestjs/config`'s `registerAs` function, ensuring that AWS settings are validated and available throughout the application. ```typescript // apps/api/src/config/aws.config.ts const awsConfigSchema = z.object({ region: z.string().default('us-east-1'), accessKeyId: z.string().min(1, 'AWS_ACCESS_KEY_ID is required'), secretAccessKey: z.string().min(1, 'AWS_SECRET_ACCESS_KEY is required'), bucketName: z.string().min(1, 'AWS_BUCKET_NAME is required'), endpoint: z.string().optional(), }); export const awsConfig = registerAs('aws', (): AwsConfig => { const config = { region: process.env.APP_AWS_REGION || 'us-east-1', accessKeyId: process.env.APP_AWS_ACCESS_KEY_ID || '', secretAccessKey: process.env.APP_AWS_SECRET_ACCESS_KEY || '', bucketName: process.env.APP_AWS_BUCKET_NAME || '', endpoint: process.env.APP_AWS_ENDPOINT || '', }; const result = awsConfigSchema.safeParse(config); if (!result.success) { throw new Error( `AWS configuration validation failed: ${result.error.issues .map((e) => `${e.path.join('.')}: ${e.message}`) .join(', ')}`, ); } return result.data; }); ``` Sources: [apps/api/src/browserbase/browserbase.service.ts:16-37](https://github.com/blade47/comp/blob/main/apps/api/src/browserbase/browserbase.service.ts#L16-L37), [apps/api/src/config/aws.config.ts:1-29](https://github.com/blade47/comp/blob/main/apps/api/src/config/aws.config.ts#L1-L29) ## Other Third-Party Integrations The project's `README.md` (`README.md`) also highlights several other key technologies and platforms that contribute to its overall architecture and functionality. * **Next.js**: A React framework for building web applications. * **Trigger.dev**: Likely used for background jobs, workflows, or event-driven tasks. The `README.md` mentions setting up a Trigger.dev project ID. * **Prisma**: An ORM (Object-Relational Mapper) used for database access and management. * **Tailwind CSS**: A utility-first CSS framework for styling user interfaces. * **Vercel**: A platform for frontend developers, used for deployment and hosting. These integrations form the foundation of the application, enabling a robust and scalable solution. Sources: [README.md:60-65](https://github.com/blade47/comp/blob/main/README.md#L60-L65), [README.md:162-165](https://github.com/blade47/comp/blob/main/README.md#L162-L165) --- ## Technical docs: Release Process URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-7/release-process
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/package.json](https://github.com/blade47/comp/blob/main/apps/api/package.json) - [README.md](https://github.com/blade47/comp/blob/main/README.md) - [.syncpackrc.json](https://github.com/blade47/comp/blob/main/.syncpackrc.json)
The release process for the `comp` project encompasses automated package publishing, rigorous dependency management, and defined build and deployment strategies. This ensures consistency across internal packages, simplifies the integration of external dependencies, and provides a structured approach to delivering the application and its components. This document outlines the mechanisms in place for managing releases, from internal package versioning to deployment considerations. ## Automated Package Publishing The project utilizes `semantic-release` to automate the publishing of internal packages to npm. This process is triggered upon merging pull requests into the `release` branch, ensuring that new versions are released consistently and follow semantic versioning principles based on conventional commits. ### Published Packages The following internal packages are automatically published: | Package Name | Description | | :----------- | :---------- | | `@comp/db` | Database utilities with Prisma client | | `@comp/email` | Email templates and components | | `@comp/kv` | Key-value store utilities using Upstash Redis | | `@comp/ui` | UI component library with Tailwind CSS | Sources: [README.md:166-169](https://github.com/blade47/comp/blob/main/README.md#L166-L169) ### Publishing Workflow The publishing workflow is designed to be fully automated once changes are merged into the `release` branch. ### Setup NPM Token To enable `semantic-release` to publish packages, an npm token must be configured as a GitHub repository secret named `NPM_TOKEN`. ### Trigger Release Create and merge pull requests into the `release` branch. `semantic-release` will automatically detect conventional commits and bump versions accordingly. Sources: [README.md:173-174](https://github.com/blade47/comp/blob/main/README.md#L173-L174) ### Local Development and Testing Developers can build and test packages locally before they are published. ```bash # Build all packages in the monorepo bun run build # Build a specific package, e.g., @comp/ui bun run -F @comp/ui build # Test the release process without actually publishing bun run release:packages --dry-run ``` Sources: [README.md:180-185](https://github.com/blade47/comp/blob/main/README.md#L180-L185) ## Dependency Management and Consistency The project uses `syncpack` to enforce consistent dependency versions across all packages within the monorepo. This tool is configured via `.syncpackrc.json` to manage internal package references, ensure uniform versions for critical external dependencies, and prevent the inclusion of forbidden modules. ### Configuration Overview Sources: [.syncpackrc.json](https://github.com/blade47/comp/blob/main/.syncpackrc.json) ### Key Consistency Rules All internal `@comp` packages are configured to use exact `workspace:*` versions. This ensures that all parts of the monorepo reference the latest local version of internal dependencies. **`semverGroups`**: This group specifically targets internal packages, ensuring they use `workspace:*` for their version ranges. | Label | Packages | Dependencies | Range | | :---- | :------- | :----------- | :---- | | Use exact versions for internal packages | `@comp/**` | `@comp/**` | `workspace:*` | **`versionGroups`**: These groups ensure that critical external dependencies maintain consistent versions across all packages in the monorepo. | Label | Dependencies | | :---- | :----------- | | Ensure React is consistent | `react`, `react-dom`, `@types/react`, `@types/react-dom`, `react-is` | | Ensure Next.js is consistent | `next` | | Ensure TypeScript is consistent | `typescript` | | Ensure common build tools are consistent | `postcss`, `tailwindcss`, `@tailwindcss/**`, `autoprefixer` | | Ensure testing tools are consistent | `@types/node`, `prettier`, `turbo` | | Ensure ESLint is consistent | `eslint`, `eslint-config-next` | **`lintRules`**: A set of rules to forbid certain dependencies, typically Node.js built-in modules or mistakenly added packages, to maintain a clean and predictable dependency graph. | Rule | Dependencies | Message | | :--- | :----------- | :------ | | `forbiddenDependencies` | `crypto`, `buffer`, `fs`, `path`, `os`, `install`, `npm` | This is a Node.js built-in module or a mistakenly added dependency | Sources: [.syncpackrc.json](https://github.com/blade47/comp/blob/main/.syncpackrc.json) ## Deployment Considerations While detailed deployment steps for Docker and Vercel are "coming soon", the project's `package.json` files provide insights into the planned deployment strategies and build processes. ### Build and Deployment Scripts The `apps/api/package.json` defines several scripts relevant to building and deploying the API service: | Script Name | Command | Description | | :---------- | :------ | :---------- | | `prebuild` | `bun run db:generate` | Generates the Prisma client before the main build process. | | `build` | `nest build` | Compiles the NestJS application. | | `build:docker` | `bunx prisma generate && nest build` | Prepares the application for Docker by generating Prisma client and then building the NestJS app. | | `deploy:trigger-prod` | `npx trigger.dev@4.0.6 deploy` | Deploys Trigger.dev jobs to the production environment. | | `start:prod` | `node dist/main` | Starts the compiled NestJS application in production mode. | Sources: [apps/api/package.json:96-100](https://github.com/blade47/comp/blob/main/apps/api/package.json#L96-L100), [apps/api/package.json:104](https://github.com/blade47/comp/blob/main/apps/api/package.json#L104) The `README.md` indicates that detailed steps for deploying Comp AI on Docker and Vercel are currently under development and will be provided soon. Sources: [README.md:154-157](https://github.com/blade47/comp/blob/main/README.md#L154-L157) --- ## Technical docs: PATCH Update a context entry URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/context/updatecontext ## Parameters ## Request Body Data for updating the context entry. ## Responses ## Try It --- ## Technical docs: Framework Editor URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-8/framework-editor
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/framework-editor/task-template/dto/create-task-template.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/dto/create-task-template.dto.ts) - [apps/api/src/framework-editor/task-template/schemas/task-template-operations.ts](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/schemas/task-template-operations.ts) - [apps/api/src/framework-editor/task-template/dto/update-task-template.dto.ts](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/dto/update-task-template.dto.ts) - [apps/api/src/framework-editor/task-template/task-template.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts) - [apps/api/src/framework-editor/task-template/task-template.service.ts](https://github.com/blade47/task-template/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts) - [apps/api/src/framework-editor/task-template/task-template.module.ts](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.module.ts)
The Framework Editor module provides an API for managing "Task Templates". These templates define recurring tasks with properties such as name, description, frequency, and responsible department. The module offers standard CRUD (Create, Read, Update, Delete) operations for these task templates, exposed via a RESTful API. This module is built using the NestJS framework, adhering to its architectural patterns of controllers, services, and DTOs (Data Transfer Objects) to ensure a clear separation of concerns and maintainability. It integrates with an authentication system and uses database interactions for persistence. ## Architecture Overview The Framework Editor's Task Template component follows a typical NestJS modular architecture, consisting of a module, controller, and service. This structure facilitates organized code and clear responsibilities for handling API requests, business logic, and data persistence. Sources: [apps/api/src/framework-editor/task-template/task-template.module.ts:1-7](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.module.ts#L1-L7), [apps/api/src/framework-editor/task-template/task-template.controller.ts:20-22](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L20-L22), [apps/api/src/framework-editor/task-template/task-template.service.ts:1-4](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts#L1-L4) ### TaskTemplateModule The `TaskTemplateModule` is the entry point for this part of the Framework Editor. It imports the `AuthModule` for authentication capabilities and registers `TaskTemplateController` and `TaskTemplateService`. The `TaskTemplateService` is also exported, making it available for use by other modules if needed. ```typescript @Module({ imports: [AuthModule], controllers: [TaskTemplateController], providers: [TaskTemplateService], exports: [TaskTemplateService], }) export class TaskTemplateModule {} ``` Sources: [apps/api/src/framework-editor/task-template/task-template.module.ts:1-7](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.module.ts#L1-L7) ### TaskTemplateController The `TaskTemplateController` handles incoming HTTP requests related to task templates. It defines the API endpoints, applies authentication guards (`HybridAuthGuard`), and uses DTOs for request body validation. It delegates business logic to the `TaskTemplateService`. All endpoints are secured and require an `X-Organization-Id` header. ```mermaid sequenceDiagram participant Client participant Controller as TaskTemplateController participant Service as TaskTemplateService participant DB as Database Client->>Controller: PATCH /framework-editor/task-template/:id (UpdateTaskTemplateDto) activate Controller Controller->>Controller: Validate ID (ValidateIdPipe) Controller->>Controller: Validate Body (ValidationPipe) Controller->>Service: updateById(id, updateDto) activate Service Service->>Service: findById(id) activate Service Service->>DB: Query existing template deactivate Service alt Template not found Service-->>Controller: NotFoundException Controller-->>Client: 404 Not Found else Template found Service->>DB: Update template data DB-->>Service: Updated template Service-->>Controller: Updated template end deactivate Service Controller-->>Client: 200 OK (Updated template + AuthContext) deactivate Controller ``` Sources: [apps/api/src/framework-editor/task-template/task-template.controller.ts:1-87](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L1-L87) ### TaskTemplateService The `TaskTemplateService` encapsulates the business logic for managing task templates. It interacts directly with the database via `db.frameworkEditorTaskTemplate` (presumably a Prisma client or similar ORM) to perform CRUD operations. It includes error handling and logging for database interactions and throws `NotFoundException` for non-existent resources. Sources: [apps/api/src/framework-editor/task-template/task-template.service.ts:6-96](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts#L6-L96) ## Data Structures The module defines specific Data Transfer Objects (DTOs) for creating and updating task templates, ensuring data integrity and clear API contracts. ### CreateTaskTemplateDto This DTO defines the required fields for creating a new task template. All fields are mandatory and include validation rules. ```typescript export class CreateTaskTemplateDto { name: string; // Task template name description: string; // Detailed description frequency: Frequency; // Frequency of the task (enum) department: Departments; // Department responsible (enum) } ``` The `Frequency` and `Departments` enums are imported from `@trycompai/db`, indicating predefined categories for these fields. | Field | Type | Description | Validation | Example | | :----------- | :---------- | :---------------------------------------------- | :---------------------------------------- | :------------------------ | | `name` | `string` | Task template name | `@IsString()`, `@IsNotEmpty()` | "Monthly Security Review" | | `description`| `string` | Detailed description of the task template | `@IsString()`, `@IsNotEmpty()` | "Review and update..." | | `frequency` | `Frequency` | Frequency of the task (e.g., monthly, weekly) | `@IsEnum(Frequency)` | `Frequency.monthly` | | `department` | `Departments` | Department responsible for the task (e.g., IT) | `@IsEnum(Departments)` | `Departments.it` | Sources: [apps/api/src/framework-editor/task-template/dto/create-task-template.dto.ts:1-30](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/dto/create-task-template.dto.ts#L1-L30) ### UpdateTaskTemplateDto The `UpdateTaskTemplateDto` is based on `CreateTaskTemplateDto` but uses `PartialType` from `@nestjs/swagger`. This makes all fields optional, allowing for partial updates of a task template. ```typescript import { PartialType } from '@nestjs/swagger'; import { CreateTaskTemplateDto } from './create-task-template.dto'; export class UpdateTaskTemplateDto extends PartialType(CreateTaskTemplateDto) {} ``` Sources: [apps/api/src/framework-editor/task-template/dto/update-task-template.dto.ts:1-4](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/dto/update-task-template.dto.ts#L1-L4) ## API Endpoints The `TaskTemplateController` exposes a set of RESTful API endpoints for managing task templates. All endpoints are versioned under `/v1/framework-editor/task-template` and require authentication. | Method | Path | Description | Service Method Called | Request Body | | :----- | :-------------------- | :----------------------------------------- | :-------------------- | :------------------- | | `GET` | `/` | Retrieve all task templates | `findAll()` | N/A | | `GET` | `/:id` | Retrieve a specific task template by ID | `findById(id)` | N/A | | `PATCH`| `/:id` | Update an existing task template by ID | `updateById(id, dto)` | `UpdateTaskTemplateDto` | | `DELETE`| `/:id` | Delete a task template by ID | `deleteById(id)` | N/A | Sources: [apps/api/src/framework-editor/task-template/task-template.controller.ts:31-87](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L31-L87), [apps/api/src/framework-editor/task-template/schemas/task-template-operations.ts:1-16](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/schemas/task-template-operations.ts#L1-L16) ### Authentication and Authorization All endpoints in the `TaskTemplateController` are protected by `HybridAuthGuard`. This guard enforces authentication, which can be either session-based or API key-based. The `X-Organization-Id` header is required for session authentication and optional for API key authentication. The `AuthContext` decorator is used to inject authentication details (e.g., `userId`, `userEmail`, `authType`) into controller methods. Sources: [apps/api/src/framework-editor/task-template/task-template.controller.ts:14-19](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L14-L19), [apps/api/src/framework-editor/task-template/task-template.controller.ts:50-51](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L50-L51) ### Request Validation The module employs several validation mechanisms: * **`ValidateIdPipe`**: Ensures that the `id` parameter in the URL is valid before it reaches the service layer. * **`ValidationPipe`**: Applied to the `updateTaskTemplate` endpoint, it validates the `UpdateTaskTemplateDto` request body against the rules defined in the DTO (e.g., `@IsString`, `@IsEnum`). It is configured to `whitelist` and `forbidNonWhitelisted` properties, ensuring only expected data is processed. Sources: [apps/api/src/framework-editor/task-template/task-template.controller.ts:12](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L12), [apps/api/src/framework-editor/task-template/task-template.controller.ts:63-68](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.controller.ts#L63-L68) ## Service Logic Details The `TaskTemplateService` implements the core logic for interacting with the database. It uses a `Logger` for operational insights and robust error handling. ### `findAll()` Retrieves all task templates from the database, ordered alphabetically by `name`. Logs the number of retrieved templates. Sources: [apps/api/src/framework-editor/task-template/task-template.service.ts:9-23](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts#L9-L23) ### `findById(id: string)` Fetches a single task template by its unique `id`. If no template is found, it throws a `NotFoundException`. Sources: [apps/api/src/framework-editor/task-template/task-template.service.ts:25-47](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts#L25-L47) ### `updateById(id: string, updateDto: UpdateTaskTemplateDto)` Updates an existing task template. It first calls `findById` to ensure the template exists. If found, it proceeds with the update operation using the provided `updateDto`. Sources: [apps/api/src/framework-editor/task-template/task-template.service.ts:49-69](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts#L49-L69) ### `deleteById(id: string)` Deletes a task template by its `id`. Similar to `updateById`, it first verifies the template's existence using `findById` before performing the deletion. It returns a confirmation message and details of the deleted template. Sources: [apps/api/src/framework-editor/task-template/task-template.service.ts:71-96](https://github.com/blade47/comp/blob/main/apps/api/src/framework-editor/task-template/task-template.service.ts#L71-L96) --- ## Technical docs: DELETE Delete a context entry URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/context/deletecontext ## Parameters ## Responses ## Try It --- ## Technical docs: Developer Tooling URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-8/developer-tooling
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/scripts/encode-badge-icons.ts](https://github.com/blade47/comp/blob/main/apps/api/scripts/encode-badge-icons.ts) - [apps/api/nest-cli.json](https://github.com/blade47/comp/blob/main/apps/api/nest-cli.json) - [apps/api/package.json](https://github.com/blade47/comp/blob/main/apps/api/package.json)
Developer tooling for the `api` application encompasses a suite of scripts, configurations, and dependencies designed to streamline development, build processes, and maintain code quality. This includes automated asset processing, project-specific CLI configurations, and a comprehensive set of development and production dependencies alongside various utility scripts for tasks like database management, testing, and deployment. This page details the core components of the `api` application's developer tooling, providing insights into its structure and functionality. ## Badge Icon Encoding Script The `encode-badge-icons.ts` script is a crucial utility for pre-processing static SVG assets. Its primary purpose is to extract SVG definitions of badge icons from a React component file, encode them as base64 data URLs, and then embed these data URLs into a TypeScript service file. This process optimizes the delivery of small icons by inlining them directly into the application's code, reducing HTTP requests. ### Architecture and Data Flow The script operates by reading a source file containing SVG components, parsing their content, performing base64 encoding, and finally updating a target service file with the generated data. This script is designed to be run manually or as part of a build process, indicated by its usage instruction: `bun run apps/api/scripts/encode-badge-icons.ts`. Sources: [apps/api/scripts/encode-badge-icons.ts:1-66](https://github.com/blade47/comp/blob/main/apps/api/scripts/encode-badge-icons.ts#L1-L66) ### Key Components * **`logos.tsx`**: The source file (located at `../../app/src/app/(app)/[orgId]/trust/portal-settings/components/logos.tsx`) from which SVG definitions are extracted. * **`extractSvg(componentName: string)`**: A function that uses regular expressions to find and extract the SVG content corresponding to a given React component name within `logos.tsx`. It also cleans up `props` spread attributes from the SVG. ```typescript function extractSvg(componentName: string): string | null { const regex = new RegExp(`export const ${componentName} = \\(props.*?\\) => \\(\\s*()\\s*\\);`, 's'); const match = logosContent.match(regex); if (!match) { console.warn(`Warning: Could not find ${componentName}`); return null; } return match[1] .replace(/\{props\}/g, '') .replace(/\{\.\.\.props\}/g, '') .trim(); } ``` Sources: [apps/api/scripts/encode-badge-icons.ts:14-27](https://github.com/blade47/comp/blob/main/apps/api/scripts/encode-badge-icons.ts#L14-L27) * **`badges` Array**: An array of objects defining the specific badge icons to be processed. Each object includes `name` (component name in `logos.tsx`), `type` (key for the map), and `label` (human-readable name). * Examples: `SOC2Type2`, `ISO27001`, `GDPR`, `HIPAA`, `PCIDSS`. * **`encodedBadges` Map**: An object that stores the final base64 encoded icon data URLs and their labels, keyed by the `type` property of each badge. * **`trust-access.service.ts`**: The target service file (located at `../src/trust-portal/trust-access.service.ts`) where the `BADGE_ICON_MAP` constant is updated. * **`BADGE_ICON_MAP`**: A constant within `trust-access.service.ts` that holds the mapping of badge types to their encoded icon data and labels. The script dynamically generates and replaces this map. ## NestJS CLI Configuration The `nest-cli.json` file configures the NestJS Command Line Interface (CLI) for the `api` application. This configuration dictates how the NestJS CLI interacts with the project, including source file locations and build options. ### Configuration Options | Option | Description | Value | | :---------------------- | :------------------------------------------------------------------------ | :---------------------------------- | | `$schema` | JSON schema for validation of the configuration file. | `https://json.schemastore.org/nest-cli` | | `collection` | Specifies the schematics collection to use for generating NestJS artifacts. | `@nestjs/schematics` | | `sourceRoot` | Defines the root directory where application source files reside. | `src` | | `compilerOptions` | Options passed to the TypeScript compiler via the NestJS CLI. | `{ "deleteOutDir": true }` | | `compilerOptions.deleteOutDir` | If `true`, the output directory (`dist` by default) is deleted before each build. | `true` | Sources: [apps/api/nest-cli.json:1-6](https://github.com/blade47/comp/blob/main/apps/api/nest-cli.json#L1-L6) ## Project Dependencies and Scripts The `package.json` file for the `api` application defines its metadata, lists all required dependencies, and provides a set of scripts for various development, build, testing, and deployment tasks. ### Dependencies The `api` application relies on a wide array of packages for its functionality, ranging from core NestJS modules to database ORMs, cloud SDKs, AI tools, and utility libraries. * **NestJS Ecosystem**: `@nestjs/common`, `@nestjs/config`, `@nestjs/core`, `@nestjs/platform-express`, `@nestjs/swagger`, `@nestjs/throttler` * **Database & ORM**: `@prisma/client`, `@trycompai/db`, `@upstash/redis`, `@upstash/vector` * **Cloud Services**: `@aws-sdk/client-s3`, `@aws-sdk/client-securityhub`, `@aws-sdk/client-sts`, `@aws-sdk/s3-request-presigner` * **AI & LLM**: `@ai-sdk/anthropic`, `@ai-sdk/groq`, `@ai-sdk/openai`, `ai`, `@mendable/firecrawl-js` * **Email & Messaging**: `@react-email/components`, `@trycompai/email`, `resend` * **Task Orchestration**: `@trigger.dev/build`, `@trigger.dev/sdk` * **Utilities**: `axios`, `class-transformer`, `class-validator`, `dotenv`, `jose`, `nanoid`, `zod`, `adm-zip`, `archiver`, `exceljs`, `jspdf`, `mammoth`, `pdf-lib`, `xlsx` * **NestJS CLI & Schematics**: `@nestjs/cli`, `@nestjs/schematics` * **Testing**: `@nestjs/testing`, `@types/jest`, `jest`, `supertest`, `ts-jest` * **Linting & Formatting**: `eslint`, `eslint-config-prettier`, `eslint-plugin-prettier`, `prettier` * **TypeScript**: `typescript`, `ts-node`, `tsconfig-paths` * **Trigger.dev CLI**: `trigger.dev` Sources: [apps/api/package.json:5-104](https://github.com/blade47/comp/blob/main/apps/api/package.json#L5-L104) ### Scripts The `scripts` section defines various command-line shortcuts for common tasks. These scripts automate repetitive actions, ensuring consistency across development environments. ### Build Operations The `build` scripts compile the NestJS application. The `build:docker` script includes a Prisma generation step, essential for containerized environments. ### Database Management Scripts for generating Prisma client, getting database schemas, and running migrations. The `db:getschema` script combines schemas from a shared package. ### Development & Debugging Scripts for running the application in development mode, with watch functionality, and for debugging. The `dev` script uses `concurrently` to run both the NestJS API and Trigger.dev services simultaneously. ### Testing A comprehensive set of scripts for running unit, integration, and end-to-end tests, including coverage reports and debugging options. ### Code Quality Scripts for formatting code with Prettier and linting with ESLint to maintain consistent code style and identify potential issues. ### Deployment A specific script for deploying Trigger.dev workflows. | Script Name | Command | Description | | :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- ## Technical docs: GET Download macOS device agent URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/device-agent/downloadmacagent ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download Windows device agent URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/device-agent/downloadwindowsagent ## Parameters ## Responses ## Try It --- ## Technical docs: Decode Single Task JWT URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/decode-single-task-jwt
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/SingleTask.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/SingleTask.tsx) - [apps/app/src/lib/evidence-download.ts](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts) - [apps/app/src/utils/jwt-manager.ts](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts)
This document outlines the execution flow when a user initiates the download of task evidence from the `SingleTask` component, leading to the decoding of a JSON Web Token (JWT) payload. The primary goal of this process is to securely fetch a file from the backend API, which requires a valid authentication token. The flow begins with a user interaction in the `SingleTask` UI, triggering a file download. To ensure the request is authenticated, the system relies on a `jwtManager` utility. This utility is responsible for providing a valid JWT, proactively refreshing it if it's missing or nearing expiration. A crucial part of this refresh mechanism involves decoding the JWT's payload to extract its expiration timestamp, thereby allowing the system to manage token validity and schedule future refreshes efficiently. This ensures that authenticated operations, like downloading sensitive evidence, proceed seamlessly without requiring the user to re-authenticate frequently. ### 1. User Initiates Evidence Download The process begins within the `SingleTask` React component when a user clicks the "Download task evidence" button. This action triggers an asynchronous operation to fetch a ZIP archive containing all evidence related to the current task. The component catches potential errors during the download and provides user feedback via `toast` notifications. The `SingleTask` component is responsible for rendering the task details and providing interactive elements, including the download button for task evidence. **Source:** [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/SingleTask.tsx:196-209](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/SingleTask.tsx#L196-L209) ### 2. Prepare Task Evidence Download Upon the user's action, the `downloadTaskEvidenceZip` function is called. This function is part of the `evidence-download` utility library and is responsible for constructing the correct API endpoint for the task evidence ZIP file. It takes the `taskId`, `taskTitle`, `organizationId`, and an `includeJson` flag as parameters. It then delegates the actual download operation to a more generic `downloadFile` function. **Inputs:** * `taskId`: The ID of the task for which evidence is being downloaded. * `taskTitle`: The title of the task, used for generating a user-friendly filename. * `organizationId`: The ID of the organization, required for API calls. * `includeJson`: A boolean indicating whether to include JSON metadata in the ZIP. **Output:** A call to `downloadFile` with the constructed URL and metadata. **Source:** [apps/app/src/lib/evidence-download.ts:46-60](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts#L46-L60) ### 3. Execute File Download with Authentication The `downloadFile` function, also within the `evidence-download` utility, handles the core logic of fetching a file from a given URL. Before making the `fetch` request, it prepares the necessary HTTP headers, including the `X-Organization-Id`. Crucially, it attempts to retrieve a valid JWT token for authentication. If successful, this token is added to the `Authorization` header as a Bearer token. The function then performs the `fetch` request, handles potential HTTP errors, extracts the filename from the `Content-Disposition` header (or generates a fallback), and finally initiates the client-side download by creating a temporary `` element. **Inputs:** * `url`: The full API endpoint for the file to be downloaded. * `organizationId`: The organization ID for the `X-Organization-Id` header. * `fallback`: An optional object containing `fallbackBaseName` and `fallbackExtension` for filename generation. **Data Flow:** 1. Calls `jwtManager.getValidToken()` to obtain an authentication token. 2. Constructs `headers` object with `X-Organization-Id` and `Authorization` (if token is available). 3. Performs `fetch(url, { method: 'GET', headers, credentials: 'include' })`. 4. Processes `response.blob()` and `Content-Disposition` header to get the file and its name. **Error Handling:** * If `jwtManager.getValidToken()` fails, an error is logged, and a new error "Authentication failed" is thrown. * If the `fetch` response is not `ok`, an error is thrown with the response text or status. **Source:** [apps/app/src/lib/evidence-download.ts:98-145](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts#L98-L145) ### 4. Retrieve a Valid JWT Token The `jwtManager.getValidToken()` method is invoked to ensure that any outgoing API request is authenticated with a current and valid JWT. It first checks if a token is already stored in `localStorage` and if that token is still valid or not expiring soon (within a `REFRESH_THRESHOLD` of 5 minutes). **Branching Logic:** * **If a stored token exists and is not expiring soon:** The method logs "✅ Using cached JWT token" and returns the stored token immediately. * **If no token is stored or the stored token is expiring soon:** The method logs "🔄 JWT token missing or expiring soon, fetching fresh token..." and proceeds to call `this.refreshToken()` to acquire a new token. **Error Handling:** * If any error occurs during this process, it's logged, and `null` is returned, indicating that no valid token could be obtained. **Source:** [apps/app/src/utils/jwt-manager.ts:25-40](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L25-L40) ### 5. Orchestrate Token Refresh The `jwtManager.refreshToken()` method is responsible for managing the token refresh process. It includes logic to prevent multiple concurrent refresh attempts and enforces a cooldown period between refreshes to avoid overwhelming the authentication service. **Concurrency and Cooldown:** * It checks `this.refreshPromise`: If a refresh is already in progress, it waits for that existing promise to resolve. * It checks `this.lastRefreshAttempt` and `REFRESH_COOLDOWN`: If a refresh was attempted too recently, it waits for the cooldown period to pass. During this wait, if a valid token is already available, it might return that token. Once these checks pass, it records the `lastRefreshAttempt` and sets `this.refreshPromise` to the result of `this._doRefreshToken()`, ensuring that subsequent calls wait for this refresh to complete. **Output:** Returns the new token obtained from `_doRefreshToken` or `null` if the refresh fails. **Source:** [apps/app/src/utils/jwt-manager.ts:47-79](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L47-L79) ### 6. Perform Actual Token Refresh The `jwtManager._doRefreshToken()` method executes the actual network requests to obtain a new JWT. It attempts two primary strategies: 1. **Session-based refresh:** It first tries to get a JWT from the `authClient.getSession()` call. The `onSuccess` callback inspects the response headers for a `set-auth-jwt` header. 2. **Explicit token endpoint:** If the session-based approach doesn't yield a token, it makes a direct `fetch` request to the `/api/auth/token` endpoint. **Data Flow:** * Sends requests to authentication endpoints. * Receives a `newToken` string if successful. **Subsequent Actions:** * If a `newToken` is successfully acquired, it calls `this.storeToken(newToken)` to save the new token and its expiry. * It then calls `this.scheduleRefresh(newToken)` to set up an automatic refresh before the new token expires. **Error Handling:** * Logs warnings if the token endpoint fails. * Logs errors if the overall refresh process fails and returns `null`. **Source:** [apps/app/src/utils/jwt-manager.ts:86-128](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L86-L128) ### 7. Store New Token and Expiry The `jwtManager.storeToken()` method is responsible for persisting the newly acquired JWT and its expiration timestamp in `localStorage`. This allows the application to retrieve the token quickly for subsequent authenticated requests without needing to refresh it every time. **Data Flow:** * Takes the `token` string as input. * Calls `this.decodeJWTPayload(token)` to extract the expiration time (`exp`) from the token's payload. * Stores the `token` under `this.STORAGE_KEY` and the `expiresAt` (converted to milliseconds) under `this.EXPIRY_KEY` in `localStorage`. **Error Handling:** * Catches and logs any errors that occur during the storage process, particularly if `decodeJWTPayload` fails. **Source:** [apps/app/src/utils/jwt-manager.ts:135-146](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L135-L146) ### 8. Decode JWT Payload The `jwtManager.decodeJWTPayload()` method is a utility function used to parse the base64-encoded payload of a JWT. This is a client-side operation and does not involve cryptographic verification, as its purpose is simply to extract information like the expiration timestamp (`exp`) for local token management. **Inputs:** * `token`: The full JWT string. **Process:** 1. Splits the JWT into its three parts (header, payload, signature) by the `.` delimiter. 2. Takes the second part (the payload). 3. Uses `atob()` to base64-decode the payload string. 4. Parses the resulting string as JSON. **Output:** The parsed JSON object representing the JWT payload. **Error Handling:** * If the token format is invalid (e.g., not enough parts, or base64 decoding/JSON parsing fails), it throws an `Error('Invalid JWT token format')`. **Source:** [apps/app/src/utils/jwt-manager.ts:170-177](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L170-L177) ### Sequence Diagram ```mermaid sequenceDiagram participant SingleTask as SingleTask.tsx participant EvidenceDownload as evidence-download.ts participant JWTManager as jwt-manager.ts participant AuthService as Auth Service/API SingleTask->>EvidenceDownload: downloadTaskEvidenceZip(taskId, title, orgId, ...) activate EvidenceDownload EvidenceDownload->>EvidenceDownload: Construct API URL EvidenceDownload->>EvidenceDownload: downloadFile(url, orgId, fallback) activate EvidenceDownload EvidenceDownload->>JWTManager: getValidToken() activate JWTManager JWTManager->>JWTManager: Check stored token & expiry alt Token invalid or expiring soon JWTManager->>JWTManager: refreshToken() activate JWTManager JWTManager->>JWTManager: Check refresh in progress / cooldown alt Refresh in progress or cooldown active JWTManager-->>JWTManager: Wait / Return existing token else No active refresh / cooldown JWTManager->>JWTManager: _doRefreshToken() activate JWTManager JWTManager->>AuthService: authClient.getSession() AuthService-->>JWTManager: Session response (with JWT header?) alt No JWT from session JWTManager->>AuthService: fetch('/api/auth/token') AuthService-->>JWTManager: Token response (JSON) end JWTManager->>JWTManager: storeToken(newToken) activate JWTManager JWTManager->>JWTManager: decodeJWTPayload(newToken) activate JWTManager JWTManager-->>JWTManager: Returns payload deactivate JWTManager JWTManager->>JWTManager: Store token & expiry in localStorage deactivate JWTManager JWTManager->>JWTManager: scheduleRefresh(newToken) JWTManager-->>JWTManager: Returns newToken deactivate JWTManager end JWTManager-->>EvidenceDownload: Returns validToken deactivate JWTManager else Token valid and not expiring soon JWTManager-->>EvidenceDownload: Returns storedToken deactivate JWTManager end EvidenceDownload->>EvidenceDownload: Add Authorization header EvidenceDownload->>AuthService: fetch(downloadUrl, { headers }) AuthService-->>EvidenceDownload: File Blob & Content-Disposition EvidenceDownload->>EvidenceDownload: Process Blob, create download link EvidenceDownload-->>SingleTask: File download initiated deactivate EvidenceDownload deactivate EvidenceDownload ``` ### Flowchart ### Key Observations * **Cross-Module Boundaries:** This flow demonstrates clear separation of concerns across different modules: * `SingleTask.tsx`: Handles UI interaction and initiates the high-level action. * `evidence-download.ts`: Manages the specifics of file downloading, including API endpoint construction and client-side download mechanics. * `jwt-manager.ts`: Centralizes all JWT-related operations, such as token retrieval, refresh, storage, and decoding, abstracting authentication details from the download logic. * **Potential Failure Points and Handling:** * **Authentication Failure:** If `jwtManager.getValidToken()` or `_doRefreshToken()` fails to acquire a token, the `downloadFile` function will throw an "Authentication failed" error, which is then caught by `SingleTask` and displayed as a `toast.error`. * **Network Errors:** `fetch` requests in `downloadFile` and `_doRefreshToken` can fail due to network issues or API unavailability. These are caught and reported to the user via `toast.error`. * **Invalid JWT Format:** `decodeJWTPayload` explicitly checks for valid JWT structure and throws an error if parsing fails, preventing corrupted tokens from being used. * **Concurrent Refreshes:** The `jwtManager` uses `refreshPromise` and `REFRESH_COOLDOWN` to prevent multiple token refresh requests from being sent simultaneously, which could lead to race conditions or unnecessary load on the authentication service. * **Performance Considerations:** * **Token Caching:** JWTs are stored in `localStorage` and reused, reducing the need for frequent authentication requests. * **Proactive Refresh:** The `scheduleRefresh` mechanism attempts to refresh the token a few minutes before its actual expiration (`REFRESH_THRESHOLD`), ensuring that a valid token is usually available when an API call is made, minimizing latency for authenticated requests. * **Optimistic Refresh:** The `refreshToken` method's handling of `refreshPromise` means that if multiple parts of the application simultaneously request a token refresh, only one actual refresh operation is performed, and all callers await its result. --- ## Technical docs: Integrate & Decode JWT URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/integrate-decode-jwt
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/TaskIntegrationChecks.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/TaskIntegrationChecks.tsx) - [apps/app/src/lib/evidence-download.ts](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts) - [apps/app/src/utils/jwt-manager.ts](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts)
This document outlines the execution flow that occurs when a user initiates the download of an automation evidence PDF from the `TaskIntegrationChecks` component. The primary goal of this process is to securely fetch a PDF document from the backend API, ensuring that the request is authenticated with a valid JSON Web Token (JWT). The flow begins with a user interaction in the UI, leading to a series of function calls that prepare the download request. A critical part of this preparation involves obtaining a current and unexpired JWT. If the existing token is missing or nearing expiration, a refresh mechanism is triggered to acquire a new token from the authentication service. The trace concludes with the decoding of this JWT to extract its payload, primarily for managing its expiry and storage. This robust authentication mechanism ensures that only authorized users can access and download sensitive evidence documents. ### Initiate Automation PDF Download The process begins within the `TaskIntegrationChecks` React component, which is responsible for displaying and managing automated checks for a specific task. When a user clicks the "Download evidence PDF" button associated with a particular automation check, an `onClick` event handler is triggered. This handler invokes the `downloadAutomationPDF` function, passing along necessary identifiers such as the `taskId`, `automationId` (which corresponds to the `check.checkId`), `automationName` (`check.checkName`), and `organizationId`. This action signals the start of the evidence download sequence. Sources: [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/TaskIntegrationChecks.tsx:392-404](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/TaskIntegrationChecks.tsx#L392-L404) ### Prepare Download Request The `downloadAutomationPDF` function, located in `apps/app/src/lib/evidence-download.ts`, is responsible for constructing the specific API endpoint URL for the automation evidence PDF. It takes the `taskId`, `automationId`, `automationName`, and `organizationId` as input. After forming the complete URL, it delegates the actual file fetching and download process to a generic `downloadFile` utility function, along with fallback naming conventions for the downloaded file. Sources: [apps/app/src/lib/evidence-download.ts:6-20](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts#L6-L20) ### Execute File Download with Authentication The `downloadFile` function in `apps/app/src/lib/evidence-download.ts` handles the core logic for downloading a file from a given URL. Before making the `fetch` request, it constructs the necessary HTTP headers. Crucially, it adds an `X-Organization-Id` header and an `Authorization` header. To obtain the value for the `Authorization` header, it calls `jwtManager.getValidToken()`. This ensures that the download request is properly authenticated with a valid JWT. If `getValidToken` throws an error (e.g., authentication failed), the download process is aborted, and an error is thrown. Upon successful retrieval of the token, it proceeds to make the `fetch` request, processes the response, extracts the filename from the `Content-Disposition` header (or uses a fallback), and then initiates the browser-based file download. Sources: [apps/app/src/lib/evidence-download.ts:64-106](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts#L64-L106) ### Retrieve or Refresh JWT The `getValidToken` method of the `jwtManager` (a singleton instance of `JWTManager` from `apps/app/src/utils/jwt-manager.ts`) is invoked to provide an up-to-date JWT. This method first attempts to retrieve a token and its expiry information from `localStorage`. It then checks if the stored token is still valid or if it's expiring soon (within a `REFRESH_THRESHOLD` of 5 minutes). If no token is found, or if the stored token is deemed to be expiring soon, `getValidToken` proceeds to call `refreshToken()` to acquire a fresh token. Otherwise, it returns the existing, valid token directly. This proactive refresh mechanism minimizes the chances of an API request failing due to an expired token. Sources: [apps/app/src/utils/jwt-manager.ts:16-30](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L16-L30) ### Manage Token Refresh The `refreshToken` method orchestrates the process of obtaining a new JWT. It includes important safeguards: 1. **Concurrent Refresh Prevention:** If a token refresh is already in progress (indicated by `this.refreshPromise`), it waits for that existing refresh to complete instead of initiating a new one. 2. **Cooldown Period:** It enforces a `REFRESH_COOLDOWN` (2 seconds) between refresh attempts to prevent excessive API calls. If an attempt is made too soon after the last, it will wait. After these checks, it sets `this.refreshPromise` to the result of `_doRefreshToken()` and awaits its completion. This ensures that only one refresh operation is active at any given time. Sources: [apps/app/src/utils/jwt-manager.ts:34-60](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L34-L60) ### Perform Actual Token Refresh The private `_doRefreshToken` method is where the actual fetching of a new JWT occurs. It attempts to acquire a new token through two primary mechanisms: 1. **Session API:** It first tries to get the JWT from the `authClient.getSession()` call, which might set a `set-auth-jwt` header in the response. 2. **Token Endpoint:** If the session API doesn't provide a new token, it then makes a `fetch` request to the `/api/auth/token` endpoint. If a new token is successfully obtained from either method, it calls `storeToken()` to persist the new token and its expiry, and `scheduleRefresh()` to set up the next automatic refresh. Sources: [apps/app/src/utils/jwt-manager.ts:64-100](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L64-L100) ### Store New Token Once a new JWT is acquired, the `storeToken` method is called. Its purpose is to securely store the token and its associated expiry information in `localStorage`. To determine the expiry time, it first calls `decodeJWTPayload()` to parse the token and extract the `exp` (expiration) claim. The `exp` value, which is a Unix timestamp in seconds, is converted to milliseconds and stored alongside the token itself. This ensures that `getValidToken` can efficiently check the token's validity without re-decoding it every time. Sources: [apps/app/src/utils/jwt-manager.ts:104-114](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L104-L114) ### Decode JWT Payload The final step in this trace is the `decodeJWTPayload` method. This utility function is responsible for parsing the JWT string to extract its payload. It performs a client-side, unverified decoding by splitting the token into its three parts (header, payload, signature), base64-decoding the payload part, and then parsing the resulting string as JSON. This decoded payload contains claims such as the token's expiration time (`exp`), which is crucial for the `storeToken` method to manage token lifecycle. Sources: [apps/app/src/utils/jwt-manager.ts:145-152](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L145-L152) ```mermaid sequenceDiagram participant UI as TaskIntegrationChecks.tsx participant ED as evidence-download.ts participant JM as jwt-manager.ts participant AuthAPI as /api/auth/token participant Browser as Browser/localStorage UI->>ED: downloadAutomationPDF(taskId, automationId, ...) ED->>ED: build API endpoint URL ED->>ED: downloadFile(url, organizationId, fallback) ED->>JM: getValidToken() JM->>Browser: getStoredToken() alt Token missing or expiring soon JM->>JM: refreshToken() JM->>JM: _doRefreshToken() JM->>AuthAPI: fetch('/api/auth/token') AuthAPI-->>JM: newToken (JWT) JM->>JM: storeToken(newToken) JM->>JM: decodeJWTPayload(newToken) JM->>Browser: store token & expiry JM-->>ED: newToken else Token valid JM-->>ED: storedToken end ED->>ED: add Authorization header with token ED->>AuthAPI: fetch(downloadUrl, {headers, credentials}) AuthAPI-->>ED: fileBlob (PDF) ED->>Browser: createObjectURL, create
, click, revokeObjectURL Browser-->>UI: File Download Started ``` ### Key Observations * **Cross-module Boundaries:** This flow demonstrates significant interaction across different modules: * `TaskIntegrationChecks.tsx` (React UI component) initiates the action. * `evidence-download.ts` (utility for file downloads) handles the API request construction and execution. * `jwt-manager.ts` (authentication utility) manages the JWT lifecycle. * The browser's `localStorage` is used for persistent token storage. * External API endpoints (`/v1/tasks/.../pdf` for download, `/api/auth/token` for token refresh) are crucial for backend communication. * **Potential Failure Points and Handling:** * **Network Errors:** `fetch` calls in `downloadFile` and `_doRefreshToken` can fail due to network issues. These are caught and result in error messages (e.g., `toast.error` in `TaskIntegrationChecks`, `console.error` in `downloadFile` and `jwt-manager`). * **Expired/Invalid JWT:** The `jwtManager` is specifically designed to handle this by proactively refreshing tokens before they expire and by attempting to refresh if an API call indicates an invalid token. If refresh fails, `downloadFile` will throw an "Authentication failed" error. * **Concurrent Refreshes:** The `refreshToken` method prevents multiple simultaneous token refresh requests, which could lead to race conditions or unnecessary load on the authentication service. * **Cooldown Period:** A cooldown is enforced between refresh attempts to avoid hammering the server if refreshes repeatedly fail. * **Invalid JWT Format:** `decodeJWTPayload` includes a `try-catch` block to handle malformed JWTs, preventing the application from crashing. * **Performance Considerations:** * **Client-side Token Management:** Storing and managing JWTs in `localStorage` and performing client-side expiry checks (`isTokenExpiringSoon`) reduces the need for frequent server-side validation, improving responsiveness. * **Proactive Refresh:** Refreshing tokens before they expire minimizes delays in authenticated API calls. * **Optimized Refresh Logic:** The `refreshToken` method's handling of concurrent requests and cooldowns prevents performance degradation due to excessive authentication attempts. * **Asynchronous Operations:** All network requests and token management operations are asynchronous, ensuring the UI remains responsive during these background tasks. Sources: [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/TaskIntegrationChecks.tsx:392-404](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/TaskIntegrationChecks.tsx#L392-L404) [apps/app/src/lib/evidence-download.ts:64-106](https://github.com/blade47/comp/blob/main/apps/app/src/lib/evidence-download.ts#L64-L106) [apps/app/src/utils/jwt-manager.ts:16-152](https://github.com/blade47/comp/blob/main/apps/app/src/utils/jwt-manager.ts#L16-L152) --- ## Technical docs: GET Get all devices URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/devices/getalldevices ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get devices by member ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/devices/getdevicesbymember ## Parameters ## Responses ## Try It --- ## Technical docs: Get Platform Connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/get-platform-connection
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx) - [apps/api/src/integration-platform/controllers/connections.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts) - [apps/api/src/integration-platform/services/connection.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts)
This document outlines the execution flow for testing an integration connection, specifically focusing on how the `IntegrationPlatformTestPage` initiates a connection test and how the backend API processes this request, including updating the connection's status in case of an error. This flow is crucial for users to verify their integration configurations and for the system to maintain accurate connection health. The process begins when a user interacts with the `IntegrationPlatformTestPage` in the frontend application. This action triggers an API call to the backend, which then retrieves the connection details and its associated credentials. For AWS connections, a specialized validation routine is executed. If any part of the connection test fails, the system updates the connection's status to 'error' in the database, providing immediate feedback to the user and marking the connection as unhealthy. ### 1. IntegrationPlatformTestPage The `IntegrationPlatformTestPage` is a React component that serves as a debug and testing interface for the integration platform. It displays a list of available integration providers and existing connections, allowing users to perform various actions like connecting, pausing, resuming, and testing connections. This page is the user-facing entry point for initiating a connection test. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:427-690](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L427-L690) ### 2. handleTestConnection When a user clicks the "Test" button next to a connection on the `IntegrationPlatformTestPage`, the `handleTestConnection` asynchronous function is invoked. This function is responsible for orchestrating the client-side logic for testing a connection. It logs the action to the UI's action log, sets a loading state, and then makes an API call to the backend to initiate the actual connection test. The function takes `connectionId` and `providerSlug` as arguments. It uses the `testConnection` mutation from `useIntegrationMutations` (which internally uses `api.post` to call the backend endpoint) and then logs the result (success or failure message) back to the UI. Finally, it refreshes the list of connections to reflect any status changes. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:498-508](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L498-L508) ### 3. testConnection Upon receiving the API request from the frontend (via `api.post('/v1/integrations/connections/:id/test')`), the `ConnectionsController`'s `testConnection` method is executed. This method is the backend entry point for validating an integration connection. It first retrieves the connection details using the provided `connectionId`. It then fetches the decrypted credentials associated with this connection from the `credentialVaultService`. If no credentials are found, it throws an error. A critical branching point occurs here: * **If the `providerSlug` is 'aws'**: The request is delegated to the `testAwsConnection` private method for AWS-specific validation. * **For other providers**: It checks if the provider's manifest defines a `testConnection` handler. If a handler exists, it's invoked with the decrypted credentials. If no handler is defined, the connection is simply activated, assuming it's a basic connection that doesn't require complex testing. In case of a successful test, the connection is activated. If the test fails (either by the handler returning `false` or throwing an error), `setConnectionError` is called to update the connection status to 'error' along with a descriptive message. Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:707-748](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L707-L748) ### 4. testAwsConnection This private method within `ConnectionsController` is specifically designed to validate AWS integration credentials. It is called by `testConnection` when the `providerSlug` is 'aws'. It reuses the `validateAwsCredentials` method to perform a comprehensive check, which involves: 1. Validating the format of the IAM Role ARN, External ID, and regions. 2. Assuming an internal "role assumer" role. 3. Using the assumed role to then assume the customer's provided IAM role with the External ID. 4. Checking if AWS Security Hub is enabled in all specified regions using the customer's assumed role. Based on the `validateAwsCredentials` result: * If validation is `success: true`, `activateConnection` is called on the `connectionService`. * If validation is `success: false`, `setConnectionError` is called on the `connectionService` with the validation error message. This method returns the validation result, which includes a success flag, a message, and optional details about region-specific checks. Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:751-772](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L751-L772) ### 5. setConnectionError The `setConnectionError` method in `ConnectionService` is called when a connection test (or any other operation) fails and the connection needs to be marked as unhealthy. Its primary responsibility is to update the connection's status to 'error' and store the specific `errorMessage` provided. It delegates the actual database update to `updateConnectionStatus`, passing 'error' as the new status and the received error message. Sources: [apps/api/src/integration-platform/services/connection.service.ts:150-153](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L150-L153) ### 6. updateConnectionStatus This method in `ConnectionService` is a core utility for changing the operational state of an `IntegrationConnection`. It is called by `setConnectionError` (and `activateConnection`, `pauseConnection`) to perform the actual persistence of the status change. Before updating, it first calls `getConnection` to ensure the connection with the given `connectionId` exists. This prevents attempting to update a non-existent record. After verification, it calls the `connectionRepository.updateStatus` method to persist the new status and error message (if any) to the database. Sources: [apps/api/src/integration-platform/services/connection.service.ts:139-147](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L139-L147) ### 7. getConnection The `getConnection` method in `ConnectionService` is a fundamental data access operation. It is called by `updateConnectionStatus` (and other service methods) to retrieve a specific `IntegrationConnection` record from the database using its `connectionId`. If a connection with the given ID is not found, it throws a `NotFoundException`, ensuring that subsequent operations don't proceed with invalid data. This acts as a crucial validation step before any modifications are attempted. Sources: [apps/api/src/integration-platform/services/connection.service.ts:25-31](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L25-L31) ### Sequence Diagram ```mermaid sequenceDiagram participant UI as IntegrationPlatformTestPage participant Frontend as handleTestConnection participant API_Controller as ConnectionsController participant Connection_Service as ConnectionService participant Credential_Vault as CredentialVaultService participant AWS_SDK as AWS SDK (STS, SecurityHub) participant DB as ConnectionRepository UI->>Frontend: User clicks "Test Connection" Frontend->>API_Controller: POST /integrations/connections/:id/test (testConnection) API_Controller->>Connection_Service: getConnection(connectionId) Connection_Service->>DB: Find connection by ID DB-->>Connection_Service: Connection record Connection_Service-->>API_Controller: Connection record API_Controller->>Credential_Vault: getDecryptedCredentials(connectionId) Credential_Vault-->>API_Controller: Decrypted credentials alt Provider is AWS API_Controller->>API_Controller: testAwsConnection(connectionId, credentials) API_Controller->>AWS_SDK: validateAwsCredentials(credentials) AWS_SDK-->>API_Controller: Validation Result (success/failure) alt AWS Validation Success API_Controller->>Connection_Service: activateConnection(connectionId) Connection_Service->>Connection_Service: updateConnectionStatus(connectionId, 'active') Connection_Service->>Connection_Service: getConnection(connectionId) Connection_Service->>DB: Update connection status to 'active' DB-->>Connection_Service: Updated connection Connection_Service-->>API_Controller: Updated connection API_Controller-->>Frontend: { success: true, message: "Validated!" } else AWS Validation Failure API_Controller->>Connection_Service: setConnectionError(connectionId, errorMessage) Connection_Service->>Connection_Service: updateConnectionStatus(connectionId, 'error', errorMessage) Connection_Service->>Connection_Service: getConnection(connectionId) Connection_Service->>DB: Update connection status to 'error' DB-->>Connection_Service: Updated connection Connection_Service-->>API_Controller: Updated connection API_Controller-->>Frontend: { success: false, message: "Validation failed" } end else Provider has custom test handler API_Controller->>API_Controller: manifest.handler.testConnection(credentials) alt Custom Test Success API_Controller->>Connection_Service: activateConnection(connectionId) Connection_Service->>Connection_Service: updateConnectionStatus(connectionId, 'active') Connection_Service->>Connection_Service: getConnection(connectionId) Connection_Service->>DB: Update connection status to 'active' DB-->>Connection_Service: Updated connection Connection_Service-->>API_Controller: Updated connection API_Controller-->>Frontend: { success: true, message: "Connection test successful" } else Custom Test Failure API_Controller->>Connection_Service: setConnectionError(connectionId, errorMessage) Connection_Service->>Connection_Service: updateConnectionStatus(connectionId, 'error', errorMessage) Connection_Service->>Connection_Service: getConnection(connectionId) Connection_Service->>DB: Update connection status to 'error' DB-->>Connection_Service: Updated connection Connection_Service-->>API_Controller: Updated connection API_Controller-->>Frontend: { success: false, message: "Connection test failed" } end else No custom test handler API_Controller->>Connection_Service: activateConnection(connectionId) Connection_Service->>Connection_Service: updateConnectionStatus(connectionId, 'active') Connection_Service->>Connection_Service: getConnection(connectionId) Connection_Service->>DB: Update connection status to 'active' DB-->>Connection_Service: Updated connection Connection_Service-->>API_Controller: Updated connection API_Controller-->>Frontend: { success: true, message: "Connection activated" } end Frontend->>UI: Display result and refresh connections ``` ### Flowchart ### Key Observations * **Cross-Module Boundaries**: This flow extensively crosses module boundaries, starting from the React frontend (`apps/app`) to the NestJS backend (`apps/api`). Within the backend, it traverses from the `ConnectionsController` to the `ConnectionService` and `CredentialVaultService`, and potentially interacts with external AWS SDKs. This layered architecture promotes separation of concerns but requires careful coordination of data flow and error handling. * **Potential Failure Points**: * **Network Issues**: API calls between frontend and backend, or backend and AWS, can fail due to network problems. * **Invalid Credentials**: Incorrect or expired credentials (e.g., AWS IAM Role ARN, External ID, API keys, OAuth tokens) are a common failure point. The system explicitly handles this by calling `setConnectionError`. * **Missing Permissions**: For AWS, the assumed IAM role might lack necessary permissions (e.g., `sts:AssumeRole`, `securityhub:DescribeHub`), leading to validation failures. * **External Service Unavailability**: The AWS Security Hub service itself might be unavailable or not enabled in a region, causing the test to fail. * **Database Errors**: Issues with retrieving or updating connection records in the database. * **Manifest Handler Errors**: Custom `testConnection` handlers defined in integration manifests can throw unhandled exceptions. * **Error Handling**: The flow demonstrates robust error handling. On the backend, `testConnection` and `testAwsConnection` catch exceptions and explicitly call `setConnectionError` to update the connection's status in the database, providing a clear indication of failure. The frontend `handleTestConnection` also logs both success and failure messages to the UI. * **Performance Considerations**: * The AWS validation step (`testAwsConnection`) involves multiple AWS SDK calls (STS AssumeRole, SecurityHub DescribeHub across multiple regions), which can introduce latency. This is an inherent cost of validating external cloud resources. * Database lookups (`getConnection`, `updateConnectionStatus`) are generally fast but could become a bottleneck under very high load if not properly indexed. * Decryption of credentials from the vault adds a small overhead but is necessary for security. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:498-508](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L498-L508) [apps/api/src/integration-platform/controllers/connections.controller.ts:707-748](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L707-L748) [apps/api/src/integration-platform/controllers/connections.controller.ts:751-772](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L751-L772) [apps/api/src/integration-platform/services/connection.service.ts:150-153](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L150-L153) [apps/api/src/integration-platform/services/connection.service.ts:139-147](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L139-L147) [apps/api/src/integration-platform/services/connection.service.ts:25-31](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L25-L31) --- ## Technical docs: GET List evidence forms URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/listforms ## Parameters ## Try It --- ## Technical docs: Update Platform Status URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/update-platform-status
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx) - [apps/api/src/integration-platform/controllers/connections.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts) - [apps/api/src/integration-platform/services/connection.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts) - [apps/api/src/integration-platform/repositories/connection.repository.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/repositories/connection.repository.ts)
The "IntegrationPlatformTestPage -> UpdateStatus" flow describes the process initiated when a user attempts to test an existing integration connection from the Integration Platform Test Page. This flow validates the connection's credentials (e.g., AWS IAM role and Security Hub status) and subsequently updates the connection's status in the database to either `active` (if successful) or `error` (if validation fails), along with a descriptive error message. This process is crucial for ensuring the health and validity of integrated services, providing immediate feedback to users about their connection's operational status. It helps identify misconfigurations or permission issues proactively, preventing downstream failures in data synchronization or automated checks. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:1-550](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L1-L550), [apps/api/src/integration-platform/controllers/connections.controller.ts:1-748](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L1-L748) ### User Initiates Connection Test The process begins on the `IntegrationPlatformTestPage` (`apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx`), a client-side React component. This page displays a list of integration connections. When a user clicks the "Test" button associated with a specific connection, it triggers the `handleTestConnection` function. This function captures the `connectionId` and `providerSlug` for the connection to be tested. ### Client-Side Test Request The `handleTestConnection` function (`apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx`) sets a loading state and logs the action to the UI. It then calls the `testConnection` mutation (provided by `useIntegrationMutations`), which internally makes an API call to the backend. This call is typically a `POST` request to `/v1/integrations/connections/:id/test`, sending the `connectionId` to the API. ### Backend Receives Test Request The `testConnection` method in `ConnectionsController` (`apps/api/src/integration-platform/controllers/connections.controller.ts`) receives the API request. It first retrieves the `IntegrationConnection` object from the database using the provided `connectionId`. It then fetches the decrypted credentials associated with this connection from the `credentialVaultService`. The controller checks the `providerSlug` of the connection. For specific providers like AWS, it delegates to a specialized testing method (`testAwsConnection`). For other providers, it attempts to use a `testConnection` handler defined within the provider's manifest, if available. If no specific handler exists, it defaults to activating the connection. ### AWS Connection Validation For AWS connections, the `testAwsConnection` method (`apps/api/src/integration-platform/controllers/connections.controller.ts`) is invoked. This method performs a comprehensive validation: 1. **Credential Parsing**: Extracts `roleArn`, `externalId`, and `regions` from the connection's credentials. 2. **IAM Role Assumption**: Attempts to assume an internal "role assumer" role, and then uses those temporary credentials to assume the customer's provided IAM role (`roleArn`) with the `externalId`. This verifies the IAM role's validity and permissions. 3. **Security Hub Check**: If role assumption is successful, it then attempts to describe Security Hub in each specified AWS region using the assumed customer credentials. This confirms that Security Hub is enabled and accessible. The result of this validation (success or failure) is returned, along with a detailed message. ### Setting Connection Error Status If the validation in `testAwsConnection` (or any other provider's test handler) fails, the `setConnectionError` method in `ConnectionService` (`apps/api/src/integration-platform/services/connection.service.ts`) is called. This method is a convenience wrapper that prepares the connection for an error state. It takes the `connectionId` and an `errorMessage` as input. ### Updating Connection Status in Service Layer The `setConnectionError` method (or `activateConnection` in case of success) internally calls `updateConnectionStatus` in `ConnectionService` (`apps/api/src/integration-platform/services/connection.service.ts`). This method is responsible for orchestrating the status update. It first performs a check to ensure the connection exists by calling `getConnection(connectionId)`. If the connection is found, it proceeds to call the repository layer to persist the status change. ### Persisting Status Update to Database Finally, the `updateStatus` method in `ConnectionRepository` (`apps/api/src/integration-platform/repositories/connection.repository.ts`) is invoked. This method directly interacts with the database. It updates the `status` field of the `IntegrationConnection` record corresponding to the `connectionId` to either `active` or `error`, and also stores the `errorMessage` if provided. This completes the backend process, and the updated status is then reflected in the frontend after the `refreshConnections` call. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:392-400](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L392-L400), [apps/api/src/integration-platform/controllers/connections.controller.ts:499-668](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L499-L668), [apps/api/src/integration-platform/services/connection.service.ts:104-110](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L104-L110), [apps/api/src/integration-platform/services/connection.service.ts:112-117](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L112-L117), [apps/api/src/integration-platform/repositories/connection.repository.ts:121-131](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/repositories/connection.repository.ts#L121-L131) ```mermaid sequenceDiagram participant UI as IntegrationPlatformTestPage participant Client as Client-side Logic participant Controller as ConnectionsController participant Service as ConnectionService participant Repository as ConnectionRepository participant AWS as AWS Services (STS, SecurityHub) participant CredVault as CredentialVaultService UI->>Client: User clicks "Test Connection" Client->>Client: handleTestConnection(connectionId, providerSlug) Client->>Controller: POST /v1/integrations/connections/:id/test activate Controller Controller->>Service: getConnection(connectionId) activate Service Service->>Repository: findById(connectionId) activate Repository Repository-->>Service: Connection deactivate Repository Service-->>Controller: Connection deactivate Service Controller->>CredVault: getDecryptedCredentials(connectionId) activate CredVault CredVault-->>Controller: Credentials deactivate CredVault alt Provider is AWS Controller->>Controller: testAwsConnection(connectionId, credentials) activate Controller Controller->>AWS: validateAwsCredentials(credentials) activate AWS AWS-->>Controller: ValidationResult (success/failure) deactivate AWS alt Validation successful Controller->>Service: activateConnection(connectionId) activate Service Service->>Service: updateConnectionStatus(connectionId, 'active') Service->>Repository: updateStatus(connectionId, 'active', null) activate Repository Repository-->>Service: UpdatedConnection deactivate Repository Service-->>Controller: UpdatedConnection deactivate Service else Validation failed Controller->>Service: setConnectionError(connectionId, errorMessage) activate Service Service->>Service: updateConnectionStatus(connectionId, 'error', errorMessage) Service->>Repository: updateStatus(connectionId, 'error', errorMessage) activate Repository Repository-->>Service: UpdatedConnection deactivate Repository Service-->>Controller: UpdatedConnection deactivate Service end Controller-->>Client: { success, message, details } deactivate Controller else Other Provider with manifest handler Controller->>Controller: manifest.handler.testConnection(credentials) activate Controller alt Test successful Controller->>Service: activateConnection(connectionId) activate Service Service->>Service: updateConnectionStatus(connectionId, 'active') Service->>Repository: updateStatus(connectionId, 'active', null) activate Repository Repository-->>Service: UpdatedConnection deactivate Repository Service-->>Controller: UpdatedConnection deactivate Service else Test failed Controller->>Service: setConnectionError(connectionId, errorMessage) activate Service Service->>Service: updateConnectionStatus(connectionId, 'error', errorMessage) Service->>Repository: updateStatus(connectionId, 'error', errorMessage) activate Repository Repository-->>Service: UpdatedConnection deactivate Repository Service-->>Controller: UpdatedConnection deactivate Service end Controller-->>Client: { success, message } deactivate Controller end Client->>Client: log(message) Client->>Client: refreshConnections() Client-->>UI: Display updated status ``` ### Key Observations This flow demonstrates a robust mechanism for validating and updating integration connection statuses, spanning multiple architectural layers. * **Cross-Module Boundaries**: The execution crosses significant boundaries: * **Client-side (Next.js App) to Server-side (NestJS API)**: The initial user interaction on the `IntegrationPlatformTestPage` triggers an API call to the `ConnectionsController`. * **Controller to Service Layer**: The `ConnectionsController` delegates business logic to the `ConnectionService` and `CredentialVaultService`. * **Service to Repository Layer**: The `ConnectionService` interacts with the `ConnectionRepository` for database operations. * **API to External Services**: For AWS connections, the `ConnectionsController` directly interacts with external AWS SDKs (STS, SecurityHub) to perform real-time credential validation. This is a critical external dependency. * **Potential Failure Points and Handling**: * **Network Issues**: The API call from client to server can fail due to network problems. The client-side `handleTestConnection` function includes `try-catch` blocks to log errors. * **Invalid Connection ID/Credentials**: The `ConnectionsController` and `ConnectionService` validate the existence of the connection and its credentials. Missing credentials or an invalid connection ID will result in `NotFoundException` or `BadRequestException`. * **AWS Credential Validation Failures**: This is a major potential failure point. `validateAwsCredentials` handles various AWS-specific errors: * **Invalid IAM Role ARN/External ID**: Caught during `sts:AssumeRole`. * **Insufficient Permissions**: If the assumed role lacks necessary permissions (e.g., for Security Hub), `AccessDenied` errors will occur. * **Security Hub Not Enabled**: If Security Hub is not active in the specified regions, a specific error is returned. * These failures lead to the connection status being set to `error` with a user-friendly message. * **Generic Provider Test Failures**: If a manifest's `testConnection` handler throws an error or returns `false`, the connection status is set to `error`. * **Database Errors**: Failures during `updateStatus` in the `ConnectionRepository` could occur, though typically handled by the ORM/database layer. * **Error Propagation**: Errors are caught at various levels (AWS SDK calls, service calls) and propagated back up the stack, eventually resulting in an API response indicating success or failure, which is then logged on the client. The AWS credential validation (`validateAwsCredentials`) is a critical external dependency. Any issues with AWS services, network connectivity to AWS, or misconfigurations of the internal `SECURITY_HUB_ROLE_ASSUMER_ARN` environment variable could lead to validation failures, even if the customer's credentials are correct. * **Performance Considerations**: * **Real-time External Calls**: The AWS credential validation involves multiple external API calls to AWS (STS AssumeRole twice, then Security Hub DescribeHub for each region). This can introduce latency, making the `testConnection` operation potentially slow. * **Database Lookups**: Multiple database lookups (`findById`, `findBySlug`) occur. These are generally fast but contribute to the overall latency. * **Client-side Refresh**: After the test, `refreshConnections()` is called on the client, which refetches all connections. This ensures the UI is up-to-date but adds another round trip. * The current implementation seems to prioritize correctness and thorough validation over raw speed for this specific "test connection" operation, which is typically an infrequent user action. Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:499-668](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L499-L668), [apps/api/src/integration-platform/services/connection.service.ts:104-117](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/connection.service.ts#L104-L117), [apps/api/src/integration-platform/repositories/connection.repository.ts:121-131](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/repositories/connection.repository.ts#L121-L131) --- ## Technical docs: GET Get submission statuses for all forms URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/getformstatuses ## Parameters ## Try It --- ## Technical docs: Autofill Node Processing URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/autofill-node-processing
Relevant source files The following files were used as context for generating this wiki page: - [apps/api/src/soa/soa.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/soa/soa.controller.ts) - [apps/api/src/vector-store/lib/sync/sync-organization.ts](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/sync/sync-organization.ts) - [apps/api/src/vector-store/lib/sync/sync-policies.ts](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/sync/sync-policies.ts) - [apps/api/src/vector-store/lib/utils/extract-policy-text.ts](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/utils/extract-policy-text.ts)
This document outlines the execution flow for the "AutoFill -> ProcessNode" process, which is initiated when a user requests to auto-fill a Statement of Applicability (SOA) document. The primary goal of this flow is to leverage the system's knowledge base to automatically generate answers for SOA questions. The process begins with an API call to trigger the auto-fill operation. A critical initial step involves ensuring the vector database, which powers the AI's retrieval capabilities, is up-to-date with the latest organizational data, including policies. This synchronization ensures that the AI has access to the most relevant and current information when attempting to answer questions. The flow culminates in the extraction of plain text from rich policy content, making it suitable for embedding and subsequent retrieval by the AI. ### Step-by-step Narrative The following steps detail the execution flow, from the initial API request to the deep-level text processing. ### 1. Initiate Auto-Fill Request The process starts with the `autoFill` method in the `SOAController`. This method is an HTTP POST endpoint designed to handle requests for automatically filling out an SOA document. It receives an `AutoFillSOADto` containing the document and organization IDs, along with the user's authentication context. Upon invocation, the controller sets up Server-Sent Events (SSE) to stream real-time progress and answers back to the client. A crucial first action within this method is to trigger a synchronization of the organization's embeddings to ensure the vector database is current. **Data Flow:** * **Input:** `AutoFillSOADto` (documentId, organizationId), `AuthContext` (userId), `Response` object for SSE. * **Output:** Initiates an SSE stream, potentially sending `progress`, `processing`, `answer`, `complete`, or `error` events. The `autoFill` method includes a `try/catch` block around the call to `syncOrganizationEmbeddings`. If the synchronization fails, a warning is logged, but the auto-fill process attempts to continue, assuming some data might still be available in the vector DB. A broader `try/catch` wraps the entire `autoFill` logic, sending an SSE `error` event and logging any unhandled exceptions. Sources: [apps/api/src/soa/soa.controller.ts:47-248](https://github.com/blade47/comp/blob/main/apps/api/src/soa/soa.controller.ts#L47-L248) ### 2. Synchronize Organization Embeddings The `autoFill` method calls `syncOrganizationEmbeddings` to ensure the vector database is up-to-date. This function is responsible for orchestrating the synchronization of all relevant organizational data into the vector store. It implements a locking mechanism to prevent multiple concurrent sync operations for the same organization, ensuring data consistency and resource management. If a sync for the given `organizationId` is already in progress, the function waits for the existing sync to complete rather than starting a new one. **Data Flow:** * **Input:** `organizationId` (string) from the `AutoFillSOADto`. * **Output:** A Promise that resolves once the synchronization is complete, updating the vector store with the latest embeddings. A `syncLocks` Map is used to manage ongoing synchronizations. If an entry exists for an `organizationId`, the function waits for the existing Promise to resolve, effectively serializing sync operations per organization. Sources: [apps/api/src/vector-store/lib/sync/sync-organization.ts:21-51](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/sync/sync-organization.ts#L21-L51) ### 3. Perform Core Synchronization Logic The `syncOrganizationEmbeddings` function delegates the actual synchronization work to the internal `performSync` function. This function executes the core logic for updating the vector store with various types of organizational data. `performSync` systematically fetches existing embeddings, then calls dedicated synchronization functions for policies, context entries, manual answers, and knowledge base documents. After processing these, it identifies and deletes any "orphaned" embeddings that no longer correspond to existing records in the database. Finally, it attempts to verify that newly created or updated embeddings are queryable, accounting for the eventual consistency of the vector store. **Data Flow:** * **Input:** `organizationId` (string). * **Output:** Updates the vector store by upserting new/updated embeddings and deleting obsolete ones. Returns `Promise`. The `verifyEmbeddingIsReady` function (called within `performSync`) uses a retry mechanism with exponential backoff. This is crucial for systems like Upstash Vector, which might have a delay between when an embedding is stored and when it becomes fully indexed and queryable. Sources: [apps/api/src/vector-store/lib/sync/sync-organization.ts:54-135](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/sync/sync-organization.ts#L54-L135) ### 4. Synchronize Policies As part of `performSync`, the `syncPolicies` function is invoked to handle the synchronization of all published policies for the organization. It first fetches all relevant policies from the database using `fetchPolicies`. The function then processes these policies in batches to optimize performance. For each policy in a batch, it calls `syncSinglePolicy` to manage the individual policy's embedding lifecycle. It aggregates statistics on created, updated, skipped, and failed policy synchronizations. **Data Flow:** * **Input:** `organizationId` (string), `existingEmbeddingsMap` (Map of sourceId to `ExistingEmbedding[]`). * **Output:** `SyncStats` object (counts for created, updated, skipped, failed policies, and the ID of the last upserted embedding). Upserts policy embeddings into the vector store. Policies are processed in batches of `POLICY_BATCH_SIZE` (100) using `Promise.all` to allow for parallel execution, improving efficiency for organizations with many policies. Sources: [apps/api/src/vector-store/lib/sync/sync-policies.ts:98-142](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/sync/sync-policies.ts#L98-L142) ### 5. Synchronize a Single Policy The `syncSinglePolicy` function is responsible for the detailed synchronization of an individual policy. It first checks if the policy's `updatedAt` timestamp has changed compared to existing embeddings. If not, it skips the policy. If an update is needed, it deletes any old embeddings associated with this policy. It then calls `extractTextFromPolicy` to convert the policy's rich content into plain text. This plain text is then chunked into smaller, embeddable units, and these chunks are upserted into the vector store. **Data Flow:** * **Input:** `policy` (PolicyData object), `existingEmbeddings` (array of `ExistingEmbedding` for this policy), `organizationId` (string). * **Output:** `SyncSingleResult` (status: 'created', 'updated', or 'skipped'; `lastEmbeddingId`). Modifies the vector store by deleting old embeddings and upserting new ones. The `needsUpdate` check prevents unnecessary re-embedding of policies that haven't changed, significantly reducing processing time and vector store operations. Sources: [apps/api/src/vector-store/lib/sync/sync-policies.ts:63-95](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/sync/sync-policies.ts#L63-L95) ### 6. Extract Text from Policy Content Before a policy's content can be embedded, it must be converted into a clean, plain text format. The `extractTextFromPolicy` function takes a policy object, which typically contains rich text content in a structured format (like TipTap JSON), and transforms it into a single string of plain text. It initializes the text with the policy's name and description, if available. Then, it iterates through the policy's content nodes, recursively calling `processNode` for each to extract text from the nested structure. **Data Flow:** * **Input:** `policy` object (containing `name`, `description`, and `content` in TipTap JSON format). * **Output:** A single string representing the plain text content of the policy. Sources: [apps/api/src/vector-store/lib/utils/extract-policy-text.ts:9-30](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/utils/extract-policy-text.ts#L9-L30) ### 7. Process Individual Content Nodes The `processNode` function is a recursive helper within `extractTextFromPolicy`. Its purpose is to traverse the tree-like structure of TipTap JSON content and extract plain text from various node types. It handles different node types such as `text`, `heading`, `paragraph`, `bulletList`, and `orderedList`. For each type, it extracts the relevant text and formats it appropriately (e.g., adding bullet points for list items). If a node has child nodes, `processNode` calls itself recursively to process them, ensuring all nested content is captured. **Data Flow:** * **Input:** A single TipTap `node` object (can be nested). * **Output:** A string representing the plain text content of that node and its children. Sources: [apps/api/src/vector-store/lib/utils/extract-policy-text.ts:32-95](https://github.com/blade47/comp/blob/main/apps/api/src/vector-store/lib/utils/extract-policy-text.ts#L32-L95) ### Sequence Diagram ### Flowchart ### Key Observations * **Cross-Module Boundaries:** This flow demonstrates significant interaction across different modules: * The `SOAController` (API layer) initiates the process. * The `vector-store/lib/sync` module handles the core synchronization logic with the vector database. * The `vector-store/lib/utils` module provides utility functions for text extraction. * Interactions with the `Database` (via Prisma ORM) and the external `VectorStore` (e.g., Upstash Vector) are central to the data flow. * **Potential Failure Points:** * **Authentication:** The `autoFill` endpoint requires user authentication, failing early if not met. * **Vector Store Sync:** `syncOrganizationEmbeddings` is a critical dependency. While `autoFill` attempts to proceed if sync fails (logging a warning), this could lead to less accurate auto-fill results if the vector store is outdated. * **Database Connectivity:** Failures to fetch policies, documents, or save answers will halt the process. * **Vector Store Operations:** Issues during upserting, querying, or deleting embeddings can cause sync failures. * **Content Extraction:** Malformed or unexpected policy content (TipTap JSON) could lead to incomplete or incorrect text extraction, impacting embedding quality. * **Concurrency:** The `syncLocks` mechanism in `syncOrganizationEmbeddings` is vital to prevent race conditions and ensure data integrity during concurrent sync requests for the same organization. * **Performance Considerations:** * **Initial Sync Latency:** The `syncOrganizationEmbeddings` call at the beginning of `autoFill` can introduce noticeable latency, especially for organizations with a large volume of data (policies, documents) that need to be processed. This is a trade-off for ensuring the AI has the freshest data. * **Batch Processing:** `syncPolicies` uses batch processing (`POLICY_BATCH_SIZE`) and `Promise.all` to parallelize policy synchronization, improving efficiency. * **Delta Sync:** The `needsUpdate` check in `syncSinglePolicy` is a key optimization, preventing unnecessary re-embedding of unchanged policies. * **Eventual Consistency:** The `verifyEmbeddingIsReady` function, with its exponential backoff retries, adds necessary delays to ensure data is queryable but can extend the overall sync time. * **SSE for Responsiveness:** Using Server-Sent Events (SSE) for `autoFill` provides a better user experience by streaming progress and answers, masking some of the backend processing time. --- ## Technical docs: GET Get current user submissions URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/getmysubmissions ## Parameters ## Try It --- ## Technical docs: Check Automation Run Success URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/check-automation-run-success
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/(app)/[orgId]/frameworks/page.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/page.tsx) - [apps/app/src/app/(app)/[orgId]/frameworks/data/getFrameworkWithComplianceScores.ts](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/data/getFrameworkWithComplianceScores.ts) - [apps/app/src/app/(app)/[orgId]/frameworks/lib/compute.ts](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/compute.ts) - [apps/app/src/app/(app)/[orgId]/frameworks/lib/taskEvidenceDocumentsScore.ts](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/taskEvidenceDocumentsScore.ts)
This document details the execution flow that calculates the compliance score for frameworks displayed on the dashboard, specifically focusing on how the success of automated evidence collection runs is determined. The process begins when a user navigates to the dashboard page, triggering a series of data fetches and computations. The primary goal of this flow is to assess the "strict completion" status of tasks associated with various compliance frameworks. A key part of this assessment involves verifying if any enabled automated evidence collection for a task has successfully completed its latest run. This ensures that compliance scores accurately reflect not only manual task completion but also the successful operation of integrated automation. The outcome directly impacts the compliance percentages shown to the user, providing an up-to-date view of their organization's adherence to various standards. ### Step-by-step Narrative The execution flow begins with the rendering of the dashboard page and proceeds through several layers of data fetching and computation to determine task compliance. ### DashboardPage Initialization The `DashboardPage` component serves as the entry point for this flow. Upon loading, it asynchronously fetches all necessary data to populate the dashboard, including user session information, organization details, and various compliance-related scores. Crucially, it retrieves a comprehensive list of tasks, including their associated controls and any configured evidence automations. This raw data is then passed down to subsequent functions for processing. ### Fetching Framework Compliance Scores The `getFrameworkWithComplianceScores` function is called by `DashboardPage` to process the fetched data. Its purpose is to take the raw framework instances and tasks, and enrich them with calculated compliance scores. It iterates through each `frameworkInstance` and delegates the core computation of compliance statistics to the `computeFrameworkStats` function. The function returns an array of frameworks, each augmented with its calculated compliance score. Sources: [apps/app/src/app/(app)/[orgId]/frameworks/data/getFrameworkWithComplianceScores.ts:13-30](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/data/getFrameworkWithComplianceScores.ts#L13-L30) ### Computing Framework Statistics The `computeFrameworkStats` function receives a single `frameworkInstance` and the full list of `tasks` relevant to the organization. It first identifies controls and policies pertinent to the given framework. It then filters the provided `tasks` to include only those associated with the current framework's controls. The function's critical role in this flow is to determine the number of "done tasks" by calling `countStrictlyCompletedTasks`, which directly contributes to the overall compliance score calculation. Sources: [apps/app/src/app/(app)/[orgId]/frameworks/lib/compute.ts:16-51](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/compute.ts#L16-L51) ### Counting Strictly Completed Tasks The `countStrictlyCompletedTasks` function is responsible for iterating through a given array of tasks and determining how many of them meet the criteria for "strict completion." For each task, it calls `isTaskStrictlyComplete` to evaluate its status. The function then returns a count of all tasks that are deemed strictly complete. Sources: [apps/app/src/app/(app)/[orgId]/frameworks/lib/taskEvidenceDocumentsScore.ts:101-103](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/taskEvidenceDocumentsScore.ts#L101-L103) ### Determining Strict Task Completion The `isTaskStrictlyComplete` function evaluates whether a single task is considered "strictly complete." It first checks if the task's `status` is either `'done'` or `'not_relevant'`. If this condition is met, it then proceeds to call `isTaskEvidenceComplete` to verify that all required evidence for the task is also complete. A task is only strictly complete if both its status indicates completion and its evidence requirements are satisfied. Sources: [apps/app/src/app/(app)/[orgId]/frameworks/lib/taskEvidenceDocumentsScore.ts:96-99](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/taskEvidenceDocumentsScore.ts#L96-L99) ### Checking Task Evidence Completion The `isTaskEvidenceComplete` function focuses specifically on the evidence requirements for a given task. It filters the task's `evidenceAutomations` to identify only those that are currently `isEnabled`. If there are no enabled automations, the task is considered to have complete evidence by default. Otherwise, it iterates through each enabled automation and calls `isSuccessfulAutomationRun` on its latest run. The task's evidence is considered complete only if *all* enabled automations have a successful run. Sources: [apps/app/src/app/(app)/[orgId]/frameworks/lib/taskEvidenceDocumentsScore.ts:86-94](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/taskEvidenceDocumentsScore.ts#L86-L94) ### Verifying Successful Automation Run The `isSuccessfulAutomationRun` function is the final step in this specific trace, directly evaluating the success of an individual evidence automation run. It takes an `EvidenceAutomationRunLite` object as input. The function returns `true` only if all three conditions are met: the run's `status` is `'completed'`, its `success` flag is `true`, and its `evaluationStatus` is not `'fail'`. If any of these conditions are not met, or if the run object itself is undefined, it returns `false`. This granular check ensures that only truly successful automation runs contribute to a task's evidence completion. Sources: [apps/app/src/app/(app)/[orgId]/frameworks/lib/taskEvidenceDocumentsScore.ts:81-84](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/frameworks/lib/taskEvidenceDocumentsScore.ts#L81-L84) ### Sequence Diagram ```mermaid sequenceDiagram participant P as apps/app/src/app/(app)/[orgId]/frameworks/page.tsx participant G as apps/app/src/app/(app)/[orgId]/frameworks/data/getFrameworkWithComplianceScores.ts participant C as apps/app/src/app/(app)/[orgId]/frameworks/lib/compute.ts participant T as apps/app/src/app/(app)/[orgId]/frameworks/lib/taskEvidenceDocumentsScore.ts P->>G: getFrameworkWithComplianceScores(frameworksWithControls, tasks) G->>C: computeFrameworkStats(frameworkInstance, tasks) C->>T: countStrictlyCompletedTasks(uniqueTasks) loop For each task T->>T: isTaskStrictlyComplete(task) alt Task status is 'done' or 'not_relevant' T->>T: isTaskEvidenceComplete(task) alt Enabled automations exist loop For each enabled automation T->>T: isSuccessfulAutomationRun(automation.runs[0]) T-->>T: true/false (run success) end T-->>T: true/false (all automations successful) else No enabled automations T-->>T: true (evidence complete) end T-->>T: true/false (task strictly complete) else Task status not 'done' or 'not_relevant' T-->>T: false (task not strictly complete) end end T-->>C: count (strictly completed tasks) C-->>G: FrameworkStats (including doneTasks) G-->>P: FrameworkInstanceWithComplianceScore[] ``` ### Flowchart ### Key Observations * **Cross-module Boundaries**: This flow demonstrates a clear separation of concerns across multiple modules. `page.tsx` handles initial data fetching and orchestration, `data/getFrameworkWithComplianceScores.ts` aggregates and prepares data for computation, and `lib/compute.ts` and `lib/taskEvidenceDocumentsScore.ts` contain the core business logic for calculating compliance and task completion. This modularity enhances maintainability and testability. * **Potential Failure Points and Handling**: * **Authentication/Authorization**: `DashboardPage` explicitly checks for a valid session and redirects to `/login` if not present. It also verifies `onboardingCompleted` status, redirecting if onboarding is still pending. * **Data Availability**: `getScores` and `getControlTasks` within `DashboardPage` handle cases where `organizationId` might be missing from the session, returning default empty values. * **Automation Run Status**: `isSuccessfulAutomationRun` meticulously checks three conditions (`status`, `success`, `evaluationStatus`) to determine success, preventing partially or incorrectly completed automations from being counted as successful. If an automation run is `undefined`, it defaults to `false`. * **No Enabled Automations**: `isTaskEvidenceComplete` gracefully handles tasks with no enabled evidence automations, considering their evidence complete by default, preventing false negatives in compliance scores. * **Performance Considerations**: * **`cache` usage**: `getScores` and `getControlTasks` in `page.tsx` utilize `cache` from `react`, indicating that their results are memoized for the duration of the request, preventing redundant database calls within the same server-side render cycle. * **Database Queries**: The initial data fetching in `DashboardPage` involves several database queries (e.g., `db.organization.findUnique`, `db.onboarding.findUnique`, `db.member.findFirst`, `db.task.findMany`, `db.frameworkEditorFramework.findMany`, `db.finding.findMany`). These are optimized with `select` and `include` clauses to fetch only necessary data. * **Looping and Filtering**: The core compliance calculation involves iterating over frameworks, controls, and tasks. While efficient, for very large datasets (thousands of tasks/controls), the nested loops could become a performance bottleneck. The use of `Map` for deduplication in `computeFrameworkStats` is a good optimization to avoid redundant processing of tasks and policies. --- ## Technical docs: GET Get pending submission count for current user URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/getpendingsubmissioncount ## Parameters ## Try It --- ## Technical docs: Get Browser Assets URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/get-browser-assets
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/BrowserAutomations.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/BrowserAutomations.tsx) - [apps/app/src/app/(app)/[orgId]/tasks/[taskId]/hooks/useBrowserContext.ts](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/hooks/useBrowserContext.ts) - [packages/device-agent/src/main/index.ts](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/index.ts) - [packages/device-agent/src/main/tray.ts](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts)
This process describes how the frontend application's `BrowserAutomations` component, through its interaction with the `useBrowserContext` hook, ultimately leads to a visual update of the Electron `device-agent`'s system tray icon. This flow is crucial for providing real-time feedback on the device agent's operational status, such as its authentication state or whether it's actively performing checks. The high-level goal is to reflect the current state of the browser context (managed by the frontend) in the system tray icon of the background `device-agent`. This involves a cross-process communication where an action in the web application triggers an internal status update within the Electron main process, which then cascades to the UI elements of the system tray, culminating in the loading of the correct icon image from the application's assets. ### Frontend Component Initialization The process begins in the `BrowserAutomations` React component, which is responsible for rendering the user interface related to browser automations. This component utilizes various hooks to manage its state and interactions. One of the key hooks it employs is `useBrowserContext`. Sources: [BrowserAutomations.tsx:19-115](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/BrowserAutomations.tsx#L19-L115) ### Browser Context Management The `useBrowserContext` hook is initialized within the `BrowserAutomations` component. This hook is responsible for managing the state and actions related to the browser context, such as checking its status, initiating authentication flows, and handling sessions. While the `useBrowserContext` hook primarily manages frontend state and interacts with a backend API, its actions (e.g., `checkContextStatus`, `startAuth`) can indirectly influence the operational status of the `device-agent`. For instance, if the frontend successfully establishes a browser context or completes an authentication flow, this state change might be observed by the `device-agent` (e.g., via a shared backend service or a polling mechanism), prompting it to update its own internal status. Sources: [useBrowserContext.ts:16-126](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/hooks/useBrowserContext.ts#L16-L126) ### Device Agent Status Update Following an indirect trigger from the frontend's browser context management, the `device-agent`'s main process calls its internal `setStatus` function. This function is central to managing the `device-agent`'s operational state as reflected in the system tray. It takes a `TrayStatus` enum (e.g., `'unauthenticated'`, `'checking'`, `'compliant'`, `'non-compliant'`) as an argument. The primary action of `setStatus` is to update the `currentStatus` variable within the `device-agent` and then immediately invoke `updateTrayMenu` to refresh the system tray's appearance. Sources: [index.ts:166-169](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/index.ts#L166-L169) ### Tray Menu Refresh The `updateTrayMenu` function in `tray.ts` is called by `setStatus` to refresh the Electron system tray icon and its associated context menu. This function receives the current `TrayStatus` along with check results and callback functions for menu actions. Its first critical task is to determine the appropriate icon for the given status by calling `getIconForStatus`. After obtaining the icon, it updates the tray's image using `tray.setImage()` and rebuilds the context menu, ensuring the visual representation and available actions are consistent with the `device-agent`'s current state. Sources: [tray.ts:110-189](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L110-L189) ### Icon Selection Based on Status The `getIconForStatus` function is responsible for mapping the `TrayStatus` to a specific icon file. It uses a `switch` statement to select the correct PNG filename based on the provided status. For example, a `'compliant'` status will result in `16x16-pass.png`, while `'unauthenticated'` or `'checking'` will use `16x16-default.png`. This function then delegates the actual loading and processing of the image to `loadTrayIcon`. Sources: [tray.ts:77-84](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L77-L84) ### Tray Icon Loading and Processing The `loadTrayIcon` function takes the selected icon filename (e.g., `16x16-pass.png`) and performs several steps to prepare it for display in the system tray. First, it determines the base path for assets by calling `getAssetsPath`. It then constructs the full path to the icon file. The image is loaded using `nativeImage.createFromPath`, resized to a standard `16x16` pixel size, and then centered on a `20x20` transparent canvas. This padding ensures the icon has sufficient "breathing room" and appears consistently across different operating systems. Robust error handling is included to return an empty image if the specified file cannot be found or loaded. Sources: [tray.ts:41-75](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L41-L75) ### Determining Asset Path The final step in this trace is `getAssetsPath`, which is called by `loadTrayIcon`. This utility function resolves the absolute path to the `assets` directory. It intelligently adapts its behavior based on whether the Electron application is running in a packaged (production) environment or a development environment. If `app.isPackaged` is true, it constructs the path relative to `process.resourcesPath`. Otherwise, it uses a relative path from the current module's directory (`__dirname`). This ensures that icon files are correctly located regardless of the application's deployment context. Sources: [tray.ts:33-38](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L33-L38) ```mermaid sequenceDiagram participant BrowserAutomations as apps/app/.../BrowserAutomations.tsx participant useBrowserContext as apps/app/.../useBrowserContext.ts participant DeviceAgentMain as packages/device-agent/src/main/index.ts participant TrayModule as packages/device-agent/src/main/tray.ts BrowserAutomations->>useBrowserContext: Initializes hook useBrowserContext-->>BrowserAutomations: Provides context state and actions Note over useBrowserContext, DeviceAgentMain: Frontend action (e.g., auth success) indirectly triggers device agent status update DeviceAgentMain->>DeviceAgentMain: setStatus(newStatus) DeviceAgentMain->>TrayModule: updateTrayMenu(newStatus, ...) TrayModule->>TrayModule: getIconForStatus(newStatus) TrayModule->>TrayModule: loadTrayIcon(iconFilename) TrayModule->>TrayModule: getAssetsPath() TrayModule-->>TrayModule: Returns assets path TrayModule-->>TrayModule: Returns loaded NativeImage TrayModule-->>TrayModule: Returns NativeImage TrayModule->>DeviceAgentMain: Updates tray icon and menu DeviceAgentMain-->>DeviceAgentMain: Status updated ``` ### Key Observations * **Cross-Module Boundaries:** This flow prominently crosses significant architectural boundaries. It starts in a React frontend component (`apps/app`), conceptually triggers an action that leads to the Electron main process (`packages/device-agent/src/main/index.ts`), and then dives into a utility module specifically for tray management (`packages/device-agent/src/main/tray.ts`). The direct link between `useBrowserContext` and `setStatus` in the trace implies an indirect communication mechanism (e.g., API calls to a shared backend, which the device agent monitors, or an explicit IPC call not detailed in the provided code snippets). * **Decoupled Status Management:** The frontend manages `BrowserContextStatus` (e.g., 'has-context', 'no-context'), while the device agent manages `TrayStatus` (e.g., 'compliant', 'unauthenticated'). Although distinct, there's an implied mapping or correlation between these states, where frontend actions influence the device agent's perceived status. * **Visual Feedback Loop:** The core purpose of this flow is to provide immediate visual feedback to the user via the system tray icon. Any change in the device agent's operational state, often initiated by user interaction in the web app, is quickly reflected in the tray. * **Environment Adaptation:** The `getAssetsPath` function demonstrates good practice by adapting to the application's environment (packaged vs. development), ensuring that assets are always correctly located. * **Performance Considerations:** Icon loading and processing (`loadTrayIcon`) involves file I/O and image manipulation. While typically fast for small icons, repeated calls or complex image processing could introduce minor delays. The padding logic ensures consistent icon appearance, which is a UX consideration. * **Potential Failure Points:** * **IPC/Communication Failure:** If the indirect communication channel between the frontend's `useBrowserContext` and the `device-agent` fails, the tray icon might not update, leading to a stale status display. * **File Not Found:** If `loadTrayIcon` cannot find the specified icon file (e.g., `16x16-pass.png`), it gracefully falls back to an empty image, preventing a crash but resulting in a missing icon. * **Image Processing Errors:** Errors during `nativeImage` creation or resizing are caught, but could lead to an empty or malformed icon. * **Tray Creation Failure:** If `createTray` fails, the application might run without a system tray icon, severely impacting user interaction. Sources: - [BrowserAutomations.tsx:19-115](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/components/BrowserAutomations.tsx#L19-L115) - [useBrowserContext.ts:16-126](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/tasks/%5BtaskId%5D/hooks/useBrowserContext.ts#L16-L126) - [index.ts:166-169](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/index.ts#L166-L169) - [tray.ts:110-189](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L110-L189) - [tray.ts:77-84](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L77-L84) - [tray.ts:41-75](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L41-L75) - [tray.ts:33-38](https://github.com/blade47/comp/blob/main/packages/device-agent/src/main/tray.ts#L33-L38) --- ## Technical docs: Create Empty Paragraph URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/create-empty-paragraph
Relevant source files The following files were used as context for generating this wiki page: - [packages/ui/src/components/editor/index.tsx](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/index.tsx) - [packages/ui/src/components/editor/utils/validate-content.ts](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts)
This document describes the execution flow for "Editor -> CreateEmptyParagraph," a process that ensures the structural integrity of content within the TipTap editor. This flow is critical when the `Editor` component receives `initialContent` that might be malformed, incomplete, or generated by external sources (like AI), especially concerning complex structures like tables. The primary goal of this process is to validate and, if necessary, repair the incoming JSON content to conform to the TipTap schema. The specific trace detailed here illustrates a scenario where a table structure is found to be incomplete or empty, leading to the insertion of an `emptyParagraph` to maintain a valid and editable state within a table cell. This prevents rendering errors and ensures a consistent user experience, even with imperfect input. ### Step-by-step Narrative The execution begins with the initialization of the `Editor` component, which then triggers a comprehensive content validation process. ### Editor Component Initialization The `Editor` component, a React functional component, is responsible for rendering and managing the TipTap editor instance. During its initial render or when `initialContent` is provided, it needs to ensure that the content is in a valid format that TipTap can consume without issues. This is particularly important for content coming from external sources. The component calls `validateAndFixTipTapContent` to process the `initialContent` before passing it to the `useEditor` hook. This proactive validation step is crucial for robust content handling. ### Validating and Fixing TipTap Content The `validateAndFixTipTapContent` function acts as the entry point for content sanitization. Its main responsibility is to take any given content (which might be `null`, an array of nodes, a single node, or a full document) and transform it into a valid TipTap `doc` structure. In this specific trace, it receives the `initialContent`. It first checks if the content is `null` or already a `doc` type. If it's an array or a single node (not a `doc`), it wraps it into a `doc` structure. Regardless of the initial shape, it proceeds to recursively fix the content's nodes by calling `fixContentArray` or `fixNode`. This ensures that the root structure is always a valid `doc` with an array of content nodes. Sources: [packages/ui/src/components/editor/index.tsx:44-44](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/index.tsx#L44-L44), [packages/ui/src/components/editor/utils/validate-content.ts:8-40](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts#L8-L40) ### Fixing Individual Nodes The `fixNode` function is a central dispatcher for content validation. It receives a single node and, based on its `type` property, delegates to a specific fixing function. If the node is invalid (e.g., missing a `type` or not an object), it returns `null`, effectively removing it from the content. In the context of this trace, `fixNode` is called as part of processing the content array. It eventually encounters a node whose type is `table`, leading to the next step. Sources: [packages/ui/src/components/editor/utils/validate-content.ts:79-139](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts#L79-L139) ### Fixing Table Structures When `fixNode` encounters a node of type `table`, it calls `fixTable`. This function is responsible for ensuring that a table node has a valid structure, particularly that it contains at least one `tableRow`. It iterates through the `content` array of the table node, expecting `tableRow` children. For each child, it calls `fixTableRow` to process it. If, after this processing, no valid rows are found (e.g., the `content` array was empty or contained invalid nodes), it proactively inserts a new, empty `tableRow` by calling `createEmptyTableRow()`. This guarantees that a table is never completely empty, preventing rendering issues. Sources: [packages/ui/src/components/editor/utils/validate-content.ts:249-261](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts#L249-L261) ### Fixing Table Rows The `fixTableRow` function is called by `fixTable` to process individual table row nodes. Its role is to ensure that each `tableRow` contains at least one `tableCell`. Similar to `fixTable`, it iterates through the `content` array of the row, expecting `tableCell` children. It calls `fixTableCell` for each child. If no valid cells are found after processing, it inserts a new, empty `tableCell` by calling `createEmptyTableCell()`. This maintains the structural integrity of the table row. Sources: [packages/ui/src/components/editor/utils/validate-content.ts:263-275](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts#L263-L275) ### Fixing Table Cells The `fixTableCell` function is invoked by `fixTableRow` to process individual table cell nodes. Its primary responsibility is to ensure that a `tableCell` always contains some content, even if it's just an empty paragraph. It attempts to fix the cell's `content` array using `fixContentArray`. If, after this process, the `blocks` array (representing the cell's content) is empty, it calls `createEmptyParagraph()` to insert a default empty paragraph. This is crucial because an empty table cell can lead to rendering issues or make it difficult for users to interact with the cell. Sources: [packages/ui/src/components/editor/utils/validate-content.ts:277-286](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts#L277-L286) ### Creating an Empty Paragraph The `createEmptyParagraph` function is a utility that simply returns a JSON object representing an empty TipTap paragraph node. In this trace, it is called by `fixTableCell` when a table cell is found to have no valid content. By inserting an empty paragraph, the system ensures that the cell is not truly empty, providing a valid child node that the TipTap editor can render and interact with. This is the final step in this specific execution path, completing the content repair for the table cell. Sources: [packages/ui/src/components/editor/utils/validate-content.ts:304-309](https://github.com/blade47/comp/blob/main/packages/ui/src/components/editor/utils/validate-content.ts#L304-L309) ### Sequence Diagram ### Flowchart ### Key Observations This flow primarily operates within a single logical module: the `Editor` component and its associated `utils/validate-content.ts` file. The `Editor` component (`index.tsx`) acts as the orchestrator, initiating the validation process by calling `validateAndFixTipTapContent`. All subsequent fixing logic resides within `validate-content.ts`, demonstrating a clear separation of concerns between the UI component and the content validation utility. The `validateAndFixTipTapContent` utility is designed to be highly resilient to malformed input. * **Invalid Root Content**: The initial checks in `validateAndFixTipTapContent` handle `null` content, arrays, or single nodes by wrapping them into a valid `doc` structure or returning an `createEmptyDocument()`. * **Invalid Nodes**: `fixNode` explicitly checks for `null` or non-object nodes and returns `null`, effectively discarding them. It also handles missing or invalid `type` properties. * **Empty Structural Nodes**: Functions like `fixTable`, `fixTableRow`, and `fixTableCell` proactively insert empty child nodes (e.g., `createEmptyTableRow`, `createEmptyTableCell`, `createEmptyParagraph`) if their respective `content` arrays are empty after processing. This prevents empty structural elements from breaking the editor's rendering or interaction logic. * **Recursive Nature**: The recursive calls (e.g., `fixContentArray` calling `fixNode`, which in turn calls other `fix` functions) ensure that validation and fixing propagate throughout the entire content tree. The validation and fixing process involves traversing the entire JSON content tree. For very large documents with deeply nested structures, this recursive processing could introduce a noticeable delay, especially during initial load. However, for typical editor content, the overhead is generally acceptable. The `Editor` component itself uses `useDebouncedCallback` for saving, which helps mitigate performance concerns for subsequent updates, but the initial validation is synchronous. --- ## Technical docs: GET Get form definition and submissions URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/getformwithsubmissions ## Parameters ## Try It --- ## Technical docs: GET Get a single submission URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/getsubmission ## Parameters ## Try It --- ## Technical docs: Get Platform Secret Key URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/get-platform-secret-key
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/app/orgId/integrations/platform-test/page.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx) - [apps/api/src/integration-platform/controllers/connections.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts) - [apps/api/src/integration-platform/services/credential-vault.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts)
This document outlines the execution flow initiated when a user attempts to test an integration connection from the `IntegrationPlatformTestPage` in the frontend. The core purpose of this flow is to securely retrieve and decrypt sensitive integration credentials (like API keys or OAuth tokens) from the backend's credential vault, enabling the system to verify the connection's validity. The process begins with a user action in the browser, triggering an API call to the backend. The backend then fetches the encrypted credentials, decrypts them using a master secret key, and finally uses these plaintext credentials to perform the actual connection test. This secure handling ensures that sensitive information is never exposed directly to the frontend and is only decrypted when needed for operational purposes. ### 1. `IntegrationPlatformTestPage` The execution begins on the `IntegrationPlatformTestPage` component, which is a React page responsible for rendering the user interface to manage and test integration connections. When a user navigates to this page, it loads and displays a list of available integration providers and existing connections. When a user clicks the "Test" button associated with a specific connection, this action triggers the `handleTestConnection` function within this component. The page passes the unique `connectionId` and `providerSlug` of the selected connection to this handler. The primary role of this component in this flow is to initiate the client-side interaction that leads to the backend process. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:329-331](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L329-L331) ### 2. `handleTestConnection` The `handleTestConnection` function is an asynchronous client-side handler defined within the `IntegrationPlatformTestPage`. It is invoked when a user clicks the "Test" button for a particular integration connection. This function takes the `connectionId` and `providerSlug` as arguments. Its main responsibility is to make an API call to the backend to initiate the actual connection test. It uses the `testConnection` mutation provided by the `useIntegrationMutations` hook (which internally uses `api.post`) to send an HTTP POST request to the backend's `/v1/integrations/connections/:id/test` endpoint. During this process, it updates the `isLoading` state to provide visual feedback to the user and logs the outcome (success or error message) to the frontend's action log. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:376-384](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L376-L384) ### 3. `testConnection` This method is a NestJS controller endpoint (`@Post(':id/test')`) within the `ConnectionsController` in the backend. It serves as the API entry point for testing an integration connection. Upon receiving the POST request from the frontend, the method extracts the `connectionId` from the URL parameters. It first retrieves the `Connection` object from the database using `this.connectionService.getConnection(id)`. The crucial step for credential access is then performed: it calls `this.credentialVaultService.getDecryptedCredentials(connection.id)` to obtain the plaintext credentials required for the test. Depending on the `providerSlug` (e.g., 'aws'), it might delegate to a specific testing method (`this.testAwsConnection`) or use a generic handler defined in the integration manifest. If the connection test is successful, it activates the connection; otherwise, it sets the connection to an error state with a descriptive message. This method handles several potential errors:
  • If the provider is not found for the connection, it throws an HttpException.
  • If no credentials are found for the connection, it throws an HttpException.
  • It catches exceptions during the actual connection test (e.g., network issues to the external service, invalid credentials) and uses this.connectionService.setConnectionError to update the connection's status in the database, providing user-facing error messages.
Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:586-630](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L586-L630) ### 4. `getDecryptedCredentials` The `getDecryptedCredentials` method resides within the `CredentialVaultService`. Its purpose is to retrieve the latest encrypted credentials for a given `connectionId` and convert them into a usable, plaintext format. This method takes the `connectionId` as input. It queries the `credentialRepository` to fetch the `latestVersion` of credentials associated with that connection. The retrieved `latestVersion` contains an `encryptedPayload`, which is a JSON object where sensitive values are stored as `EncryptedData` objects (containing `encrypted`, `iv`, `tag`, and `salt` as base64 strings). The method then iterates through this payload, calling `this.decrypt()` for each `EncryptedData` object to transform it back into its original plaintext string. Non-encrypted values are passed through directly. The final output is a `Record` containing all decrypted credentials. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:241-274](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L241-L274) ### 5. `decrypt` The `decrypt` method is a private, core cryptographic function within the `CredentialVaultService`. It performs the actual decryption of a single piece of sensitive data. This method accepts an `EncryptedData` object as input. It first calls `this.getSecretKey()` to retrieve the application's master encryption key. Using this key and the `salt` from the `EncryptedData`, it derives the specific cryptographic key required for decryption using `scryptSync`. It then initializes an `aes-256-gcm` decipher using `createDecipheriv`, sets the authentication tag (`tag`) to verify data integrity, and finally performs the decryption. The result is the original plaintext string. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:80-92](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L80-L92) ### 6. `getSecretKey` The `getSecretKey` method is a private helper function within the `CredentialVaultService`. Its sole responsibility is to retrieve the master encryption key required for cryptographic operations. This method accesses the `process.env.SECRET_KEY` environment variable. This environment variable holds the critical secret key used to encrypt and decrypt all sensitive credentials stored in the vault. This method is a critical failure point. If the SECRET_KEY environment variable is not set, the method will throw an Error, preventing any decryption operations and effectively rendering the credential vault unusable. This highlights the importance of proper environment configuration for security. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:65-71](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L65-L71) ### Sequence Diagram ```mermaid sequenceDiagram participant User as User (Browser) participant Frontend as IntegrationPlatformTestPage participant BackendController as ConnectionsController participant CredentialVaultService as CredentialVaultService participant CredentialRepository as CredentialRepository participant Env as Environment Variables User->>Frontend: Clicks "Test Connection" Frontend->>Frontend: handleTestConnection(connId, providerSlug) Frontend->>BackendController: POST /integrations/connections/:id/test BackendController->>BackendController: getConnection(id) BackendController->>CredentialVaultService: getDecryptedCredentials(connectionId) CredentialVaultService->>CredentialRepository: findLatestByConnection(connectionId) CredentialRepository-->>CredentialVaultService: EncryptedData[] loop For each encrypted credential CredentialVaultService->>CredentialVaultService: decrypt(EncryptedData) CredentialVaultService->>CredentialVaultService: deriveKey(secret, salt) CredentialVaultService->>Env: getSecretKey() Env-->>CredentialVaultService: SECRET_KEY CredentialVaultService-->>CredentialVaultService: Decrypted string end CredentialVaultService-->>BackendController: Decrypted Credentials BackendController->>BackendController: Perform connection test (e.g., validateAwsCredentials) alt Test Successful BackendController->>BackendController: activateConnection(connectionId) BackendController-->>Frontend: Success message else Test Failed BackendController->>BackendController: setConnectionError(connectionId, errorMessage) BackendController-->>Frontend: Error message end Frontend->>Frontend: Log result ``` ### Flowchart ### Key Observations * **Cross-Module Boundaries:** This flow demonstrates a clear separation of concerns across multiple modules and layers: * **Frontend (`apps/app`):** Handles user interaction and initiates API requests. * **Backend Controller (`apps/api/src/integration-platform/controllers`):** Acts as the API gateway, receiving requests and orchestrating business logic. * **Backend Service (`apps/api/src/integration-platform/services`):** Contains core business logic, such as credential management and cryptographic operations. * **Backend Repository (implicit in `CredentialVaultService`):** Abstracts database interactions for credential storage. * **Environment Variables:** Crucial for secure configuration of the master encryption key. * **Potential Failure Points:** * **Network failures:** Between the frontend and backend, or from the backend to external integration services. * **Missing or invalid `SECRET_KEY`:** This is a critical configuration error that would prevent all decryption, leading to system-wide credential access failures. * **Corrupted encrypted data:** If the stored `EncryptedData` is tampered with or malformed, decryption will fail. * **Database issues:** Failure to retrieve connection or credential records. * **External service unavailability:** The actual connection test to the third-party integration might fail due to the external service being down or returning errors. * **Invalid credentials:** Even if decrypted successfully, the credentials might be outdated or incorrect, causing the external connection test to fail. * **Error Handling:** * The frontend logs API call results and displays user-friendly messages. * The `ConnectionsController` catches exceptions during the connection test and updates the connection's status in the database (`setConnectionError`), providing persistent feedback. * The `CredentialVaultService.getSecretKey` explicitly throws an error if the `SECRET_KEY` is not set, indicating a critical deployment issue. * **Performance Considerations:** * The cryptographic operations (`scryptSync`, `createDecipheriv`) involved in decryption are CPU-intensive. While generally fast for individual credentials, decrypting a large number of credentials concurrently could introduce latency. * Database queries for connection and credential records contribute to the overall response time. * The most significant performance variable is often the external API call made during the actual connection test, as its latency depends entirely on the third-party service. --- ## Technical docs: POST Submit evidence form entry URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/submitform ## Parameters ## Request Body body ## Try It --- ## Technical docs: Derive Platform Key URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/how-it-works/derive-platform-key
Relevant source files The following files were used as context for generating this wiki page: - [apps/app/src/app/app/orgId/integrations/platform-test/page.tsx](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx) - [apps/api/src/integration-platform/controllers/connections.controller.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts) - [apps/api/src/integration-platform/services/credential-vault.service.ts](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts)
This document outlines the execution flow when a user initiates a "Test Connection" action from the Integration Platform Test Page, specifically focusing on the backend process of decrypting stored credentials. This flow is critical for ensuring that sensitive integration credentials, such as API keys or OAuth tokens, are securely stored and retrieved only when needed, and then correctly decrypted for use by the integration logic. The process begins with a user interaction on the frontend, triggering an API call to the backend. The backend then retrieves the encrypted credentials from its vault, performs a multi-step decryption process involving key derivation, and finally makes the decrypted credentials available for the connection testing logic. This secure handling of credentials is fundamental to maintaining the integrity and confidentiality of integration data. ### 1. IntegrationPlatformTestPage The journey begins on the `IntegrationPlatformTestPage`, a React component responsible for displaying and managing integration connections. This page provides a user interface to view available providers, existing connections, and actions like "Test Connection." When a user clicks the "Test" button associated with a specific connection, it initiates the `handleTestConnection` function. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:557-557](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L557-L557) ### 2. handleTestConnection The `handleTestConnection` function is a client-side asynchronous operation defined within the `IntegrationPlatformTestPage` component. It takes the `connectionId` and `providerSlug` as arguments. Its primary role is to make an API call to the backend to test the specified connection. It uses the `testConnection` mutation provided by the `useIntegrationMutations` hook, which abstracts the actual HTTP request. Upon receiving a response from the API, it logs the success or failure message to the UI's action log and refreshes the list of connections. Sources: [apps/app/src/app/(app)/[orgId]/integrations/platform-test/page.tsx:590-599](https://github.com/blade47/comp/blob/main/apps/app/src/app/(app)/%5BorgId%5D/integrations/platform-test/page.tsx#L590-L599) ### 3. testConnection This method is an API endpoint within the `ConnectionsController` on the backend, accessible via a `POST` request to `/v1/integrations/connections/:id/test`. It receives the `connectionId` from the URL parameter. Its responsibility is to orchestrate the connection testing process. First, it retrieves the connection details from the database. Crucially, it then calls `this.credentialVaultService.getDecryptedCredentials(connection.id)` to fetch and decrypt the sensitive credentials associated with that connection. If no credentials are found, it throws an error. For AWS connections, it delegates to a specific `testAwsConnection` method. For other providers, it attempts to use a `testConnection` handler defined in the integration's manifest. The outcome (success or failure) is then used to update the connection's status in the database. Sources: [apps/api/src/integration-platform/controllers/connections.controller.ts:608-649](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/controllers/connections.controller.ts#L608-L649) ### 4. getDecryptedCredentials Located in the `CredentialVaultService`, this asynchronous method is responsible for retrieving the latest encrypted credential version for a given `connectionId` and then decrypting its payload. It fetches the `latestVersion` from the `credentialRepository`. If no version is found, it returns `null`. It then iterates through the `encryptedPayload` of the credential. For each field that is identified as `EncryptedData` (meaning it contains `encrypted`, `iv`, `tag`, and `salt` properties), it calls `this.decrypt(value)` to obtain the plaintext string. Other fields (like `token_type` or `scope` for OAuth) are returned as-is. Array values are also handled, with each encrypted item within the array being decrypted individually. The method returns a `Record` containing all the decrypted credential values. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:182-215](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L182-L215) ### 5. decrypt This is the core decryption method within the `CredentialVaultService`. It takes an `EncryptedData` object as input, which contains the base64-encoded encrypted text, initialization vector (IV), authentication tag, and salt. The method first retrieves the master `SECRET_KEY` from environment variables. It then converts the base64-encoded components (encrypted text, IV, tag, salt) back into Node.js `Buffer` objects. The crucial step here is calling `this.deriveKey(secretKey, salt)` to generate the symmetric decryption key. With the derived key, IV, and tag, it initializes a `createDecipheriv` cipher, updates it with the encrypted data, and finalizes the decryption. The resulting plaintext is returned as a UTF-8 string. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:74-89](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L74-L89) ### 6. deriveKey The `deriveKey` method, also part of the `CredentialVaultService`, is responsible for securely generating a cryptographic key from a secret and a salt. It uses Node.js's `crypto.scryptSync` function, a password-based key derivation function (PBKDF) designed to be computationally intensive, thus making brute-force attacks more difficult. It takes the master `secret` (the `SECRET_KEY` from environment variables) and a `salt` (randomly generated for each encryption) as input. It then applies `scryptSync` with specific parameters: `N` (CPU/memory cost factor), `r` (block size), and `p` (parallelization factor), and requests a `KEY_LENGTH` of 32 bytes. The output is a `Buffer` containing the derived key, which is then used by the `decrypt` method for the actual decryption process. Sources: [apps/api/src/integration-platform/services/credential-vault.service.ts:68-72](https://github.com/blade47/comp/blob/main/apps/api/src/integration-platform/services/credential-vault.service.ts#L68-L72) ### Sequence Diagram ```mermaid sequenceDiagram participant UI as IntegrationPlatformTestPage participant Client as handleTestConnection participant API as ConnectionsController participant VaultService as CredentialVaultService UI->>Client: User clicks "Test Connection" (connectionId, providerSlug) Client->>API: POST /v1/integrations/connections/:id/test API->>VaultService: getDecryptedCredentials(connectionId) VaultService->>VaultService: findLatestByConnection(connectionId) alt Credential found loop For each encrypted field in payload VaultService->>VaultService: decrypt(encryptedData) VaultService->>VaultService: getSecretKey() VaultService->>VaultService: deriveKey(secretKey, salt) VaultService-->>VaultService: Derived Key VaultService-->>VaultService: Decrypted Value end VaultService-->>API: Decrypted Credentials (Record) API->>API: Perform connection test logic (e.g., validateAwsCredentials) API-->>Client: Test Result (success/failure message) else No credential found VaultService-->>API: null API-->>Client: Error: No credentials found end Client-->>UI: Update UI with test result/error ``` ### Flowchart ### Key Observations * **Cross-Module Boundaries**: The execution flow spans significant architectural layers, starting from the Next.js frontend (`IntegrationPlatformTestPage`), crossing the network boundary to the NestJS API gateway (`ConnectionsController`), and then delving into a dedicated backend service (`CredentialVaultService`) for secure credential handling. This clear separation of concerns enhances maintainability and security. * **Potential Failure Points**: * **Missing `SECRET_KEY`**: The `getSecretKey` method explicitly checks for the `SECRET_KEY` environment variable. If this critical key is not set, the application will crash during decryption attempts, rendering all encrypted credentials unusable. * **Corrupted Encrypted Data**: If any part of the `EncryptedData` (encrypted text, IV, tag, salt) is corrupted or tampered with, the decryption process will fail, likely resulting in an `Authentication Tag Mismatch` error, indicating data integrity compromise. * **Incorrect `SECRET_KEY`**: If the `SECRET_KEY` used for decryption does not match the one used for encryption, the `deriveKey` function will produce a different key, leading to decryption failure. * **Database Issues**: Problems fetching the latest credential version from the `credentialRepository` would prevent decryption. * **Network Errors**: The initial API call from the client to the controller could fail due to network connectivity issues. * **Performance Considerations**: The `deriveKey` method uses `scryptSync`, a computationally intensive key derivation function. While this is excellent for security (making brute-force attacks harder), its synchronous nature means it blocks the Node.js event loop during execution. For a single connection test, this overhead is acceptable. However, in scenarios requiring high-volume, concurrent decryption operations, this could become a performance bottleneck. The parameters (`N`, `r`, `p`) for `scryptSync` are chosen to provide a balance between security and acceptable performance. * **Security Best Practices**: The use of `scryptSync` with a unique `salt` for each encryption, along with AES-256-GCM (which provides authenticated encryption), demonstrates robust cryptographic practices for protecting sensitive data at rest. The separation of the master secret key (`SECRET_KEY`) from the application code and its reliance on environment variables is also a good security practice. --- ## Technical docs: PATCH Review a submission URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/reviewsubmission ## Parameters ## Request Body body ## Try It --- ## Technical docs: POST Upload evidence form file URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/uploadfile ## Parameters ## Request Body body ## Try It --- ## Technical docs: GET Export form submissions to CSV URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/exportcsv ## Parameters ## Try It --- ## Technical docs: GET Get all finding templates URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/finding-templates/getallfindingtemplates ## Responses ## Try It --- ## Technical docs: GET Get finding template by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/finding-templates/getfindingtemplatebyid ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a finding template URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/finding-templates/createfindingtemplate ## Request Body Finding template data ## Responses ## Try It --- ## Technical docs: PATCH Update a finding template URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/finding-templates/updatefindingtemplate ## Parameters ## Request Body Finding template update data ## Responses ## Try It --- ## Technical docs: DELETE Delete a finding template URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/finding-templates/deletefindingtemplate ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get findings for a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-getfindingsbytask ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all findings for organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-getorganizationfindings ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get finding by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-getfindingbyid ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a finding URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-createfinding ## Parameters ## Request Body Finding data ## Responses ## Try It --- ## Technical docs: PATCH Update a finding URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-updatefinding ## Parameters ## Request Body Finding update data ## Responses ## Try It --- ## Technical docs: DELETE Delete a finding URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-deletefinding ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get finding history URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/findings/findingscontroller-getfindinghistory ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all task templates URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/framework-editor-task-templates/tasktemplatecontroller-getalltasktemplates ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get task template by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/framework-editor-task-templates/tasktemplatecontroller-gettasktemplatebyid ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Update a task template URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/framework-editor-task-templates/tasktemplatecontroller-updatetasktemplate ## Parameters ## Request Body Data to update the task template. ## Responses ## Try It --- ## Technical docs: DELETE Delete a task template URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/framework-editor-task-templates/tasktemplatecontroller-deletetasktemplate ## Parameters ## Responses ## Try It --- ## Technical docs: GET Health check URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/health/healthcontroller-gethealth ## Responses ## Try It --- ## Technical docs: GET List all integrations with their credential status URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/adminintegrationscontroller-listintegrations ## Try It --- ## Technical docs: GET Get details for a specific integration URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/adminintegrationscontroller-getintegration ## Parameters ## Try It --- ## Technical docs: POST Save platform credentials for an integration URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/adminintegrationscontroller-saveplatformcredentials ## Request Body ## Try It --- ## Technical docs: DELETE Delete platform credentials for an integration URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/adminintegrationscontroller-deleteplatformcredentials ## Parameters ## Try It --- ## Technical docs: GET List available checks for a provider URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/listproviderchecks ## Parameters ## Responses ## Try It --- ## Technical docs: GET List available checks for a connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/listconnectionchecks ## Parameters ## Responses ## Try It --- ## Technical docs: POST Run checks for a connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/runconnectionchecks ## Parameters ## Request Body Request body to specify check to run ## Responses ## Try It --- ## Technical docs: POST Run a specific check for a connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/endpoints/runsinglecheck ## Parameters ## Responses ## Try It --- ## Technical docs: GET List all available integration providers URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/listproviders ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get a specific provider's details URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/getprovider ## Parameters ## Responses ## Try It --- ## Technical docs: GET List connections for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/listconnections ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get a specific connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/getconnection ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new connection with API key credentials URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/createconnection ## Request Body Connection creation data ## Responses ## Try It --- ## Technical docs: POST Test a connection's credentials URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/testconnection ## Parameters ## Responses ## Try It --- ## Technical docs: POST Pause a connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/pauseconnection ## Parameters ## Responses ## Try It --- ## Technical docs: POST Resume a paused connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/resumeconnection ## Parameters ## Responses ## Try It --- ## Technical docs: POST Disconnect (soft delete) a connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/disconnectconnection ## Parameters ## Responses ## Try It --- ## Technical docs: DELETE Delete a connection permanently URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/deleteconnection ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Update connection metadata (connectionName, regions, etc.) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/updateconnection ## Parameters ## Request Body Metadata to update ## Responses ## Try It --- ## Technical docs: POST Get valid credentials for a connection, refreshing OAuth tokens if needed. URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/ensurevalidcredentials ## Parameters ## Responses ## Try It --- ## Technical docs: PUT Update credentials for a custom auth connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/connections/updatecredentials ## Parameters ## Request Body New credentials to update ## Responses ## Try It --- ## Technical docs: GET List custom OAuth apps for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthappscontroller-listoauthapps ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get OAuth app setup info for a provider URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthappscontroller-getsetupinfo ## Parameters ## Responses ## Try It --- ## Technical docs: POST Save custom OAuth app credentials for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthappscontroller-saveoauthapp ## Request Body OAuth app credentials to save. ## Responses ## Try It --- ## Technical docs: DELETE Delete custom OAuth app credentials for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthappscontroller-deleteoauthapp ## Parameters ## Responses ## Try It --- ## Technical docs: GET Check if OAuth credentials are available for a provider URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthcontroller-checkavailability ## Parameters ## Responses ## Try It --- ## Technical docs: POST Start OAuth flow - returns authorization URL URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthcontroller-startoauth ## Request Body Information to start the OAuth flow. ## Responses ## Try It --- ## Technical docs: GET OAuth callback - exchanges code for tokens URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integrations/oauthcontroller-oauthcallback ## Parameters ## Responses ## Try It --- ## Technical docs: POST Sync employees from Google Workspace URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-syncgoogleworkspaceemployees ## Parameters ## Responses ## Try It --- ## Technical docs: POST Check if Google Workspace is connected for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-getgoogleworkspacestatus ## Parameters ## Responses ## Try It --- ## Technical docs: POST Sync employees from Rippling URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-syncripplingemployees ## Parameters ## Responses ## Try It --- ## Technical docs: POST Check if Rippling is connected for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-getripplingstatus ## Parameters ## Responses ## Try It --- ## Technical docs: POST Sync employees from Ramp URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-syncrampemployees ## Parameters ## Responses ## Try It --- ## Technical docs: POST Sync employees from JumpCloud URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-syncjumpcloudemployees ## Parameters ## Responses ## Try It --- ## Technical docs: POST Check if JumpCloud is connected for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-getjumpcloudstatus ## Parameters ## Responses ## Try It --- ## Technical docs: POST Check if Ramp is connected for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-getrampstatus ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get the current employee sync provider for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-getemployeesyncprovider ## Parameters ## Responses ## Try It --- ## Technical docs: POST Set the employee sync provider for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-sync/synccontroller-setemployeesyncprovider ## Parameters ## Request Body Provider to set ## Responses ## Try It --- ## Technical docs: GET Get all integration checks that can auto-complete a specific task template URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-integrations/getchecksfortasktemplate ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get integration checks for a specific task (by task ID) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-integrations/getchecksfortask ## Parameters ## Responses ## Try It --- ## Technical docs: POST Run a specific check for a task and store results URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-integrations/runcheckfortask ## Parameters ## Request Body Body for running a check for a task. ## Responses ## Try It --- ## Technical docs: GET Get check run history for a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-integrations/gettaskcheckruns ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all variables required for a provider's checks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-variables/getprovidervariables ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get variables for a specific connection (with current values) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-variables/getconnectionvariables ## Parameters ## Responses ## Try It --- ## Technical docs: GET Fetch dynamic options for a variable (requires active connection) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-variables/fetchvariableoptions ## Parameters ## Responses ## Try It --- ## Technical docs: POST Save variable values for a connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/integration-variables/saveconnectionvariables ## Parameters ## Request Body Body for saving connection variables. ## Responses ## Try It --- ## Technical docs: POST Handle incoming webhooks for a specific provider and connection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/webhooks/webhookcontroller-handlewebhook ## Parameters ## Request Body The payload of the webhook, which can be any JSON object. ## Responses ## Try It --- ## Technical docs: GET List all knowledge base documents for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-listdocuments ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: POST Upload a knowledge base document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-uploaddocument ## Request Body Upload document DTO. ## Responses ## Try It --- ## Technical docs: POST Get a signed download URL for a knowledge base document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-getdownloadurl ## Parameters ## Request Body Get document URL DTO. ## Responses ## Try It --- ## Technical docs: POST Get a signed view URL for a knowledge base document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-getviewurl ## Parameters ## Request Body Get document URL DTO. ## Responses ## Try It --- ## Technical docs: POST Delete a knowledge base document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-deletedocument ## Parameters ## Request Body Delete document DTO. ## Responses ## Try It --- ## Technical docs: POST Trigger processing of knowledge base documents URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-processdocuments ## Request Body Process documents DTO. ## Responses ## Try It --- ## Technical docs: POST Create a public access token for a Trigger.dev run URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-createruntoken ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: POST Delete a manual answer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-deletemanualanswer ## Parameters ## Request Body Delete manual answer DTO. ## Responses ## Try It --- ## Technical docs: POST Delete all manual answers for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/knowledge-base/knowledgebasecontroller-deleteallmanualanswers ## Request Body Delete all manual answers DTO. ## Responses ## Try It --- ## Technical docs: GET Get the organization chart URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/org-chart/orgchartcontroller-getorgchart ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: PUT Create or update an interactive organization chart URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/org-chart/orgchartcontroller-upsertorgchart ## Parameters ## Request Body Data for the organization chart, including nodes and edges. ## Responses ## Try It --- ## Technical docs: POST Upload an image as the organization chart URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/org-chart/orgchartcontroller-uploadorgchart ## Parameters ## Request Body DTO for uploading an organization chart image. ## Responses ## Try It --- ## Technical docs: DELETE Delete the organization chart URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/org-chart/orgchartcontroller-deleteorgchart ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: GET Get organization details URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/organization/organizationcontroller-getorganization ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: PATCH Update organization details URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/organization/organizationcontroller-updateorganization ## Parameters ## Request Body Data to update the organization. ## Responses ## Try It --- ## Technical docs: POST Transfer organization ownership URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/organization/organizationcontroller-transferownership ## Parameters ## Request Body Data for transferring ownership. ## Responses ## Try It --- ## Technical docs: DELETE Delete an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/organization/organizationcontroller-deleteorganization ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: GET Get organization primary color URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/organization/organizationcontroller-getprimarycolor ## Parameters ## Request Body No request body is required. ## Responses ## Try It --- ## Technical docs: GET Get all people for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-getallpeople ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new person (member) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-createmember ## Parameters ## Request Body The person (member) data to create. ## Responses ## Try It --- ## Technical docs: POST Bulk create people (members) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-bulkcreatemembers ## Parameters ## Request Body An array of people (members) data to create. ## Responses ## Try It --- ## Technical docs: GET Get a person (member) by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-getpersonbyid ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Update a person (member) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-updatemember ## Parameters ## Request Body The person (member) data to update. ## Responses ## Try It --- ## Technical docs: DELETE Remove a host from a person (member) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-removehost ## Parameters ## Responses ## Try It --- ## Technical docs: DELETE Delete a person (member) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-deletemember ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Unlink a device from a person (member) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/people/peoplecontroller-unlinkdevice ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all policies for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-getallpolicies ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download all published policies as a single PDF URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-downloadallpolicies ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get a policy by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-getpolicy ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new policy URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-createpolicy ## Parameters ## Request Body The policy data to create. ## Responses ## Try It --- ## Technical docs: PATCH Update a policy URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-updatepolicy ## Parameters ## Request Body The policy data to update. ## Responses ## Try It --- ## Technical docs: DELETE Delete a policy URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-deletepolicy ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all versions for a policy URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-getpolicyversions ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get a policy version by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-getpolicyversionbyid ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new policy version URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-createpolicyversion ## Parameters ## Request Body The policy version data to create. ## Responses ## Try It --- ## Technical docs: PATCH Update policy version content URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-updateversioncontent ## Parameters ## Request Body The content data to update in the policy version. ## Responses ## Try It --- ## Technical docs: DELETE Delete a policy version URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-deletepolicyversion ## Parameters ## Responses ## Try It --- ## Technical docs: POST Publish a policy version URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-publishpolicyversion ## Parameters ## Request Body Data to publish the version. ## Responses ## Try It --- ## Technical docs: POST Set a policy version as active URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-setactivepolicyversion ## Parameters ## Responses ## Try It --- ## Technical docs: POST Submit a policy version for approval URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-submitversionforapproval ## Parameters ## Request Body Data for submitting the version for approval. ## Responses ## Try It --- ## Technical docs: POST Chat with AI about a policy URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/policies/policiescontroller-aichatpolicy ## Parameters ## Request Body The AI chat request data. ## Responses ## Try It --- ## Technical docs: POST Parse questionnaire content URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-parsequestionnaire ## Request Body ## Responses ## Try It --- ## Technical docs: POST Generated single answer result URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-answersinglequestion ## Request Body ## Responses ## Try It --- ## Technical docs: POST Save manual or generated answer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-saveanswer ## Request Body ## Responses ## Try It --- ## Technical docs: POST Delete questionnaire answer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-deleteanswer ## Request Body ## Responses ## Try It --- ## Technical docs: POST Export questionnaire by ID to specified format URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-exportbyid ## Request Body ## Responses ## Try It --- ## Technical docs: POST Upload file, parse questions (no answers), save to DB, return questionnaireId URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-uploadandparse ## Request Body ## Responses ## Try It --- ## Technical docs: POST Upload file, parse questions (no answers), save to DB, return questionnaireId URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-uploadandparseupload ## Request Body ## Responses ## Try It --- ## Technical docs: POST Create Upload URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-parsequestionnaireupload ## Request Body ## Responses ## Try It --- ## Technical docs: POST Create Token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-parsequestionnaireuploadbytoken ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Create Export URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-autoanswerandexport ## Request Body ## Responses ## Try It --- ## Technical docs: POST Create Upload URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-autoanswerandexportupload ## Request Body ## Responses ## Try It --- ## Technical docs: POST Create Auto Answer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/questionnaire/questionnairecontroller-autoanswer ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get all risks for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/risks/riskscontroller-getallrisks ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get a risk by its ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/risks/riskscontroller-getriskbyid ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new risk URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/risks/riskscontroller-createrisk ## Parameters ## Request Body Risk data to create. ## Responses ## Try It --- ## Technical docs: PATCH Update an existing risk URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/risks/riskscontroller-updaterisk ## Parameters ## Request Body Partial risk data to update. ## Responses ## Try It --- ## Technical docs: DELETE Delete a risk URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/risks/riskscontroller-deleterisk ## Parameters ## Responses ## Try It --- ## Technical docs: POST Save a SOA answer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-saveanswer ## Parameters ## Request Body SaveSOAAnswerDto ## Responses ## Try It --- ## Technical docs: POST Auto-fill SOA document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-autofill ## Parameters ## Request Body AutoFillSOADto ## Responses ## Try It --- ## Technical docs: POST Create a new SOA document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-createdocument ## Parameters ## Request Body CreateSOADocumentDto ## Responses ## Try It --- ## Technical docs: POST Ensure SOA configuration and document exist URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-ensuresetup ## Parameters ## Request Body EnsureSOASetupDto ## Responses ## Try It --- ## Technical docs: POST Approve a SOA document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-approvedocument ## Parameters ## Request Body ApproveSOADocumentDto ## Responses ## Try It --- ## Technical docs: POST Decline a SOA document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-declinedocument ## Parameters ## Request Body DeclineSOADocumentDto ## Responses ## Try It --- ## Technical docs: POST Submit SOA document for approval URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/soa/soacontroller-submitforapproval ## Parameters ## Request Body SubmitSOAForApprovalDto ## Responses ## Try It --- ## Technical docs: GET Get task items statistics for an entity URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-gettaskitemsstats ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get task items for an entity URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-gettaskitems ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new task item URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-createtaskitem ## Parameters ## Request Body CreateTaskItemDto ## Responses ## Try It --- ## Technical docs: PUT Update a task item URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-updatetaskitem ## Parameters ## Request Body UpdateTaskItemDto ## Responses ## Try It --- ## Technical docs: DELETE Delete a task item URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-deletetaskitem ## Parameters ## Responses ## Try It --- ## Technical docs: POST Upload attachment to task item URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-uploadtaskitemattachment ## Parameters ## Request Body UploadTaskItemAttachmentDto ## Responses ## Try It --- ## Technical docs: DELETE Delete attachment from task item URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-deletetaskitemattachment ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get task item activity log URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-management/taskmanagementcontroller-gettaskitemactivity ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all automations for a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-gettaskautomations ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get automation details URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-getautomation ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-createautomation ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Update an automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-updateautomation ## Parameters ## Request Body UpdateAutomationDto ## Responses ## Try It --- ## Technical docs: DELETE Delete an automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-deleteautomation ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all versions for an automation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-getautomationversions ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get all automation runs for a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/task-automations/automationscontroller-gettaskautomationruns ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get task evidence summary URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-export/evidenceexportcontroller-gettaskevidencesummary ## Parameters ## Responses ## Try It --- ## Technical docs: GET Export automation evidence as PDF URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-export/evidenceexportcontroller-exportautomationpdf ## Parameters ## Responses ## Try It --- ## Technical docs: GET Export task evidence as ZIP URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-export/evidenceexportcontroller-exporttaskevidencezip ## Parameters ## Responses ## Try It --- ## Technical docs: GET Export all organization evidence as ZIP (Auditor only) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-export-auditor/auditorevidenceexportcontroller-exportallevidence ## Parameters ## Responses ## Try It --- ## Technical docs: POST Send task status change notifications (email + in-app) without a user actor (internal) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/internal-tasks/internaltasknotificationcontroller-notifystatuschange ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Send automation failure notifications (email + in-app) when one or more automations fail (internal) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/internal-tasks/internaltasknotificationcontroller-notifyautomationfailures ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get all tasks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-gettasks ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Update status for multiple tasks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-updatetasksstatus ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: PATCH Update assignee for multiple tasks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-updatetasksassignee ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Bulk submit tasks for review URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-bulksubmitforreview ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: DELETE Delete multiple tasks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-deletetasks ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get task by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-gettask ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get task activity URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-gettaskactivity ## Parameters ## Responses ## Try It --- ## Technical docs: PATCH Update a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-updatetask ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Submit task for review URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-submitforreview ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Approve a task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-approvetask ## Parameters ## Responses ## Try It --- ## Technical docs: POST Reject a task review URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-rejecttask ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get task attachments URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-gettaskattachments ## Parameters ## Responses ## Try It --- ## Technical docs: POST Upload attachment to task URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-uploadtaskattachment ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get attachment download URL URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-gettaskattachmentdownloadurl ## Parameters ## Responses ## Try It --- ## Technical docs: DELETE Delete task attachment URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/tasks/taskscontroller-deletetaskattachment ## Parameters ## Responses ## Try It --- ## Technical docs: POST Send training completion email with certificate URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/training/trainingcontroller-sendtrainingcompletionemail ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Generate training completion certificate PDF URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/training/trainingcontroller-generatecertificate ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Submit data access request URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-createaccessrequest ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET List access requests URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-listaccessrequests ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get access request details URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getaccessrequest ## Parameters ## Responses ## Try It --- ## Technical docs: POST Approve access request URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-approverequest ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Deny access request URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-denyrequest ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET List access grants URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-listgrants ## Parameters ## Responses ## Try It --- ## Technical docs: POST Revoke access grant URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-revokegrant ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Resend access granted email URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-resendaccessemail ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get NDA details by token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getnda ## Parameters ## Responses ## Try It --- ## Technical docs: POST Preview NDA by token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-previewndabytoken ## Parameters ## Responses ## Try It --- ## Technical docs: POST Sign NDA URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-signnda ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Resend NDA email URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-resendnda ## Parameters ## Responses ## Try It --- ## Technical docs: POST Preview NDA PDF URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-previewnda ## Parameters ## Responses ## Try It --- ## Technical docs: POST Reclaim access URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-reclaimaccess ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get grant data by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getgrantbyaccesstoken ## Parameters ## Responses ## Try It --- ## Technical docs: GET List policies by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getpoliciesbyaccesstoken ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download all policies as watermarked PDF URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-downloadallpolicies ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download all policies as ZIP with individual PDFs URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-downloadallpoliciesaszip ## Parameters ## Responses ## Try It --- ## Technical docs: GET List compliance resources by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getcomplianceresourcesbyaccesstoken ## Parameters ## Responses ## Try It --- ## Technical docs: GET List additional documents by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-gettrustdocumentsbyaccesstoken ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download all additional documents as a ZIP by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-downloadalltrustdocuments ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download additional document by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-gettrustdocumenturlbyaccesstoken ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download compliance resource by access token URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getcomplianceresourceurlbyaccesstoken ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get FAQs for a trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getfaqs ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get overview section for a trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getpublicoverview ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get custom links for a trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getpubliccustomlinks ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get favicon URL for a trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getpublicfavicon ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get vendors/subprocessors for a trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-access/trustaccesscontroller-getpublicvendors ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get domain verification status URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-getdomainstatus ## Parameters ## Responses ## Try It --- ## Technical docs: POST Upload or replace a compliance certificate (PDF only) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-uploadcomplianceresource ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Generate a temporary signed URL for a compliance certificate URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-getcomplianceresourceurl ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST List uploaded compliance certificates for the organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-listcomplianceresources ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Upload an additional trust portal document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-uploadtrustdocument ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST List additional trust portal documents for the organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-listtrustdocuments ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Generate a temporary signed URL for a trust portal document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-gettrustdocumenturl ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Delete (deactivate) a trust portal document URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-deletetrustdocument ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Update trust portal overview section URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-updateoverview ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get trust portal overview URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-getoverview ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a custom link for trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-createcustomlink ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Update a custom link URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-updatecustomlink ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Delete a custom link URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-deletecustomlink ## Parameters ## Responses ## Try It --- ## Technical docs: POST Reorder custom links URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-reordercustomlinks ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET List custom links for trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-listcustomlinks ## Parameters ## Responses ## Try It --- ## Technical docs: POST Update vendor trust portal settings URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-updatevendortrustsettings ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET List vendors configured for trust portal URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/trust-portal/trustportalcontroller-listpublicvendors ## Parameters ## Responses ## Try It --- ## Technical docs: POST Trigger vendor risk assessment tasks for a batch of vendors (internal) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/internal-vendors/internalvendorautomationcontroller-triggervendorriskassessmentbatch ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: POST Trigger vendor risk assessment for a single vendor and return run info (internal) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/internal-vendors/internalvendorautomationcontroller-triggersinglevendorriskassessment ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get all vendors for an organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/vendors/vendorscontroller-getallvendors ## Parameters ## Responses ## Try It --- ## Technical docs: GET Get a vendor by ID URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/vendors/vendorscontroller-getvendorbyid ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new vendor URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/vendors/vendorscontroller-createvendor ## Parameters ## Request Body Vendor details to be created. ## Responses ## Try It --- ## Technical docs: PATCH Update an existing vendor URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/vendors/vendorscontroller-updatevendor ## Parameters ## Request Body Updated vendor details. ## Responses ## Try It --- ## Technical docs: DELETE Delete a vendor URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/vendors/vendorscontroller-deletevendor ## Parameters ## Responses ## Try It --- ## Technical docs: GET Handle invitation link redirection URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/auth/getinvitation ## Parameters ## Responses ## Try It --- ## Technical docs: GET Test database connection (E2E only) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/auth/testdatabaseconnection ## Responses ## Try It --- ## Technical docs: POST Perform a test login for E2E (Internal Only) URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/auth/testlogin ## Request Body User credentials and optional organization creation flag. ## Responses ## Try It --- ## Technical docs: POST Engage in AI chat URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/ai/chatwithai ## Parameters ## Request Body Messages for the AI chat. ## Responses ## Try It --- ## Technical docs: GET Retrieve cloud test findings for an organization. URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/cloud-tests/getcloudtestfindings ## Parameters ## Responses ## Try It --- ## Technical docs: GET Retrieve active cloud providers for an organization. URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/cloud-tests/getcloudtestproviders ## Parameters ## Responses ## Try It --- ## Technical docs: POST Analyze evidence form submissions using AI. URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/evidence-forms/analyzeevidenceform ## Parameters ## Request Body The evidence form data to be analyzed. Can be either meeting minutes or tabletop exercise details. ## Responses ## Try It --- ## Technical docs: GET Get a signed URL for an image stored in S3. URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/file-management/getimageurl ## Parameters ## Responses ## Try It --- ## Technical docs: POST Approve an organization by setting hasAccess to true (QA internal). URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/qa-internal/approveorganization ## Parameters ## Request Body The ID of the organization to approve. ## Responses ## Try It --- ## Technical docs: POST Delete a user and all associated data (QA internal). URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/qa-internal/deleteuser ## Parameters ## Request Body The ID and email of the user to delete. ## Responses ## Try It --- ## Technical docs: POST Resets an organization's data URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/retool-internal/resetorg ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: GET Get a specific secret URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/secrets/getsecret ## Parameters ## Responses ## Try It --- ## Technical docs: PUT Update a secret URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/secrets/updatesecret ## Parameters ## Request Body ## Responses ## Try It --- ## Technical docs: DELETE Delete a secret URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/secrets/deletesecret ## Parameters ## Responses ## Try It --- ## Technical docs: GET List all secrets for the organization URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/secrets/listsecrets ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a new secret URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/secrets/createsecret ## Request Body ## Responses ## Try It --- ## Technical docs: GET Retrieve user frameworks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/user-data/getuserframeworks ## Parameters ## Responses ## Try It --- ## Technical docs: POST Confirms a fleet policy and uploads attachments. URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/fleet-policies/confirmfleetpolicy ## Request Body Form data containing policy ID, policy name, organization ID, and image files. ## Responses ## Try It --- ## Technical docs: GET Retrieve device agent status URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/device-agent/getdeviceagentstatus ## Parameters ## Responses ## Try It --- ## Technical docs: GET Download a device agent installer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/device-agent/downloadagent ## Parameters ## Responses ## Try It --- ## Technical docs: HEAD Get metadata for a device agent installer URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/device-agent/headagentdownload ## Parameters ## Responses ## Try It --- ## Technical docs: POST Create a one-time download token for a device agent URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/api/device-agent/createdownloadtoken ## Request Body Request body containing organization ID, employee ID, and optionally, the target OS. ## Responses ## Try It --- ## User guide: Quickstart URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-1/quickstart Comp AI is an open-source compliance platform designed to help you achieve compliance with frameworks like SOC 2, ISO 27001, HIPAA, and GDPR. It automates evidence collection, policy management, and control implementation, giving you control over your data and infrastructure. This guide provides step-by-step instructions to get Comp AI running on your local machine for development and testing. By following these steps, you'll have a fully functional local instance of the platform. Before you begin, ensure you have the following software installed on your system: * **Node.js**: Version `20.x` or higher * **Bun**: Version `1.1.36` or higher * **PostgreSQL**: Version `15.x` or higher * **Docker Desktop** or **Docker Engine** (for database setup) ### Get the Comp AI Codebase First, you need to download the Comp AI project files to your local machine. 1. **Clone the repository:** ```sh git clone https://github.com/trycompai/comp.git ``` 2. **Navigate to the project directory:** ```sh cd comp ``` ### Install Project Dependencies Once you're in the project directory, install all necessary dependencies using Bun. ```sh bun install ``` ### Prepare Environment Variables Comp AI uses environment variables to manage configurations and credentials. You'll need to create `.env` files in specific locations and fill them with your settings. 1. **Copy example environment files:** These commands create the necessary `.env` files from their examples. ```sh cp apps/app/.env.example apps/app/.env cp apps/portal/.env.example apps/portal/.env cp packages/db/.env.example packages/db/.env ``` ```cmd copy apps\app\.env.example apps\app\.env copy apps\portal\.env.example apps\portal\.env copy packages\db\.env.example packages\db\.env ``` ```powershell Copy-Item apps\app\.env.example -Destination apps\app\.env Copy-Item apps\portal\.env.example -Destination apps\portal\.env Copy-Item packages\db\.env.example -Destination packages\db\.env ``` 2. **Fill in required variables for `apps/app/.env`:** Open the `apps/app/.env` file and add or update the following variables. ```env AUTH_SECRET="" DATABASE_URL="postgresql://user:password@host:port/database" RESEND_API_KEY="" NEXT_PUBLIC_PORTAL_URL="http://localhost:3002" REVALIDATION_SECRET="" ``` * **`AUTH_SECRET`** and **`REVALIDATION_SECRET`**: Generate secure random strings for these. You can use a command like `openssl rand -base64 32` in your terminal. * **`DATABASE_URL`**: This will be your PostgreSQL connection string. You'll configure the database in a later step. * **`RESEND_API_KEY`**: Obtain this from your Resend account (https://resend.com/api-keys). The `.env.example` files might not include `NEXT_PUBLIC_PORTAL_URL` and `REVALIDATION_SECRET`. Ensure you add these manually to your `apps/app/.env` file. ### Configure Cloud & Authentication Services Comp AI integrates with several external services for authentication, workflows, and data storage. You'll need to set these up. 1. **Trigger.dev (Workflows)** * Create an account at [https://cloud.trigger.dev](https://cloud.trigger.dev). * Create a new project and copy its Project ID. * Open the file `apps/app/trigger.config.ts` and update the `project` field with your Project ID: ```ts project: 'proj_****az***ywb**ob*'; // Replace with your actual Project ID ``` 2. **Google OAuth (Authentication)** * Go to the [Google Cloud OAuth Console](https://console.cloud.google.com/auth/clients). * Create a new OAuth client: * Select "Web Application" as the application type. * Give it a name, e.g., `comp_app`. * Add the following **Authorized Redirect URIs**: ``` http://localhost http://localhost:3000 http://localhost:3002 http://localhost:3000/api/auth/callback/google http://localhost:3002/api/auth/callback/google http://localhost:3000/auth http://localhost:3002/auth ``` * After creation, copy the `Client ID` (your `GOOGLE_ID`) and `Client Secret` (your `GOOGLE_SECRET`). * Add these to your `.env` files. If Google OAuth variables are not recognized from your `.env` files, you might need to hard-code them directly into `apps/portal/src/app/lib/auth.ts`. 3. **Redis (Upstash for Key-Value Store)** * Go to [https://console.upstash.com](https://console.upstash.com). * Create a new Redis database. * Copy the **Redis URL** and **TOKEN**. * Add these to your `.env` file. If Redis environment variables are not recognized, you might need to hard-code them into `packages/kv/src/index.ts`. ### Set up the Database Comp AI uses PostgreSQL. You'll use Docker to run a local PostgreSQL instance and then apply the necessary schema and data. 1. **Navigate to the database package:** ```sh cd packages/db ``` 2. **Start the PostgreSQL database using Docker:** ```sh bun run docker:up ``` The default credentials for the database are: * **Database name**: `comp` * **Username**: `postgres` * **Password**: `postgres` You can change the password by connecting to the database and running `ALTER USER postgres WITH PASSWORD 'new_password';`. 3. **Generate Prisma client:** ```sh bun run db:generate ``` 4. **Push the schema to the database:** ```sh bun run db:push ``` 5. **Optionally, seed the database with initial data:** ```sh bun run db:seed ``` 6. **Fix potential database function error:** If you encounter an error like `HINT: No function matches the given name and argument types...`, run the following command (replace `` with your PostgreSQL password): ```sh psql "postgresql://postgres:@localhost:5432/comp" -f ./prisma/functionDefinition.sql ``` Expected output: `CREATE FUNCTION` **Useful Database Commands:** * `bun run db:studio`: Open Prisma Studio to view and edit data. * `bun run db:migrate`: Run database migrations. * `bun run docker:down`: Stop the database container. * `bun run docker:clean`: Remove the database container and its volume. ### Start the Application After all configurations are complete, you can start the Comp AI application. 1. **Return to the root directory of the project:** ```sh cd ../.. ``` 2. **Start all applications in parallel:** ```sh bun run dev ``` Alternatively, if you have Turbo installed, you can use: ```sh turbo dev ``` If you don't have Turbo installed, you can install it globally using Bun: ```sh bun add -g turbo ``` 🎉 Congratulations! You now have a working local instance of Comp AI! ## Self-Hosting Comp AI While this guide focuses on local development, Comp AI also supports self-hosting for production environments. This typically involves Docker-based deployments. For detailed, up-to-date instructions on self-hosting, including environment variable references and Docker deployment steps, please refer to the official documentation: * [Docker Self-Hosting Guide](https://trycomp.ai/docs/self-hosting/docker) * [Environment Reference](https://trycomp.ai/docs/self-hosting/env-reference) --- ## User guide: First Workspace URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-1/first-workspace Your Workspace, also referred to as an "Organization" within the system, is your central hub for managing your team and associated resources. This guide will walk you through the initial setup and ongoing management of your workspace, including customizing its details and adding or managing team members. A Workspace is your team's dedicated environment where you can manage users, devices, and other settings specific to your organization. When you first sign up, a default workspace is usually created for you. ### Updating Your Workspace Details You can customize various aspects of your workspace, such as its name, branding, and integration settings. ### Access Workspace Settings Navigate to your workspace settings. The exact location might vary depending on your interface, but it's typically found under an "Organization Settings" or "Workspace Profile" section. ### Modify Details You can update the following information for your workspace: | Setting | Description | Example | | :------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- ## User guide: Policies URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-2/policies Policies are central to managing your organization's rules, guidelines, and compliance requirements. This feature allows you to create, manage, and track various policies, ensuring your organization adheres to internal standards and external regulations like SOC 2, ISO 27001, and GDPR. You can maintain different versions of each policy, allowing for drafting, review, and publication workflows. The system also offers an AI assistant to help you refine and improve your policy content, making compliance management more efficient. --- ### Key Concepts Before you start, it's helpful to understand a few key terms: * **Policy**: A formal statement of principles that guides and determines present and future decisions and actions. * **Policy Version**: A specific iteration of a policy. Policies often go through multiple drafts and revisions, each saved as a distinct version. * **Published Version**: A policy version that has been officially released and is accessible to relevant stakeholders. * **Active Version**: The currently enforced or most relevant published version of a policy. * **Policy Content**: The actual text and structure of the policy, typically managed in a rich text editor. --- ## Managing Policies This section covers how to create, view, update, and delete your organizational policies. ### View All Policies To see a list of all policies in your organization: 1. Navigate to the "Policies" section of the application. 2. A list displaying all policies, including their names, descriptions, and current statuses, will be shown. ### Create a New Policy You can create a new policy from scratch. 1. Go to the "Policies" section. 2. Click the "Create New Policy" button (or similar action). 3. Fill in the required details: * **Name**: A clear and concise title for your policy (e.g., "Data Privacy Policy"). * **Description** (Optional): A brief overview of what the policy covers. * **Content**: The main body of your policy. You will typically use a rich text editor for this. * **Status** (Optional): Initial status, such as `Draft`. * **Review Frequency** (Optional): How often this policy should be reviewed (e.g., `Yearly`). * **Department** (Optional): Which department this policy primarily applies to. * **Requires Signature** (Optional): Indicate if users need to sign this policy. * **Review Date** (Optional): A specific date for the next review. * **Assignee** (Optional): The user responsible for this policy. * **Approver** (Optional): The user who approved this policy. * **Policy Template** (Optional): If you're basing this on an existing template. 4. Click "Save" or "Create Policy". ### Update Policy Details You can modify a policy's general information at any time. 1. From the list of policies, select the policy you wish to update. 2. Click the "Edit" button (or similar icon). 3. Modify fields such as: * **Name** * **Description** * **Status** * **Review Frequency** * **Department** * **Requires Signature** * **Review Date** * **Assignee** * **Approver** * **Archive Policy**: You can also choose to archive a policy if it's no longer in use but needs to be retained for historical purposes. 4. Click "Save Changes". ### Delete a Policy If a policy is no longer needed, you can delete it. 1. From the list of policies, select the policy you wish to delete. 2. Click the "Delete" button (often represented by a trash can icon). 3. Confirm your decision when prompted. Deleting a policy will remove it and all its associated versions from the system. This action cannot be undone. Consider archiving policies instead of deleting them if you need to retain historical records. ### Download All Published Policies You can generate a single PDF document containing all your organization's published policies. 1. Navigate to the "Policies" section. 2. Look for an option like "Download All Policies" or "Export All Published Policies". 3. Click this option. The system will generate a PDF bundle with your organization's branding and provide a signed URL for you to download it. This feature is useful for audits, compliance checks, or providing a comprehensive policy manual to new employees. --- ## Managing Policy Versions Policies evolve over time. Version control allows you to track changes, draft new updates without affecting the live policy, and maintain a history of all revisions. ### View Policy Versions To see all versions associated with a specific policy: 1. Select the policy you are interested in from the main policies list. 2. Navigate to the "Versions" tab or section for that policy. 3. You will see a list of all versions, including their status (e.g., Draft, Published), creation date, and any associated changelog. ### Create a New Policy Version You can create a new version, often based on an existing one, to make updates without altering the currently active policy. 1. Go to the "Versions" section of a specific policy. 2. Click "Create New Version" (or similar). 3. You may have options: * **Base on existing version** (Optional): Select a `sourceVersionId` to copy content from an earlier version. If not specified, a new empty version might be created or it might copy from the active version. * **Changelog** (Optional): Add a brief note describing the purpose of this new version (e.g., "Initial draft for quarterly updates"). 4. Click "Create". A new draft version will be added to the policy. ### Update Policy Version Content Once a new version is created (or if you're editing an existing draft), you can modify its content. 1. From the policy's "Versions" list, select the specific version you want to edit. 2. Click the "Edit Content" button. 3. Use the rich text editor to make your desired changes to the policy text. 4. Click "Save Changes" to update the version's content. ### Publish a Policy Version When a policy version is ready for official release, you can publish it. 1. From the policy's "Versions" list, select the version you wish to publish. 2. Click the "Publish" button. 3. You will have options: * **Set as Active** (Optional): Choose whether this published version should immediately become the active, live policy. * **Changelog** (Optional): Add a note about the changes included in this published version (e.g., "Updated access controls section"). 4. Confirm the publication. ### Set an Active Policy Version You can designate any published version as the current active policy. 1. From the policy's "Versions" list, select the *published* version you want to make active. 2. Click the "Set as Active" button (or similar action). 3. Confirm your choice. This version will now be the primary policy in effect. ### Submit a Policy Version for Approval If your workflow requires formal approval, you can submit a version for review. 1. From the policy's "Versions" list, select the version you want to submit. 2. Click "Submit for Approval". 3. You will need to specify the `Approver ID` (the user who needs to approve this version). 4. Confirm the submission. The policy's status will likely change to `Needs Review`. ### Delete a Policy Version You can delete specific versions of a policy, especially if they are drafts or no longer relevant. 1. From the policy's "Versions" list, select the version you wish to delete. 2. Click the "Delete" button (often a trash can icon). 3. Confirm your decision. You typically cannot delete an active or published policy version directly. You may need to unpublish it or set another version as active first. --- ## AI Assistant for Policy Editing The AI assistant can help you draft, refine, and ensure the compliance of your policies. It acts as an expert GRC (Governance, Risk, and Compliance) editor. ### Access the AI Chat 1. Select the policy you want to work on from the main policies list. 2. Navigate to the policy's editing interface or a dedicated "AI Chat" section. ### Provide Instructions 1. In the chat interface, type your instructions or questions for the AI. * **Example**: "Update the data retention section to specify a 7-year retention period." * **Example**: "Review this policy for GDPR compliance and suggest improvements." * **Example**: "Explain the purpose of the 'Purpose' section." 2. Send your message to the AI. ### Review AI Suggestions The AI will stream its response, acting as a GRC expert. It can: * Help you understand and improve your policies. * Suggest specific changes. * Ensure policies remain compliant with relevant frameworks (e.g., SOC 2, ISO 27001, GDPR). * Maintain professional, clear language. When the AI suggests changes to the policy content, it will first explain what changes it will make and why. Then, it will provide the **COMPLETE updated policy content** within a code block labeled `policy`. You should copy this entire block to replace your current policy content. ### Apply AI-Suggested Changes 1. If the AI provides updated policy content in a `policy` code block, copy the entire content from that block. 2. Paste this content into your policy's content editor, replacing the existing text. 3. Save the policy version. --- ## Policy Attributes Reference Here's a quick reference for the various attributes you can set for your policies and their versions. ### Policy Status | Value | Description | | :-------------- | :------------------------------------------------ | | `draft` | The policy is under development and not yet final. | | `published` | The policy has been officially released. | | `needs_review` | The policy has been submitted for approval or review. | ### Review Frequency | Value | Description | | :---------- | :------------------------------------------------ | | `monthly` | Policy should be reviewed every month. | | `quarterly` | Policy should be reviewed every three months. | | `yearly` | Policy should be reviewed once a year. | ### Departments | Value | Description | | :------ | :------------------------------------------------ | | `none` | Policy does not apply to a specific department. | | `admin` | Applies to administrative functions. | | `gov` | Applies to governance-related functions. | | `hr` | Applies to Human Resources. | | `it` | Applies to Information Technology. | | `itsm` | Applies to IT Service Management. | | `qms` | Applies to Quality Management Systems. | --- ## User guide: Evidence URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-2/evidence This section guides you through using the Evidence feature, which helps your organization collect, manage, and review important information and files. Whether you need to submit documents for compliance, provide details for a task, or review submissions from others, this system streamlines the process. You will interact with pre-defined "Evidence Forms" to submit your contributions, and if you are a designated reviewer, you'll be able to review and manage these submissions. ### Key Concepts * **Evidence Forms**: These are standardized templates designed by your organization to collect specific types of information and files. Each form is tailored to a particular task or requirement. * **Submissions**: When you complete and send an Evidence Form, it becomes a submission. This includes all the data you entered and any files you attached. * **Review Process**: After evidence is submitted, it often goes through a review process. A designated reviewer will examine the submission and decide whether to approve or reject it. * **Attachments**: These are files (such as documents, images, or spreadsheets) that you upload and link to your evidence submission to provide supporting information. --- ### View Available Evidence Forms To see what evidence forms are available for your organization: 1. Navigate to the "Evidence" section of the application. 2. You will see a list of all pre-built evidence forms. 3. For each form, you can also see the date of the latest submission, if any, for your organization. ### Submit Evidence To submit evidence, you will fill out an Evidence Form and potentially attach files. 1. Select the specific Evidence Form you need to complete from the list of available forms. 2. Fill in all the required information in the form fields. 3. If the form requires attachments, use the upload feature to add your files. When uploading files for an evidence form, the system will process them and provide metadata that will be included in your submission. 4. Once all information is entered and files are attached, submit the form. ### View Your Submissions You can always check the status and details of the evidence you have submitted. 1. Go to the "Evidence" section. 2. Look for a section or filter that shows "My Submissions." 3. Here, you will see a list of all evidence forms you have submitted. 4. You can filter this list by a specific form type if needed. 5. You can also see how many of your submissions are currently pending review. ### Review Evidence Submissions (for Reviewers) If you are a designated reviewer, you will be notified when evidence requires your attention. 1. You will receive an email notification when someone requests your review for a single evidence submission or multiple submissions. The email will include a direct link to the submission(s) awaiting your review. 2. Click the link in the email or navigate to the relevant submission within the application. 3. Examine the submitted form data and any attached files. 4. Decide whether to **Approve** or **Reject** the submission. 5. If necessary, provide a reason for your decision, especially if rejecting. ### Download Attached Evidence Files If an evidence submission includes attachments, you can download them. 1. Access the specific evidence submission that contains the attachment you wish to download. 2. Locate the attachment within the submission details. 3. Click the download option for the attachment. The system will generate a secure, temporary link for you to download the file. Download links are temporary and will expire after a certain period (e.g., 15 minutes) for security reasons. If a link expires, simply request it again. ### Export Evidence Submissions to CSV You can export all submissions for a particular evidence form type into a CSV (Comma Separated Values) file for external analysis or record-keeping. 1. Navigate to the specific Evidence Form for which you want to export submissions. 2. Look for an "Export" or "Download CSV" option. 3. Click this option to download a CSV file containing all submissions for that form type. The file will be named according to the form type and the date of export. --- ## User guide: Risks URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-2/risks This page guides you through managing risks within your organization. The Risks feature allows you to identify, assess, track, and manage potential threats that could impact your operations. By documenting risks, their potential impact, likelihood, and planned treatment strategies, you can proactively address vulnerabilities and ensure business continuity. Each risk can be categorized, assigned to a department, and tracked through various statuses. You can define the initial likelihood and impact, as well as the residual likelihood and impact after applying treatment strategies. ### Key Concepts Understanding these terms will help you effectively manage risks: * **Risk Title**: A concise name for the risk. * **Description**: A detailed explanation of the risk, its potential causes, and consequences. * **Category**: A classification for the risk, helping to group similar threats (e.g., `Technology`). * **Department**: The organizational department primarily responsible for managing or being affected by the risk (e.g., `IT`). * **Status**: The current state of the risk, indicating whether it's active, being addressed, or resolved (e.g., `Open`). * **Likelihood**: The probability of the risk occurring (e.g., `Possible`, `Very Unlikely`). * **Impact**: The severity of the consequences if the risk materializes (e.g., `Major`, `Insignificant`). * **Residual Likelihood**: The estimated probability of the risk occurring *after* treatment strategies have been implemented. * **Residual Impact**: The estimated severity of the consequences if the risk materializes *after* treatment strategies have been implemented. * **Treatment Strategy Description**: A detailed plan outlining how the risk will be addressed. * **Treatment Strategy Type**: The approach chosen to handle the risk (e.g., `Mitigate`, `Accept`). * **Assignee ID**: The unique identifier of the user or member responsible for managing this specific risk. All risk management actions are performed within the context of your organization. Ensure you are operating under the correct organization ID. ## Managing Risks You can perform several actions to manage your organization's risks, including viewing, creating, updating, and deleting them. ### View All Risks To see a comprehensive list of all risks identified within your organization: 1. Navigate to the "Risks" section of the application. 2. The system will display a list of all risks, including their key details. ### View a Specific Risk To examine the details of an individual risk: 1. From the list of all risks, locate the risk you wish to view. 2. Click on the risk's entry or its unique identifier. 3. The system will display a detailed view of the selected risk, including all its attributes. ### Create a New Risk Follow these steps to add a new risk to your organization's register: 1. Navigate to the "Risks" section. 2. Look for an option like "Create New Risk" or a similar button. 3. Fill in the required and optional fields as described below: | Field | Description | | :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- ## User guide: Questionnaires URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-2/questionnaires The Questionnaires feature helps you efficiently manage and respond to security, compliance, and other types of questionnaires. Instead of manually answering each question, you can upload a questionnaire document, and the system can automatically extract the questions, generate answers based on your organization's knowledge base, and then export the completed questionnaire in various formats. This streamlines the process of responding to inquiries from partners, customers, or auditors. ### Key Concepts * **Questionnaire**: A document (like a PDF, spreadsheet, or text file) containing a list of questions that need to be answered. * **Organization's Knowledge Base**: This refers to the collection of documents, policies, and information specific to your organization that the system uses to find relevant answers. * **Auto-Answer**: An intelligent process that uses your organization's knowledge base to automatically generate responses for the questions in a questionnaire. * **Sources**: When an answer is generated, the system can provide references to the documents or policies from your knowledge base that were used to formulate that answer. * **Internal vs. External Source**: * **Internal**: You are processing the questionnaire within your organization's account. * **External**: A third party (e.g., a customer or auditor) is submitting a questionnaire to you, often through a secure portal using a special token. ### Workflow: Upload, Auto-Answer, and Export This is the most common way to use the Questionnaire feature, allowing you to quickly process and respond to a new questionnaire. ### Upload Your Questionnaire File You can upload a questionnaire file to extract its questions and prepare it for answering. 1. Navigate to the Questionnaire section of the application. 2. Select the option to "Upload and Process" or similar. 3. Choose your questionnaire file from your computer. * **Supported File Types**: PDF, image files (e.g., JPG, PNG), XLSX (Excel spreadsheets), CSV, and TXT files. 4. Specify the **Organization** this questionnaire belongs to. This tells the system which knowledge base to use for generating answers. 5. Optionally, choose the desired **Output Format** for the final answered questionnaire (PDF, CSV, or XLSX). If not specified, XLSX is often the default. 6. Initiate the upload. ### Monitor Auto-Answering Progress After uploading, the system will begin to automatically generate answers for the extracted questions. This process happens in several stages: 1. **Syncing Knowledge Base**: The system first ensures it has the most up-to-date information from your organization's knowledge base. 2. **Searching for Content**: It then searches your knowledge base for content relevant to each question. 3. **Generating Answers**: Finally, it uses the relevant content to formulate answers. During this process, you will typically see real-time updates on the progress, indicating how many questions have been processed and answered. ### Download the Answered Questionnaire Once the auto-answering process is complete, the system will provide you with the fully answered questionnaire. 1. The answered questionnaire will be automatically downloaded to your computer in the format you selected (PDF, CSV, or XLSX). 2. The filename will typically indicate it's an answered version of your original file. Larger questionnaire files or those with many complex questions may take longer to process and auto-answer. The system provides progress updates during this time. ### Managing Answers You have full control over the answers generated by the system or to add your own. ### Answer a Single Question If you need an answer for a specific question outside of a full questionnaire upload, or if an auto-generated answer needs refinement: 1. Locate the specific question you want to answer in the interface. 2. Trigger the "Generate Answer" or "Answer Question" action for that question. 3. The system will provide a generated answer, often with sources. ### Save or Update an Answer Whether an answer was auto-generated or you've written it manually, you can save or update it. 1. After generating an answer or typing a new one, review the content. 2. Click "Save Answer" or a similar button. 3. You can also specify if the answer was `generated` by the system or `manual` (entered by a user). 4. If available, you can also associate `sources` (documents, policies) with the answer to provide context. ### Delete an Answer If an answer is no longer needed or was entered incorrectly: 1. Locate the question with the answer you wish to remove. 2. Select the "Delete Answer" option. 3. Confirm the deletion when prompted. While the auto-answer feature is powerful, it relies on the quality and completeness of your organization's knowledge base. Always review auto-generated answers for accuracy and relevance before finalizing them. Manual adjustments and saving are recommended. ### Exporting Existing Questionnaires You can export questionnaires that have already been processed and saved in the system. ### Export a Questionnaire by ID If you have a questionnaire that was previously uploaded and processed, you can export it at any time. 1. Go to your list of saved questionnaires. 2. Select the questionnaire you wish to export. 3. Choose the desired **Output Format** (PDF, CSV, or XLSX). 4. Initiate the export. The file will be downloaded to your computer. ### Special Export for External Parties (Trust Portal) This feature is designed for scenarios where external parties (like customers or auditors) need to submit a questionnaire and receive an automatically answered version. ### Upload and Export via Trust Portal Token If you've been provided with a special Trust Access Token, you can use it to process and receive an answered questionnaire. 1. You will typically be directed to a specific portal or link. 2. Upload your questionnaire file (PDF, image, XLSX, CSV, TXT). 3. Enter the **Trust Access Token** provided to you. This token links the request to the correct organization's knowledge base. 4. The system will automatically process the questionnaire, generate answers, and then provide a download. * **Note**: When using a Trust Access Token, the system will automatically export the answered questionnaire as a **ZIP file** containing all available formats (PDF, CSV, and XLSX), regardless of any format you might have specified. 5. Download the ZIP file containing the answered questionnaire in all formats. Treat Trust Access Tokens like sensitive credentials. They grant access to your organization's knowledge base for answering questionnaires. Only share them with trusted external parties for their intended purpose. --- ## User guide: Manage Policies URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-3/manage-policies This guide explains how to manage your organization's policies, including creating, editing, publishing, and archiving them. Policies are essential for maintaining governance, risk, and compliance (GRC) standards within your organization. This feature provides robust version control, approval workflows, and even AI-powered assistance to help you maintain accurate and compliant documentation. You can manage policies and their versions, ensuring that your organization's guidelines are always up-to-date and accessible. ## Key Concepts Before you begin, it's helpful to understand a few key terms: * **Policy**: A formal document outlining rules, guidelines, or principles that govern actions within your organization. Examples include an "Information Security Policy" or a "Data Privacy Policy." * **Policy Version**: A specific iteration or snapshot of a policy at a given point in time. This allows you to track changes and revert to previous states if needed. * **Draft Version**: A policy version that is currently under development or review. It is not yet published or active and can be freely edited. * **Published Version**: A policy version that has been finalized, approved, and made available for organizational use. Once published, its content is generally immutable. * **Active Version**: Among the published versions, one is designated as the "active" version. This is the official and currently enforced policy that users should refer to. * **Pending Approval Version**: A draft version that has been submitted for review by designated approvers. It cannot be published or become active until it receives approval. ## Managing Policies This section covers the fundamental operations for handling your policies. ### View All Policies To see a list of all policies within your organization: 1. Navigate to the **Policies** section in the application. 2. A list of all policies will be displayed, showing their names, descriptions, and current status. ### View a Specific Policy To inspect the details of an individual policy: 1. From the list of all policies, click on the **name** or **view icon** next to the policy you wish to examine. 2. This will open the policy's detail page, where you can see its description, current active version, and a list of all its versions. ### Create a New Policy To establish a new policy for your organization: 1. On the main Policies page, click the **"Create New Policy"** button. 2. You will be prompted to enter a **Name** for the policy and an optional **Description**. 3. Click **"Save"** or **"Create"** to finalize the new policy. ### Update Policy Details You can modify the general information of an existing policy, such as its name or description. 1. Go to the detail page of the policy you want to update. 2. Click the **"Edit"** button (often represented by a pencil icon) next to the policy's name or description. 3. Make the necessary changes to the policy's **Name** or **Description**. 4. Click **"Save Changes"** to apply your updates. ### Delete a Policy You can permanently remove a policy from your system. 1. Go to the detail page of the policy you want to delete. 2. Look for a **"Delete Policy"** button or option (often represented by a trash can icon). 3. Confirm your decision when prompted. Deleting a policy is a permanent action and cannot be undone. All associated versions and history for that policy will also be removed. Proceed with caution. ## Managing Policy Versions Policies evolve over time, and version management is crucial for tracking changes and maintaining historical records. ### View Policy Versions To see all the different iterations of a policy: 1. Go to the detail page of the policy you are interested in. 2. Navigate to the **"Versions"** tab or section. 3. A list of all policy versions will be displayed, typically in descending order from newest to oldest, along with their status (Draft, Published, Active, Pending Approval). ### Create a New Policy Version (Draft) When you need to make changes to a policy, you should create a new draft version. 1. From the policy's detail page, go to the **"Versions"** tab. 2. Click the **"Create New Version"** button. 3. This will typically create a new draft based on the content of the current active version, or you might have an option to base it on another existing version. 4. The new draft version will now be available for editing. ### Update Policy Version Content You can modify the content of a draft policy version. 1. From the policy's detail page, go to the **"Versions"** tab. 2. Select the **draft version** you wish to edit. 3. Open the version for editing (e.g., by clicking an "Edit Content" button). 4. Make your desired changes to the policy content. 5. **Save** your changes. You can only update the content of **draft** versions. Published and pending approval versions are immutable and cannot be directly edited. If you need to change a published policy, you must create a new draft version. ### Delete a Policy Version You can remove draft versions that are no longer needed. 1. From the policy's detail page, go to the **"Versions"** tab. 2. Locate the **draft version** you want to delete. 3. Click the **"Delete"** button (often a trash can icon) next to that version. 4. Confirm your decision when prompted. Only **draft** versions can be deleted. Published and pending approval versions cannot be deleted to maintain historical integrity. ### Publish a Policy Version Once a draft version is complete and reviewed, you can publish it. 1. From the policy's detail page, go to the **"Versions"** tab. 2. Select the **draft version** you want to publish. 3. Click the **"Publish"** button. 4. You may be asked to confirm or provide a brief description of the changes. 5. After publishing, the version will become a "Published" version and can optionally be set as the "Active" version. ### Set an Active Policy Version To make a published version the official, currently enforced policy: 1. From the policy's detail page, go to the **"Versions"** tab. 2. Locate the **published version** you want to make active. 3. Click the **"Set as Active"** button or option next to that version. 4. Confirm your choice. The selected version will now be marked as the "Active" policy. ### Submit a Version for Approval If your organization uses an approval workflow, you can submit a draft for review. 1. From the policy's detail page, go to the **"Versions"** tab. 2. Select the **draft version** you wish to submit for approval. 3. Click the **"Submit for Approval"** button. 4. You may be prompted to add comments for the approvers. 5. The version's status will change to "Pending Approval," and it will be sent to the designated approvers. ## AI-Powered Policy Assistance Leverage artificial intelligence to help you draft, refine, and ensure the compliance of your policies. ### Chat with AI about a Policy The AI assistant acts as an expert GRC (Governance, Risk, and Compliance) policy editor, providing suggestions and making changes based on your instructions. 1. While editing a policy version, look for an **"AI Assistant"** or **"Chat with AI"** option. 2. A chat interface will appear, showing the current policy content. 3. Type your instructions or questions into the chat. For example: * "Suggest improvements for GDPR compliance." * "Rephrase this section to be clearer." * "Add a section about data retention policies." 4. The AI will respond with explanations and, if you ask it to make changes, will provide the **complete updated policy content** in a markdown code block. When the AI provides updated policy content, it will always include the **entire policy**, not just the changed sections. This is because the content in the `policy` code block is designed to replace the entire current policy. ## Downloading Policies You can download all your published policies as a single, branded PDF document. ### Download All Published Policies This feature is useful for audits, external sharing, or creating a comprehensive policy manual. 1. Navigate to the main **Policies** section. 2. Look for a **"Download All Policies"** or similar button. 3. Clicking this button will generate a PDF bundle of all currently published policies, including your organization's branding. 4. You will receive a signed URL to download the generated PDF. Only **published** policies are included in the PDF bundle. Draft or pending approval policies will not be part of the download. --- ## User guide: Upload Evidence URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-3/upload-evidence This feature allows you to securely upload files that serve as evidence or supporting documentation within the system. These files are typically associated with specific records, such as Evidence Forms, to provide necessary context and proof. Once uploaded, these files are stored securely and can be accessed or downloaded as needed. Uploading evidence ensures that all relevant information is centrally located and easily auditable, helping you maintain comprehensive records for compliance and operational transparency. ### Key Concepts Before you upload evidence, it's helpful to understand a few key terms: * **Evidence Forms**: These are structured digital forms used to collect specific information and often require supporting documents or files as evidence. Uploading evidence typically links it to a particular field or submission within an Evidence Form. * **Base64 Encoding**: For security and transfer efficiency, files are not sent directly. Instead, they must be converted into a special text format called Base64. This process transforms the binary data of your file (like an image or PDF) into a string of characters that can be easily transmitted. * **MIME Type**: This is a standard way to classify the type of content a file holds (e.g., `application/pdf` for a PDF document, `image/png` for a PNG image, `text/plain` for a plain text file). Providing the correct MIME type helps the system handle your file appropriately. For security reasons, certain file types that could potentially execute malicious code are blocked from being uploaded. Always ensure your files are safe and do not fall into the blocked categories. ### How to Upload Evidence To upload a file as evidence, you'll need to prepare the file and provide its details. ### Prepare Your File First, you need to convert your file into a Base64 encoded string. This is a common process that can be done using various tools or programming libraries. For example, if you have an image file, you would convert its content into a long string of characters. ### Gather File Information You will need the following details about your file: * **File Name**: The original name of your file (e.g., `report.pdf`, `screenshot.png`). * **File Type (MIME Type)**: The standard identifier for your file's content type (e.g., `application/pdf`, `image/jpeg`). * **File Data**: The Base64 encoded string of your file's content. * **Description (Optional)**: A brief explanation of what the file contains or its relevance. ### Submit the Upload Once you have the necessary information, you can submit the upload request. The system will process your file and return metadata about the newly uploaded evidence. Here's an example of the information you would provide: ```json { "fileName": "meeting-notes-q4.pdf", "fileType": "application/pdf", "fileData": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==", "description": "Meeting notes from Q4 planning session" } ``` The `fileData` field will contain a much longer Base64 string representing your actual file content. The example above is a very short placeholder. ### File Type Restrictions To maintain system security, certain file types are not permitted for upload. These are typically executable files or scripts that could pose a risk. The following MIME types are blocked: | Category | MIME Types | | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | **File Name** | `fileName` | string | Required | The name of the file, including its extension (e.g., `document.pdf`). Maximum length is 255 characters. --- ## User guide: Track Remediation URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-3/track-remediation This guide explains how to use the system to track and manage the remediation of identified issues, referred to as "findings." Effective remediation tracking ensures that all issues are addressed promptly, responsibilities are clear, and progress is transparent. The system provides tools to manage the lifecycle of findings, from their initial identification to their final resolution. This includes updating their status, assigning them to team members, adding comments for collaboration, and reviewing a complete history of changes. You'll also receive notifications about important updates to help you stay informed. ### Key Concepts * **Findings**: These are identified issues, vulnerabilities, or non-compliance points that require attention and resolution. Each finding has a lifecycle that you can track. * **Finding Status**: This indicates the current stage of a finding's remediation process. Common statuses include: * **Open**: The finding has been identified and needs to be addressed. * **In Progress**: Work has begun to remediate the finding. * **Resolved**: The finding has been addressed, but may still require verification. * **Closed**: The finding has been fully remediated and verified. * **Comments**: These allow you to communicate with team members directly within the context of a finding or related task. You can ask questions, provide updates, or share relevant information. * **Tasks**: While not explicitly detailed here, findings are often associated with tasks that represent the specific actions needed for remediation. Changes to these tasks (like assignee or status) can trigger notifications. ### Tracking Remediation Progress The primary way to track remediation is by updating the status of findings and collaborating through comments. ### View Findings You can view all findings across your organization or filter them by specific criteria. 1. Navigate to the "Findings" section in the application. 2. To see all findings, select the "Organization" view. 3. To narrow down the list, you can filter by: * **Status**: For example, view only "Open" or "In Progress" findings. * **Associated Task**: If a finding is linked to a specific task. * **Evidence Submission**: If a finding is related to a particular evidence submission. * **Evidence Form Type**: To see findings from specific types of evidence forms (e.g., "access-request"). ### Update a Finding's Status Changing a finding's status is crucial for reflecting its current remediation stage. 1. Locate the specific finding you wish to update. 2. Open the finding's details page. 3. Look for the status field, usually presented as a dropdown or button. 4. Select the appropriate new status (e.g., "In Progress," "Resolved"). 5. Save your changes. Changing a finding's status may be restricted based on your user role. For example, only Auditors or Platform Admins might be able to mark a finding as "Closed." If you cannot change a status, contact an administrator. ### Add Comments to a Finding Comments facilitate communication and provide context for remediation efforts. 1. Navigate to the finding or task you want to comment on. 2. Locate the comments section, typically at the bottom of the details page. 3. Type your message in the comment box. 4. You can mention other users by typing `@` followed by their name, which will send them a notification. 5. Click "Post Comment" or similar to add your comment. You can also update or delete your own comments if needed. ### Review Finding History The history log provides an audit trail of all changes made to a finding. 1. Open the details page for the finding you are interested in. 2. Look for a section labeled "Activity," "History," or "Audit Log." 3. This section will display a chronological list of events, such as status changes, assignee changes, and comments, along with who made the change and when. ### Notifications To keep you informed about remediation progress and collaboration, the system sends email notifications for key events: * **Task Status Changed**: You will receive an email if the status of a task you are involved with changes (e.g., from "Open" to "In Progress"). * **Task Assignee Changed**: If a task you are assigned to, or a task you created, is reassigned to someone else, you will be notified. * **Comment Mention**: If another user mentions you in a comment on a finding or task, you will receive an email notification with the comment's content and a link to view it. You can manage your email notification preferences to control which types of alerts you receive. Look for a link to "Manage your email preferences" in the footer of any notification email. ### User Roles and Permissions Certain actions related to findings are restricted to specific user roles to maintain control and accountability: Only users with `Auditor`, `Admin`, or `Owner` roles, or Platform Admins, are authorized to create, update, or delete findings. Regular members can view findings and add comments, but cannot modify the finding's core details or status. While many users might be able to update a finding's status to "In Progress" or "Resolved," specific transitions, such as marking a finding as "Closed," might be reserved for `Auditor`, `Admin`, or `Owner` roles. --- ## User guide: Organization Settings URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-4/organization-settings This section allows you to manage the core properties and settings of your organization. Here, you can update your organization's name, branding elements like the logo and primary color, and other essential details. You can also perform critical actions such as transferring ownership or, if necessary, deleting the entire organization. Managing these settings ensures your organization's profile is accurate and reflects your current needs. ### Viewing Your Organization's Settings You can view all the current details of your organization, including its name, unique identifier (slug), logo, website, and other configured properties. This overview helps you verify the current state of your organization's profile. ### Updating Organization Details You can modify various aspects of your organization's profile. This includes general information, branding, and specific feature-related settings. ### Navigate to Organization Settings Access your organization's settings page within the application. This is typically found in a "Settings" or "Admin" section. ### Edit the desired fields Locate the fields you wish to change. The following properties can be updated: | Setting Name | Description | | :----------- | :---------- | | **Name** | The display name of your organization. | | **Slug** | A unique, user-friendly identifier for your organization, often used in URLs. | | **Logo** | The URL to your organization's logo image. | | **Metadata** | Additional data associated with your organization. | | **Website** | Your organization's official website URL. | | **Onboarding Completed** | Indicates whether the initial onboarding process for the organization has been marked as complete. | | **Has Access** | Controls general access to the organization. | | **Fleet DM Label ID** | An identifier related to Fleet Device Management. | | **Is Fleet Setup Completed** | Indicates whether the Fleet Device Management setup is complete. | | **Primary Color** | The main brand color for your organization, typically in hexadecimal format (e.g., `#3B82F6`). | ### Save your changes After making your desired edits, save the changes. The system will update your organization's profile with the new information. ### Transferring Organization Ownership Transferring ownership is a critical action that assigns the highest level of administrative control over your organization to another member. The new owner will have full permissions, including the ability to manage other members, update settings, and delete the organization. * **Irreversible Action**: Once ownership is transferred, you will no longer be the owner. * **Existing Member**: The new owner must already be a member of your organization. * **Permissions**: Ensure the new owner is trustworthy and understands the responsibilities of organization ownership. ### Access the Ownership Transfer section Navigate to the organization settings and find the section dedicated to ownership transfer. ### Provide the new owner's ID You will need to enter the unique identifier (ID) of the member you wish to designate as the new owner. If you are performing this action using an API key, you might also need to explicitly provide your own user ID (the current owner's ID) in the request to confirm the transfer. When using the application's user interface, your ID is automatically recognized. ### Confirm the transfer Review the details and confirm the ownership transfer. A confirmation prompt may appear to prevent accidental transfers. ### Deleting an Organization Deleting an organization is a permanent and irreversible action. This will remove all associated data, members, and resources. Deleting your organization cannot be undone. All data, configurations, and associated resources will be permanently removed. Proceed with extreme caution. ### Navigate to Organization Settings Go to your organization's settings page. ### Locate the Delete Organization option Find the section or button specifically for deleting the organization. This is often clearly labeled and may be separated from other settings. ### Confirm deletion You will typically be asked to confirm this action, often by typing the organization's name or ID, to ensure you understand the gravity of the operation. ### Execute deletion Once confirmed, the organization and all its data will be permanently deleted. ### Retrieving Your Organization's Primary Color You can retrieve the primary color configured for your organization. This color is often used for branding and theming within the application or for external integrations. The primary color can be retrieved even without full authentication if a specific access token is provided. This allows for public-facing elements to adopt your organization's branding without requiring a user to log in. The primary color is returned in a hexadecimal format (e.g., `#3B82F6`). --- ## User guide: People Access URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-4/people-access This section of the documentation explains how to manage people, referred to as "members," within your organization. This includes adding new members, viewing their details, updating their information, and removing them. By managing members, you control who has access to your organization's resources and what permissions they hold. All actions related to people management are performed within the context of your specific organization. ### Key Concepts * **Member**: An individual user associated with your organization in the system. Each member has a unique user ID, and can have a role, department, and other attributes. * **Organization**: Your dedicated workspace or company account within the system. All members belong to an organization. * **Role**: A set of permissions assigned to a member, determining what actions they can perform. Common roles might include `admin`, `member`, or `owner`. The `owner` role typically has the highest level of access and can perform sensitive operations. * **User ID**: A unique identifier for a user, often provided by an external identity management system. This ID links a system user to a member in your organization. * **Fleet DM Label ID**: An optional identifier used for integrating with Fleet Device Management, allowing you to associate members with specific device groups or labels. When interacting with the system programmatically (e.g., via API), you will need to provide your `X-Organization-Id` in the request header to specify which organization you are managing members for. ### Managing Members You can perform various operations to manage the members of your organization. ### View All Members To retrieve a list of all members currently associated with your organization: 1. Access the people management interface or send a request to the appropriate API endpoint. 2. The system will return a list of all members, including their details such as user ID, role, department, and activity status. ### Add a Single Member You can add new members to your organization one by one. 1. Prepare the details for the new member. At a minimum, you will need their `userId` and `role`. 2. Provide the member's information to the system. **Example Member Details:** ```json { "userId": "usr_abc123def456", "role": "admin", "department": "it", "isActive": true, "fleetDmLabelId": 123 } ``` ### Add Multiple Members (Bulk Upload) For adding many members at once, you can use the bulk creation feature. 1. Compile a list of member details, where each item in the list is a new member to be added. 2. Submit this list to the system. You can add a maximum of 1000 members in a single bulk request. **Example Bulk Member Details:** ```json { "members": [ { "userId": "usr_abc123def456", "role": "admin", "department": "it", "isActive": true, "fleetDmLabelId": 123 }, { "userId": "usr_def456ghi789", "role": "member", "department": "hr", "isActive": true } ] } ``` ### View Specific Member Details To see the detailed information for a particular member: 1. Identify the unique ID of the member you wish to view. 2. Request the member's details using their ID. 3. The system will return all available information for that member. ### Update Member Information You can modify existing member details, such as their role, department, or activity status. 1. Identify the unique ID of the member you wish to update. 2. Provide the updated information. Only include the fields you want to change. **Example Update Details (changing role and deactivating):** ```json { "role": "member", "isActive": false } ``` ### Deactivate a Member Deactivating a member (setting `isActive` to `false`) is a "soft delete." The member's record remains in the system, but they will no longer have active access. 1. Follow the "Update Member Information" steps. 2. Set the `isActive` field to `false` in the update request. ### Remove a Host from a Member This action allows you to disassociate a specific host device from a member. 1. Identify the unique ID of the member and the numerical ID of the host you want to remove. 2. Submit the request to remove the host. This operation typically requires the `owner` role within the organization. ### Delete a Member To permanently remove a member from your organization: 1. Identify the unique ID of the member you wish to delete. 2. Confirm the deletion request. Deleting a member is a permanent action and cannot be undone. Consider deactivating a member first if you might need their record later. ### Unlink a Device from a Member This action allows you to remove any associated device information from a member's profile without deleting the member themselves. 1. Identify the unique ID of the member from whom you want to unlink a device. 2. Submit the request to unlink the device. --- ## User guide: User Issues URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-5/user-issues When using Comp AI, you might occasionally encounter issues related to accessing the platform or its API. These issues are typically related to **authentication** (verifying who you are) or **authorization** (determining what you're allowed to do). This guide explains common access problems and how to resolve them, ensuring you can securely and effectively use Comp AI. ### Key Concepts Before diving into specific issues, understanding a few key terms will be helpful: * **Authentication**: The process of verifying your identity. This could be by logging in with your username and password, or by providing a secret API Key. * **Authorization**: After you're authenticated, authorization determines what resources or actions you are permitted to access or perform within Comp AI. * **API Key**: A unique, secret code that identifies your application or service when it communicates with the Comp AI API. It acts like a password for your automated tools. * **JWT (JSON Web Token)**: A secure, digitally signed token used to verify your identity after you log in to the Comp AI web application. It represents your active session. * **Organization ID**: A unique identifier for your organization within Comp AI. Many actions require specifying which organization you are performing them for. ### Common Access Issues and Solutions Here are some common issues you might encounter and steps to resolve them. #### 1. Missing or Invalid API Key This issue occurs when you are trying to access the Comp AI API using an API Key, but the key is either not provided, incorrectly formatted, or no longer valid. API Keys are typically used for programmatic access to Comp AI, such as integrating with other systems or running automated tasks. **Symptoms:** You might receive error messages like: * `X-API-Key header is required` * `Invalid API key format` * `Invalid or expired API key` ### Check if the API Key is provided Ensure that your request includes the `X-API-Key` header with your valid API Key. For example, in an API request, it should look like: ``` X-API-Key: your_api_key_here ``` ### Verify API Key format Make sure the API Key is correctly copied and pasted without any extra spaces or characters. ### Validate API Key expiration and status API Keys can expire or be revoked. If you suspect your key is no longer valid, you may need to generate a new one within your Comp AI account settings or contact your organization's administrator. #### 2. Invalid or Expired Login Session (JWT) This issue typically affects users interacting with the Comp AI web application or client applications that rely on your logged-in session. Your session token (JWT) might have expired or become invalid. **Symptoms:** You might be redirected to the login page, or receive error messages such as: * `Authentication token is invalid. Please log out and log back in to refresh your session.` * `Invalid or expired JWT token` ### Log out and log back in The most common solution for an expired or invalid session is to simply log out of Comp AI and then log back in. This will generate a new, valid session token. #### 3. Missing Organization Context for Logged-in Users When you are logged into Comp AI (using a JWT), many actions require you to specify which organization you are working within. If this context is missing, your request will be denied. **Symptoms:** You might receive an error message like: * `Organization context required: X-Organization-Id header is mandatory for JWT authentication` ### Provide the X-Organization-Id header Ensure that your request includes the `X-Organization-Id` header with the unique identifier of the organization you wish to access. This is crucial for all authenticated actions when using a JWT. ``` X-Organization-Id: your_organization_id_here ``` #### 4. User Not Authorized for Organization Even if you are logged in and provide an `X-Organization-Id`, you must be a member of that specific organization to access its resources. **Symptoms:** You might receive an error message like: * `User does not have access to organization: your_organization_id_here` ### Contact your organization administrator If you believe you should have access to a particular organization, reach out to an administrator within that organization. They can add you as a member or adjust your roles and permissions. #### 5. Cross-Origin Resource Sharing (CORS) Errors CORS errors typically occur in web browsers when a web page tries to make requests to a server (like Comp AI's API) that is on a different domain than the web page itself. This is a security measure. Comp AI is configured to allow access from its official web application domains and common local development environments (e.g., `localhost`). If you are developing a custom application, ensure your development server's origin is correctly configured. **Symptoms:** You might see error messages in your browser's developer console related to CORS, such as: * `Access to XMLHttpRequest at '...' from origin '...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.` ### Verify your application's origin If you are developing a custom application, ensure that the domain where your application is hosted is among the allowed origins for Comp AI. For local development, `http://localhost:3000`, `http://localhost:3001`, and `http://127.0.0.1:3000` are typically allowed. ### Contact support if persistent If you encounter CORS errors from an officially supported Comp AI application or a correctly configured custom application, please contact support. #### 6. Internal System Errors Very rarely, you might encounter an error message indicating a problem with Comp AI's internal configuration or services. These are not typically user-facing issues but indicate a system-level problem. **Symptoms:** You might receive error messages like: * `Cannot connect to authentication service. Please check BETTER_AUTH_URL configuration.` * `Internal access is not configured` (in specific scenarios) * `Invalid internal token` (in specific scenarios) ### Contact Comp AI support These errors indicate a problem with the Comp AI service itself. Please report the issue to Comp AI support, providing any error messages and details about what you were doing when the error occurred. ### Tips for Troubleshooting * **Check Headers Carefully**: Many authentication and authorization issues stem from missing or incorrect HTTP headers (`X-API-Key`, `Authorization`, `X-Organization-Id`). Double-check their presence and values. * **Keep API Keys Secure**: Treat your API Keys like passwords. Do not share them publicly or embed them directly in client-side code. * **Refresh Your Session**: If you're having trouble with the web application, logging out and logging back in often resolves session-related issues. * **Provide Context**: Always ensure you're providing the necessary `X-Organization-Id` when interacting with organization-specific resources. * **Contact Support**: If you've followed these steps and are still experiencing issues, don't hesitate to contact Comp AI support with details about the problem, including any error messages you received. --- ## User guide: Content Problems URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-5/content-problems The system processes various types of content, such as documents uploaded to your Knowledge Base or questionnaires you want to auto-answer. While the system is designed to handle a wide range of content, sometimes issues can occur during processing, leading to "content problems." These problems can manifest as documents failing to process or questions not being answered automatically. Understanding how to identify and address these issues ensures your content is effectively utilized by the system. ## Identifying Content Problems ### Knowledge Base Document Processing Failures When you upload documents to your Knowledge Base, they go through a processing phase to extract information and make it available for answering questions. Sometimes, this process can fail. ### Check Document Status Navigate to your Knowledge Base section. You will see a list of all uploaded documents. Each document will display its **Processing Status**. ### Understand Statuses Observe the status of your documents: - **Pending**: The document is waiting to be processed. - **Processing**: The system is actively working on the document. - **Completed**: The document has been successfully processed, and its content is available for use. - **Failed**: The system encountered an error and could not process the document. If a document's status is **Failed**, its content will not be used by the system to generate answers. You will need to investigate the cause or re-upload the document. ### Questionnaire Auto-Answering Errors When you use the auto-answer feature for a questionnaire, the system attempts to generate answers based on your Knowledge Base. Individual questions or the entire auto-answering process can encounter issues. ### Review Auto-Answered Questionnaires After initiating an auto-answer process, carefully review the generated answers within the questionnaire. ### Look for Missing or Error Messages If a question could not be answered, you might observe: - A blank answer field where an answer was expected. - An explicit error message indicating why the answer generation failed for that specific question. ### Automation Failure Notifications The system can send email notifications if an automation related to content processing (e.g., a task that involves content processing) encounters failures. ### Check Your Email for Automation Failure Alerts You might receive an email with a subject like "Automation Failures" if a task involving content processing has issues. ### Review the Email Details The email will provide key information, including: - The number of automations that failed. - The specific task title associated with the failure. - The organization where the failure occurred. - A direct link to view the task for more details. ## Common Causes and Solutions ### Knowledge Base Document Failures Document processing can fail due to several reasons: - **Unsupported file formats**: Ensure your document is in a supported format (e.g., PDF, common image formats, XLSX, CSV, TXT). - **Corrupted files**: The file might be damaged or unreadable. - **Content issues**: The document might contain content that the system cannot parse or understand effectively (e.g., extremely complex layouts, scanned images without OCR). - **System errors**: Less commonly, an internal system issue might temporarily prevent processing. **What to do:** ### Re-upload the Document Try uploading the document again. Sometimes, transient issues can cause a failure that resolves on a second attempt. ### Check File Integrity and Format Verify that the file is not corrupted and is in a common, supported format. If it's a less common format, try converting it to PDF or plain text. ### Simplify Content (if applicable) If the document has complex layouts, many images, or unusual fonts, try creating a simpler version (e.g., a plain text version or a PDF with selectable text). ### Contact Support If problems persist after trying the above steps, gather details about the document and any error messages you observed, then contact support for assistance. ### Questionnaire Auto-Answering Failures Questions might not be auto-answered due to: - **Lack of relevant information**: Your Knowledge Base might not contain sufficient or relevant information to answer the specific question. - **Ambiguous questions**: The question might be phrased in a way that the AI cannot confidently match to your Knowledge Base content. - **System limitations**: The AI model might not be able to generate a coherent answer even with seemingly relevant content. **What to do:** ### Review Your Knowledge Base Ensure your Knowledge Base contains documents that thoroughly cover the topics related to the unanswered questions. Upload more relevant content if needed. ### Manually Answer the Question If the system cannot auto-answer, you can always provide a manual answer directly within the questionnaire. ### Refine Questions (if possible) If you have control over the questionnaire, try rephrasing ambiguous questions to be more direct and specific. ## Managing Problematic Content ### Deleting Knowledge Base Documents If a document consistently fails to process or is no longer relevant, you can remove it from your Knowledge Base. ### Locate the Document Go to your Knowledge Base section where your documents are listed. ### Delete the Document Find the document you want to remove and use the delete option provided (e.g., a trash can icon or a "Delete" button). Confirm the deletion when prompted. ### Deleting Questionnaire Answers If an auto-generated answer is incorrect, or you want to remove a manual answer, you can delete it from the questionnaire. ### Navigate to the Questionnaire Open the specific questionnaire you are working on. ### Find the Answer Locate the question whose answer you wish to delete. ### Remove the Answer Use the delete option associated with that answer. This might be a button next to the answer field or within an edit menu. The system also provides an advanced option to delete *all* manual answers for your organization. Use this feature with extreme caution as it is irreversible and will remove all manually provided answers across your entire organization's knowledge base. This is typically not needed for individual content problems. --- ## User guide: Connected Tools URL: https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/guide/section-6/connected-tools Connected Tools allow you to integrate our platform with various external services, enhancing its capabilities by connecting to your existing infrastructure and applications. These integrations enable features like automated employee data synchronization, cloud security posture management, and browser-based task automation. By connecting your tools, you can centralize data, automate routine tasks, and gain deeper insights into your organization's security and compliance posture, all from within our platform. This page guides you through setting up and managing these valuable connections. ### Key Concepts Before you begin, understanding a few key terms will be helpful: * **Provider**: An external service or application you want to connect to (e.g., AWS, Google Workspace, Rippling, JumpCloud, Ramp). * **Connection**: A specific link established between our platform and one of your external service accounts. Each connection stores the necessary credentials and configuration to interact with that service. * **Authentication Type**: The method used to verify your identity and grant our platform access to your external service. Common types include: * **API Key**: A secret key or token you provide directly. * **OAuth2**: A secure authorization flow where you grant permission through the provider's website, without sharing your direct login credentials. * **Custom**: Specific credentials tailored to a particular provider, such as IAM Role ARN and External ID for AWS. * **Employee Sync**: A feature that automatically imports and manages your organization's user accounts by synchronizing with an external Identity Provider (IdP) or Human Resources Information System (HRIS). This ensures that user statuses (active, suspended, removed) are kept up-to-date. * **Cloud Security Scan**: A process that analyzes your connected cloud environments for security vulnerabilities, misconfigurations, and compliance deviations, often leveraging services like AWS Security Hub. * **Browser Automation**: A capability to record and replay browser actions, allowing you to automate repetitive web-based tasks or data collection from web applications. --- ### Connecting a New Tool Connecting a new tool typically involves selecting the provider, providing authentication details, and confirming the connection. ### Browse Available Providers Navigate to the "Integrations" or "Connected Tools" section in your platform settings. You will see a list of all available providers. ### Select a Provider Choose the tool you wish to connect. The platform will guide you through the specific authentication steps required for that provider. ### Provide Authentication Details Depending on the provider, you will either: * **Be redirected to the provider's website (OAuth2)**: You'll log in to the provider and grant our platform the necessary permissions. After authorization, you'll be redirected back to our platform. * **Enter API keys or other credentials directly**: You'll copy and paste API keys, tokens, or other required information into designated fields. * **Enter custom credentials (e.g., AWS)**: For providers like AWS, you'll provide specific details such as an IAM Role ARN and an External ID. Ensure that your browser allows pop-ups and redirects, as the OAuth2 flow will temporarily take you to the provider's website. ### Validate and Activate the Connection After providing the credentials, the platform will attempt to validate them. If successful, your connection will be activated. For some providers, like AWS, this validation includes checking for necessary permissions and service enablement (e.g., Security Hub). For AWS connections, the platform verifies that: 1. The provided IAM Role ARN and External ID are correct and allow our platform to assume the role. 2. AWS Security Hub is enabled in all specified AWS regions. If validation fails, you will receive a specific error message guiding you on how to resolve the issue. --- ### Managing Existing Connections You can view, test, update, and remove your connected tools at any time. ### View Your Connections Access the "Integrations" or "Connected Tools" section to see a list of all your active and inactive connections. Each connection will display its status (e.g., active, error, paused) and last sync time. ### Test a Connection If you suspect an issue with a connection or want to verify its credentials, you can trigger a connection test. This re-validates the credentials and updates the connection's status. ### Pause or Resume a Connection You can temporarily pause a connection to stop all automated activities associated with it. When you're ready to resume, simply activate it again. ### Update Credentials For connections using API keys or custom authentication, you can update the stored credentials. For OAuth2 connections, you typically need to disconnect and re-establish the connection if the authorization expires or needs to be changed. OAuth2 integrations often rely on access tokens that can expire. While the platform attempts to refresh these tokens automatically, if a refresh fails, you may need to disconnect and reconnect the integration to re-authorize access. ### Disconnect or Delete a Connection * **Disconnect**: This performs a soft delete, marking the connection as inactive but retaining its history. * **Delete**: This permanently removes the connection and all associated data from the platform. Use this option with caution. --- ### Employee Sync The Employee Sync feature automates the management of user accounts within your organization by integrating with your HRIS or Identity Provider (IdP). ### Connect an Employee Sync Provider Follow the general steps above to connect one of the supported providers: * Google Workspace * Rippling * Ramp * JumpCloud ### Set Your Employee Sync Provider Once connected, you need to designate which connected tool will be your primary source for employee data. 1. Go to the "Integrations" or "Connected Tools" section. 2. Find the "Employee Sync Provider" setting. 3. Select your desired active connection (e.g., Google Workspace, Rippling) from the dropdown list. 4. Save your changes. When an employee sync provider is active: * Users found in the external system will be imported or reactivated in our platform. * Users marked as suspended, inactive, or removed in the external system will be deactivated in our platform. * Changes made directly in our platform for users managed by the sync provider may be overwritten during the next sync. ### Trigger a Manual Sync While employee syncs often run automatically on a schedule, you can manually trigger a sync at any time from the provider's connection details page. This is useful after making significant changes in your HRIS/IdP or to quickly update user statuses. --- ### Cloud Security Scans (e.g., AWS Security Hub) For cloud environments, you can connect your accounts to perform automated security scans and identify potential risks. ### Connect Your Cloud Provider Follow the general steps to connect your cloud provider, such as AWS. Ensure you provide the necessary credentials and permissions for security scanning. ### Trigger a Cloud Security Scan Once connected, you can initiate a security scan for your cloud environment. This will analyze your resources for security findings based on the configured policies and services (e.g., AWS Security Hub). ### Monitor Scan Status You can view the status of your security scans, including any findings, directly within the platform. This allows you to track progress and address identified issues. --- ### Browser Automation Browser Automation allows you to record and execute sequences of actions within a web browser, automating repetitive tasks. ### Create a Browser Automation You can define new browser automations by specifying the steps you want the browser to perform (e.g., navigating to a URL, clicking elements, entering text). ### Run an Automation You have several options for running automations: * **Start Live**: Executes the automation and provides a live view of the browser session, allowing you to watch the automation in real-time. * **Execute on Existing Session**: Runs the automation on a pre-existing browser session. * **Run Automation**: Executes the automation and returns the final result, including screenshots if configured. ### Manage Automations You can view a list of all your created automations, edit their steps, or delete them if they are no longer needed. ### View Run History Access the history of past automation runs to review their outcomes, check for errors, and view any generated artifacts like screenshots. ---