Skip to content

[comp] Production Deploy#2601

Merged
Marfuen merged 20 commits intoreleasefrom
main
Apr 20, 2026
Merged

[comp] Production Deploy#2601
Marfuen merged 20 commits intoreleasefrom
main

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Apr 20, 2026

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.


Summary by cubic

Adds first-class org-custom frameworks and requirements, and lets you link policies, tasks, requirements, and required evidence types to controls in a new Documents tab. Updates scoring to use submission time, ignores controls without artifacts, hardens multi-tenant safety, removes control-template auto-linking, and fixes policy alerts when a pending version is cleared.

  • New Features

    • Create custom frameworks and requirements (new APIs + sheets).
    • Link policies, tasks, requirements, and evidence form types to a control; manage in a new Documents tab.
    • Map controls to platform or org-custom requirements on create/link.
    • Framework pages: add/link requirements and link existing controls; lists/search/compliance include custom frameworks.
    • Scoring respects required document types, uses EvidenceSubmission.submittedAt, and excludes controls with no artifacts.
    • UX polish: org-scoped cache in control options (useApiSWR), requirement sheet resets on close.
    • Control template create no longer auto-links framework requirements; removed frameworkId param and added a regression test.
  • Migration

    • Split per-org data into CustomFramework and CustomRequirement; FrameworkInstance/RequirementMap support platform or custom IDs.
    • Composite FKs enforce tenant consistency; DB checks require exactly one of each ID pair.
    • Existing org data is migrated and references repointed.
    • Step: run database migrations before deploy; no manual data steps required.

Written for commit a7389a1. Summary will update on new commits.

Lewis Carhart and others added 16 commits April 17, 2026 21:16
…points

- Implemented new API endpoints for creating custom frameworks and requirements in the FrameworksController.
- Added DTOs for CreateCustomFrameworkDto, CreateCustomRequirementDto, LinkRequirementsDto, and LinkControlsDto.
- Enhanced findAvailable method to filter frameworks by organization ID.
- Introduced client components for adding and linking requirements, including AddCustomRequirementSheet and LinkRequirementSheet.
- Updated FrameworkOverview to include new actions for managing custom requirements.
- Added UI components for creating custom frameworks and linking existing controls.

This update enhances the framework management capabilities, allowing users to create and manage custom frameworks and their associated requirements effectively.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ts to controls

- Implemented new API endpoints in ControlsController for linking existing policies, tasks, and requirements to a control.
- Added corresponding DTOs: LinkPoliciesDto, LinkTasksDto, and LinkRequirementsToControlDto.
- Enhanced ControlsService with methods to handle linking logic and validation.
- Updated UI components to support linking actions, including LinkPolicySheet, LinkTaskSheet, and LinkRequirementForControlSheet.
- Improved data fetching with useControlOptions hook for better management of linked items.

This update enhances the control management capabilities, allowing users to effectively link existing resources to controls.
…tables

Previously the branch added a nullable organizationId column to the platform
FrameworkEditorFramework / FrameworkEditorRequirement tables so a single row
was either platform (null) or org-custom (set). That hybrid shape mismatched
the template/instance pattern used everywhere else in the codebase and caused
two cross-tenant reads (frameworks.service.findOne, findRequirement) to leak
one org's custom requirements to another org on the same framework.

Move the org-custom data into dedicated CustomFramework / CustomRequirement
tables. FrameworkInstance.frameworkId and RequirementMap.requirementId become
nullable and gain customFrameworkId / customRequirementId siblings with DB
CHECK constraints enforcing exactly one of the two is set. The editor tables
are pure platform definitions again, so the leaks vanish structurally (no
shared table to filter) rather than relying on filter discipline in each read.

- Schema: revert organizationId from FrameworkEditor tables; add
  CustomFramework + CustomRequirement; relax/branch FrameworkInstance and
  RequirementMap FKs with CHECK constraints
- Migration: move existing per-org rows into the new tables, repoint FKs,
  drop the old columns
- API: rewrite FrameworksService findOne / findRequirement / createCustom /
  createRequirement / linkRequirements / linkControlsToRequirement /
  findAvailable to branch on platform vs custom. Update ControlsService
  create + linkRequirements + DTOs to accept customRequirementId (with
  exactly-one validation) and persist documentTypes in the same transaction
- Frontend: plumb isCustom through the requirement/control sheets, widen
  FrameworkInstanceWithControls / FrameworkInstanceForTasks to surface
  customFramework, and fix all fw.framework.* null-unsafe reads
- Tests: frameworks.service.spec regression coverage that a custom FI never
  reads from frameworkEditorRequirement and a platform FI never reads from
  customRequirement

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the per-request console.log in the requirement page that was dumping
  internal API status/error payloads into server logs
- Return result.count from createMany in linkRequirements,
  linkControlsToRequirement, and linkDocumentTypes so skipDuplicates-skipped
  rows no longer inflate the reported count

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
controls.service.create() accepted policyIds, taskIds, and requirementMappings
(frameworkInstanceId, requirementId, customRequirementId) without verifying
they belong to the caller's organization. Prisma FKs only check existence,
not tenancy, so a user with control:create in org A could submit a
frameworkInstanceId from org B — the resulting RequirementMap would join the
attacker's control to the victim's framework, persistently rendering attacker
content inside org B's compliance UI via FrameworksService.findOne /
findRequirement includes.

Validate every FK against organizationId before the transaction, mirroring
the logic already present in linkRequirements:

