Skip to content

Conversation

@github-actions
Copy link
Contributor

This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.

github-actions bot and others added 2 commits January 30, 2026 17:03
…2079)

* feat(app): add 'Remove Device' menu on Employ Devices tab

* feat(api): create delete endpoint to remove single host from fleet

* feat(app): integrate delete endpoint to remove the host

* fix(api): missing host ownership validation allows cross-organization deletion

* fix(app): redundant null check after early return guard on handleRemoveDeviceClick

* fix(api): duplicated host deletion logic not consolidated on fleet.service

* fix(app): remove unnecessary accessorKey on actions column

* fix(app): remove duplicated database query for current user member

---------

Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
@vercel
Copy link

vercel bot commented Jan 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app (staging) Ready Ready Preview, Comment Feb 1, 2026 11:04pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal (staging) Skipped Skipped Feb 1, 2026 11:04pm

Request Review

@CLAassistant
Copy link

CLAassistant commented Jan 30, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ tofikwest
❌ github-actions[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@cursor
Copy link

cursor bot commented Jan 30, 2026

PR Summary

High Risk
High risk because it adds new policy/version lifecycle APIs, modifies publish/approval behavior (including signature resets), and introduces bulk migrations plus S3 copy/delete paths that can affect persisted data and stored documents.

Overview
Policy versioning is added end-to-end. The API now supports listing/creating/updating/deleting policy versions, publishing versions, setting an active version, and submitting a version for approval, with policy reads and AI chat using currentVersion content when present.

Publishing/approval flows are updated to be version-aware. Draft edits are stored separately (draftContent), approvals can promote a pendingVersionId to currentVersionId, and policy PDF handling (upload/get/delete/download) is extended to target specific versions while preventing edits to active/pending versions.

Storage + data migration changes. Policy creation now creates version 1 transactionally; deleting a policy/version cleans up associated S3 PDFs (including version PDFs); Trigger tasks are added to bulk-migrate legacy policies without versions; trust portal PDF bundling and vector-store sync now prefer version content.

Other changes. Findings updates gain revisionNote that is set/cleared based on status, and People adds an owner-only endpoint/UI to remove a single FleetDM host (plus Fleet service helper).

Written by Cursor Bugbot for commit 3a37196. This will update automatically on new commits. Configure here.

* feat(api): add revision note handling for findings update

* feat(app): update onStatusChange to support async handling in FindingItem

---------

Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
} finally {
setIsSubmitting(false);
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revision dialog closes on API failure, losing user input

Medium Severity

The handleRevisionSubmit and handleRevisionSkip functions expect onStatusChange to throw on API failure so the dialog remains open for retry. However, handleStatusChange (the implementation of onStatusChange) catches errors internally and shows a toast but doesn't re-throw. This causes await onStatusChange(...) to always resolve successfully, so the dialog closes and the user's typed revision note is cleared even when the API call fails. The user sees an error toast but loses their input.

Additional Locations (1)

Fix in Cursor Fix in Web

@IsString()
@IsOptional()
@MaxLength(2000)
revisionNote?: string | null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing explicit type causes incorrect OpenAPI schema

Low Severity

The @ApiProperty decorator for revisionNote is missing an explicit type: String specification. Combined with nullable: true and TypeScript type string | null, this causes NestJS Swagger to generate "type": "object" in the OpenAPI spec instead of "type": "string". Add type: String to the decorator options.

Fix in Cursor Fix in Web

* feat(api): add policy versioning with create, update, delete, and fetch operations

* fix(api): update approver handling and current version assignment in policy changes

* feat(api): enhance deleteById to clean up PDFs from S3 before deletion

* feat(api): update policy version creation to handle S3 copy after transaction

* feat(api): clear pending approval state when publishing or activating versions

* feat(api): include organizationId check to prevent cross-org access in PDF URL retrieval

* feat(api): sync draft content to prevent unpublished changes UI bug

* feat(api): prevent activating a different version when another is pending approval

* feat(api): add validation for deactivated members as approvers

* feat(api): clear signatures when publishing or activating policy versions

* feat(api): sync draft content to prevent false unpublished changes indicator

* feat(api): use transaction for atomic policy updates and sync draft content

---------

Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
}
return [];
})()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Editor loads published content instead of draft content

Medium Severity

The policyContent prop passed to PolicyContentManager loads from currentVersion.content or policy.content, but never from policy.draftContent. Meanwhile, hasDraftChanges correctly compares draftContent vs content to detect unpublished changes. This mismatch means when a user has draft changes (saved to draftContent), the editor will show the published version content instead of their draft. The "unpublished changes" indicator will appear, but the actual draft content won't be displayed or editable, potentially causing users to overwrite their draft work.

Fix in Cursor Fix in Web

}

return processed;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated processContent function and ContentNode interface

Medium Severity

The ContentNode interface and processContent function are duplicated in both update-draft.ts and update-version-content.ts. These are nearly identical implementations that sanitize TipTap editor content. Extract to a shared utility like apps/app/src/actions/policies/lib/content-utils.ts.

Fix in Cursor Fix in Web

console.error('Error copying policy PDF:', error);
return null;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated S3 PDF copy helper function

Low Severity

The copyPolicyVersionPdf function duplicates the logic in AttachmentsService.copyPolicyVersionPdf (apps/api/src/attachments/attachments.service.ts lines 341-358). Consider extracting to a shared S3 utility module or creating a reusable pattern.

Fix in Cursor Fix in Web

} catch (error) {
console.error('Error deleting policy PDF:', error);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated S3 PDF delete helper function

Low Severity

The deletePolicyVersionPdf function duplicates the logic in AttachmentsService.deletePolicyVersionPdf (apps/api/src/attachments/attachments.service.ts lines 363-374). Consider extracting to a shared S3 utility module.

Fix in Cursor Fix in Web

* fix(trust-portal): improve error handling for custom domain updates

* fix(trust-portal): enhance error handling for domain ownership checks

---------

Co-authored-by: Tofik Hasanov <annexcies@gmail.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

);
}

// Delete the policy (versions are cascade deleted)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S3 deletion before database update causes inconsistent state on failure

Medium Severity

S3 PDF files are deleted before the database operation (delete or transaction). If the database operation fails after S3 deletion succeeds, the policy versions will reference non-existent S3 files, causing broken PDF links for users. The S3 cleanup should occur after the database operation succeeds to maintain data consistency. This affects policy deletion and policy regeneration flows.

Additional Locations (2)

Fix in Cursor Fix in Web

});

return version.id;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused exported function ensurePolicyHasVersion

Low Severity

The ensurePolicyHasVersion utility function is exported but never imported or used anywhere in the codebase. The comment states it "Can be called from other server actions or components when needed" but no callers exist.

Fix in Cursor Fix in Web

console.error('Error copying policy PDF:', error);
return null;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate S3 helper functions across packages

Low Severity

copyPolicyVersionPdf in create-version.ts and deletePolicyVersionPdf in delete-version.ts duplicate functionality that already exists in AttachmentsService (attachments.service.ts lines 341-374). Consider creating a shared S3 utility in the app package or calling the API endpoints.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants