-
Notifications
You must be signed in to change notification settings - Fork 284
[dev] [Marfuen] feat/framework-instance-requirements #2370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
github-actions
wants to merge
25
commits into
main
Choose a base branch
from
feat/framework-instance-requirements
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
2c4521f
feat: add FrameworkInstanceRequirement schema for custom org requirem…
Marfuen 6aba767
feat: add customer-facing framework instance requirements CRUD API
Marfuen 5195747
fix: remove redundant per-method ValidationPipe, rely on global pipe
Marfuen 6329294
feat: include instance requirements in framework detail response
Marfuen d839159
feat: make framework rows clickable in overview when advanced mode is…
Marfuen b05b17b
feat: add framework instance requirement types, SWR hook, and update …
Marfuen f34aa4d
feat: add custom requirements list and create sheet components
Marfuen dbd4b84
test: add framework instance requirements service tests
Marfuen 29f9aff
refactor: merge custom requirements into unified requirements table
Marfuen 310aef3
refactor: restyle CreateRequirementSheet to match create risk pattern
Marfuen 2bffd2d
fix: support clicking on custom requirements to view detail page
Marfuen 282e5cf
feat: add create control button on requirement detail page and contro…
Marfuen 7de8bfa
fix: render controls multi-select only after data loads
Marfuen fff750c
fix: cap controls dropdown height at 200px with scroll
Marfuen 75fe587
fix: remove unnecessary className, MultipleSelector already caps at 2…
Marfuen a6a43cb
refactor: use DS Combobox with chips for controls multi-select
Marfuen e026914
fix: remove ComboboxEmpty that shows incorrectly with manual items
Marfuen f23f182
fix: show only framework controls in add requirement dropdown
Marfuen f12ee56
fix: sort controls alphabetically in add requirement dropdown
Marfuen c5f394c
feat: add tasks and policies selectors to create control sheet
Marfuen e9f52b1
feat: support instance requirements in controls create flow
Marfuen 9f8503b
fix: add Requirements breadcrumb level on requirement detail page
Marfuen 6b801bc
fix: set maxItems=4 on breadcrumbs to prevent collapsing
Marfuen a00f832
fix: handle nullable requirement in RequirementsTable for instance re…
Marfuen 0884244
chore: update migration
Marfuen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
.../api/src/framework-instance-requirements/dto/create-framework-instance-requirement.dto.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; | ||
| import { | ||
| IsArray, | ||
| IsString, | ||
| IsNotEmpty, | ||
| IsOptional, | ||
| MaxLength, | ||
| } from 'class-validator'; | ||
|
|
||
| export class CreateFrameworkInstanceRequirementDto { | ||
| @ApiProperty({ example: 'frm_abc123' }) | ||
| @IsString() | ||
| @IsNotEmpty() | ||
| @MaxLength(255) | ||
| frameworkInstanceId: string; | ||
|
|
||
| @ApiProperty({ example: 'Custom Access Control' }) | ||
| @IsString() | ||
| @IsNotEmpty() | ||
| @MaxLength(255) | ||
| name: string; | ||
|
|
||
| @ApiPropertyOptional({ example: 'CUSTOM-1' }) | ||
| @IsString() | ||
| @IsOptional() | ||
| @MaxLength(255) | ||
| identifier?: string; | ||
|
|
||
| @ApiProperty({ example: 'Custom requirement for access control policies' }) | ||
| @IsString() | ||
| @IsNotEmpty() | ||
| @MaxLength(5000) | ||
| description: string; | ||
|
|
||
| @ApiPropertyOptional({ | ||
| description: 'Control IDs to link to this requirement', | ||
| type: [String], | ||
| }) | ||
| @IsOptional() | ||
| @IsArray() | ||
| @IsString({ each: true }) | ||
| controlIds?: string[]; | ||
| } |
22 changes: 22 additions & 0 deletions
22
.../api/src/framework-instance-requirements/dto/update-framework-instance-requirement.dto.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { ApiPropertyOptional } from '@nestjs/swagger'; | ||
| import { IsString, IsOptional, MaxLength } from 'class-validator'; | ||
|
|
||
| export class UpdateFrameworkInstanceRequirementDto { | ||
| @ApiPropertyOptional() | ||
| @IsString() | ||
| @IsOptional() | ||
| @MaxLength(255) | ||
| name?: string; | ||
|
|
||
| @ApiPropertyOptional() | ||
| @IsString() | ||
| @IsOptional() | ||
| @MaxLength(255) | ||
| identifier?: string; | ||
|
|
||
| @ApiPropertyOptional() | ||
| @IsString() | ||
| @IsOptional() | ||
| @MaxLength(5000) | ||
| description?: string; | ||
| } |
92 changes: 92 additions & 0 deletions
92
apps/api/src/framework-instance-requirements/framework-instance-requirements.controller.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import { | ||
| Body, | ||
| Controller, | ||
| Delete, | ||
| Get, | ||
| Param, | ||
| Patch, | ||
| Post, | ||
| Query, | ||
| UseGuards, | ||
| } from '@nestjs/common'; | ||
| import { | ||
| ApiTags, | ||
| ApiBearerAuth, | ||
| ApiOperation, | ||
| ApiQuery, | ||
| } from '@nestjs/swagger'; | ||
| import { HybridAuthGuard } from '../auth/hybrid-auth.guard'; | ||
| import { PermissionGuard } from '../auth/permission.guard'; | ||
| import { RequirePermission } from '../auth/require-permission.decorator'; | ||
| import { OrganizationId } from '../auth/auth-context.decorator'; | ||
| import { FrameworkInstanceRequirementsService } from './framework-instance-requirements.service'; | ||
| import { CreateFrameworkInstanceRequirementDto } from './dto/create-framework-instance-requirement.dto'; | ||
| import { UpdateFrameworkInstanceRequirementDto } from './dto/update-framework-instance-requirement.dto'; | ||
|
|
||
| @ApiTags('Framework Instance Requirements') | ||
| @ApiBearerAuth() | ||
| @UseGuards(HybridAuthGuard, PermissionGuard) | ||
| @Controller({ path: 'framework-instance-requirements', version: '1' }) | ||
| export class FrameworkInstanceRequirementsController { | ||
| constructor( | ||
| private readonly service: FrameworkInstanceRequirementsService, | ||
| ) {} | ||
|
|
||
| @Get() | ||
| @RequirePermission('framework', 'read') | ||
| @ApiOperation({ | ||
| summary: 'List custom requirements for a framework instance', | ||
| }) | ||
| @ApiQuery({ name: 'frameworkInstanceId', required: true, type: String }) | ||
| async findAll( | ||
| @OrganizationId() organizationId: string, | ||
| @Query('frameworkInstanceId') frameworkInstanceId: string, | ||
| ) { | ||
| const data = await this.service.findAll( | ||
| frameworkInstanceId, | ||
| organizationId, | ||
| ); | ||
| return { data, count: data.length }; | ||
| } | ||
|
|
||
| @Get(':id') | ||
| @RequirePermission('framework', 'read') | ||
| @ApiOperation({ summary: 'Get a single framework instance requirement' }) | ||
| async findOne( | ||
| @OrganizationId() organizationId: string, | ||
| @Param('id') id: string, | ||
| ) { | ||
| return this.service.findOne(id, organizationId); | ||
| } | ||
|
|
||
| @Post() | ||
| @RequirePermission('framework', 'create') | ||
| @ApiOperation({ summary: 'Create a framework instance requirement' }) | ||
| async create( | ||
| @OrganizationId() organizationId: string, | ||
| @Body() dto: CreateFrameworkInstanceRequirementDto, | ||
| ) { | ||
| return this.service.create(dto, organizationId); | ||
| } | ||
|
|
||
| @Patch(':id') | ||
| @RequirePermission('framework', 'update') | ||
| @ApiOperation({ summary: 'Update a framework instance requirement' }) | ||
| async update( | ||
| @OrganizationId() organizationId: string, | ||
| @Param('id') id: string, | ||
| @Body() dto: UpdateFrameworkInstanceRequirementDto, | ||
| ) { | ||
| return this.service.update(id, dto, organizationId); | ||
| } | ||
|
|
||
| @Delete(':id') | ||
| @RequirePermission('framework', 'delete') | ||
| @ApiOperation({ summary: 'Delete a framework instance requirement' }) | ||
| async delete( | ||
| @OrganizationId() organizationId: string, | ||
| @Param('id') id: string, | ||
| ) { | ||
| return this.service.delete(id, organizationId); | ||
| } | ||
| } |
12 changes: 12 additions & 0 deletions
12
apps/api/src/framework-instance-requirements/framework-instance-requirements.module.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { Module } from '@nestjs/common'; | ||
| import { AuthModule } from '../auth/auth.module'; | ||
| import { FrameworkInstanceRequirementsController } from './framework-instance-requirements.controller'; | ||
| import { FrameworkInstanceRequirementsService } from './framework-instance-requirements.service'; | ||
|
|
||
| @Module({ | ||
| imports: [AuthModule], | ||
| controllers: [FrameworkInstanceRequirementsController], | ||
| providers: [FrameworkInstanceRequirementsService], | ||
| exports: [FrameworkInstanceRequirementsService], | ||
| }) | ||
| export class FrameworkInstanceRequirementsModule {} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RequirementMapping allows creating orphaned maps without any requirement
High Severity
RequirementMappingDtomakes bothrequirementIdandframeworkInstanceRequirementIdoptional with no cross-field validation ensuring at least one is provided. Thecreatemethod uses conditional spreads that silently skip both when neither is present, producing aRequirementMaprow that references no requirement at all — an orphaned record that bypasses both@@uniqueconstraints (sinceNULL ≠ NULLin PostgreSQL unique indexes).Additional Locations (1)
apps/api/src/controls/controls.service.ts#L217-L229