- policies / tasks: findMany filtered by { id in, organizationId } and
  reject if any are missing
- frameworkInstance: must belong to caller org
- requirementId: platform requirement's frameworkId must match the FI's
  frameworkId
- customRequirementId: custom requirement must be in caller org and its
  customFrameworkId must match the FI's customFrameworkId

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…om-framework parity

- Schema: enforce tenant consistency on CustomFramework FKs with composite
  (id, organizationId) references. CustomRequirement and FrameworkInstance
  can no longer point at another org's CustomFramework, even if application
  code regresses. Migration adds a guard that aborts if any existing row
  already violates the invariant.
- Scoring: use EvidenceSubmission.submittedAt (canonical submission time)
  instead of createdAt for the "within last 6 months" recency check;
  update all evidenceSubmission selects/orderBys in frameworks.service
  to match.
- Policies (both admin + org): include customFramework when collecting the
  AI policy-regeneration context so org-custom frameworks influence the
  prompt instead of being silently dropped.
- Frontend framework list: exclude already-added custom frameworks from the
  "available to add" list on both overview and frameworks pages.
- useControls createControl payload: tighten requirementMappings to a
  discriminated union so invalid requirementId+customRequirementId combos
  fail at compile time (matches the backend's exactly-one rule).
- Controls controller: validate :formType path param with ParseEnumPipe.
- Document-type labels map: type as Record<EvidenceFormType, string> so
  Prisma enum drift becomes a compile error.
- DocumentsTable: disable every unlink button while any unlink is pending
  so users can't click enabled controls that no-op.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
validatePolicyIds / validateTaskIds compared findMany row count to the raw
input length. Duplicate ids in the request (e.g. [p1, p1, p2]) made the
input longer than the set of rows returned, so a legitimate request with
repeated ids was rejected as invalid. Dedupe via Set before the findMany
lookup and length check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolve bun.lock and package.json conflicts by accepting main.
[dev] [carhartlewis] lewis/comp-framework-controls
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

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

Project Deployment Actions Updated (UTC)
app (staging) Ready Ready Preview, Comment Apr 20, 2026 5:37pm
comp-framework-editor Canceled Canceled Apr 20, 2026 5:37pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal (staging) Skipped Skipped Apr 20, 2026 5:37pm

Request Review

@CLAassistant
Copy link
Copy Markdown

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.

✅ carhartlewis
❌ Lewis Carhart


Lewis Carhart seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 64 files

Note: This PR contains a large number of files. During the trial, cubic reviews up to 50 files per PR. Paid plans get a higher limit.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/app/src/app/(app)/[orgId]/frameworks/[frameworkInstanceId]/controls/[controlId]/components/useControlOptions.ts">

<violation number="1" location="apps/app/src/app/(app)/[orgId]/frameworks/[frameworkInstanceId]/controls/[controlId]/components/useControlOptions.ts:33">
P1: This hook uses raw `useSWR` instead of the project's `useApiSWR` wrapper, which scopes the SWR cache key by organization ID. Without org scoping, switching organizations will return stale cached control options from the previous org.

Use `useApiSWR` from `@/hooks/use-api-swr` to stay consistent with the rest of the codebase and get automatic org-scoped cache invalidation.</violation>
</file>

<file name="apps/app/src/app/(app)/[orgId]/frameworks/[frameworkInstanceId]/components/AddCustomRequirementSheet.tsx">

<violation number="1" location="apps/app/src/app/(app)/[orgId]/frameworks/[frameworkInstanceId]/components/AddCustomRequirementSheet.tsx:46">
P2: Form state is not reset when the sheet is closed without submitting. The sibling `LinkRequirementSheet` handles this via a `useEffect` that clears state on close. Add a similar effect here so reopening the sheet always shows a clean form.</violation>
</file>

<file name="apps/api/src/frameworks/frameworks-scores.helper.ts">

<violation number="1" location="apps/api/src/frameworks/frameworks-scores.helper.ts:270">
P1: Controls with no associated policies, tasks, or document types are now counted as incomplete (`hasAnyArtifact` is false), dragging down the compliance score. The old code excluded such controls from the calculation entirely. If frameworks commonly have controls that haven't been fully configured with artifacts yet, this will cause unexpected score drops for users.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread apps/api/src/frameworks/frameworks-scores.helper.ts Outdated
carhartlewis and others added 2 commits April 20, 2026 17:28
- useControlOptions: switch to useApiSWR for org-scoped cache invalidation
- AddCustomRequirementSheet: reset form state when sheet closes
- frameworks-scores: exclude controls without artifacts from score
  calculation instead of counting them as incomplete

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-fix

[dev] [carhartlewis] lewis/comp-framework-controls-fix
…n control create (#2605)

Creating a control from a framework's controls tab auto-connected every
requirement in that framework to the new control. Users expect to commit
the empty control and then link requirements manually.

Removed the requirement fetch/connect from ControlTemplateService.create,
dropped the now-unused frameworkId query param from the POST endpoint, and
stopped forwarding it from the frontend. Added a regression test that fails
if the auto-link behavior is reintroduced (CS-271).

Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
Co-authored-by: chasprowebdev <chasgarciaprowebdev@gmail.com>
Co-authored-by: Mariano Fuentes <marfuen98@gmail.com>
@vercel vercel Bot temporarily deployed to staging – portal April 20, 2026 17:32 Inactive
@Marfuen Marfuen merged commit 0d8ce3b into release Apr 20, 2026
11 of 14 checks passed
@claudfuen
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.25.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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.

4 participants