---
title: "Policy Management"
description: "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 draf..."
last_updated: "2026-05-06T07:29:41.620964+00:00"
canonical_url: "https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/technical/section-3/policy-management"
---

<details>
<summary>Relevant source files</summary>

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)
</details>

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.

<Callout title="Authentication" variant="info">
All policy management API endpoints require authentication, either via session cookies with an `X-Organization-Id` header or via an API key.
</Callout>


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.

<Callout title="Important Note on Content Updates" variant="warning">
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.
</Callout>
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.

<Callout title="Version Immutability" variant="info">
Published and pending policy versions are immutable. Their content cannot be directly updated or deleted. To make changes, a new version must be created.
</Callout>
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)

## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/49c89830-117b-4def-8edc-b5bcc50766e0/llms.txt) for all pages in this wiki.
