Add risk assessment system#1171
Conversation
There was a problem hiding this comment.
11 issues found across 47 files
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/console/src/pages/organizations/risks/tabs/RiskScenariosTab.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risks/tabs/RiskScenariosTab.tsx:91">
P2: Do not default Relay connection IDs to an empty string; use the `@connection` record directly so edge updates always target a valid connection.
(Based on your team's feedback about treating Relay `@connection` fields as non-null after `useFragment`.) [FEEDBACK_USED]</violation>
</file>
<file name="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentDetailPage.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentDetailPage.tsx:454">
P2: Edit dialogs can show stale values because `useForm` `defaultValues` are not updated when props change.</violation>
</file>
<file name="pkg/coredata/migrations/20260421T140001Z.sql">
<violation number="1" location="pkg/coredata/migrations/20260421T140001Z.sql:53">
P1: `risk_assessment_processes` can reference nodes from a different scope because FK constraints do not enforce scope consistency.</violation>
<violation number="2" location="pkg/coredata/migrations/20260421T140001Z.sql:66">
P1: `risk_assessment_threats` does not enforce that `process_id` belongs to the same scope as `risk_assessment_scope_id`.</violation>
</file>
<file name="pkg/probo/risk_assessment_service.go">
<violation number="1" location="pkg/probo/risk_assessment_service.go:124">
P2: Add GID validation for `ProcessID` in threat updates; this relation field is mutable but currently unvalidated.</violation>
<violation number="2" location="pkg/probo/risk_assessment_service.go:124">
P2: Validate `SourceNodeID` and `TargetNodeID` in process updates; they are persisted but currently unchecked.</violation>
</file>
<file name="apps/console/src/pages/organizations/risks/RiskDetailPage.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risks/RiskDetailPage.tsx:160">
P2: Handle mutation errors in the delete confirm flow; otherwise failed requests can leave the confirmation promise unresolved.</violation>
</file>
<file name="pkg/coredata/risk_assessment.go">
<violation number="1" location="pkg/coredata/risk_assessment.go:192">
P2: `RiskAssessment.Insert` returns raw DB errors instead of mapping unique violations to `ErrResourceAlreadyExists` like the other risk-assessment inserts, causing inconsistent error semantics.</violation>
</file>
<file name="pkg/server/api/console/v1/risk_assessment_resolvers.go">
<violation number="1" location="pkg/server/api/console/v1/risk_assessment_resolvers.go:226">
P1: Validate that source and target nodes belong to the provided risk assessment scope before creating a process.</violation>
<violation number="2" location="pkg/server/api/console/v1/risk_assessment_resolvers.go:296">
P1: Enforce that `process_id` belongs to `risk_assessment_scope_id` when creating or updating threats.</violation>
<violation number="3" location="pkg/server/api/console/v1/risk_assessment_resolvers.go:360">
P1: Authorize and validate `ThreatID` against the caller and ensure threat/risk belong to the same organization boundary before creating a scenario.</violation>
</file>
Tip: cubic used a learning from your PR history. Let your coding agent read cubic learnings directly with the cubic MCP.
fad84e5 to
2baabe5
Compare
There was a problem hiding this comment.
Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit
eslint (apps/console)
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 26 spaces but found 28 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 28 spaces but found 30 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 28 spaces but found 30 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 26 spaces but found 28 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 14 spaces but found 16 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 14 spaces but found 16 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 14 spaces but found 16 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 14 spaces but found 16 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 26 spaces but found 28 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 28 spaces but found 30 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 28 spaces but found 30 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 26 spaces but found 28 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 24 spaces but found 26 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 22 spaces but found 24 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 20 spaces but found 22 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 18 spaces but found 20 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 16 spaces but found 18 @stylistic/indent
🚫 [eslint (apps/console)] reported by reviewdog 🐶
Expected indentation of 14 spaces but found 16 @stylistic/indent
2f1345c to
c822c7c
Compare
There was a problem hiding this comment.
4 issues found across 47 files
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/console/src/pages/organizations/risk-assessments/RiskAssessmentDetailPage.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentDetailPage.tsx:438">
P2: Avoid nesting interactive controls inside the scope toggle button; move the actions dropdown outside the `<button>` element.</violation>
</file>
<file name="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentsPage.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentsPage.tsx:246">
P2: Provide a validation message for the required Name field; currently the form can fail validation without showing feedback.</violation>
</file>
<file name="pkg/coredata/risk_assessment.go">
<violation number="1" location="pkg/coredata/risk_assessment.go:56">
P1: Authorization attribute lookup is not tenant-scoped. Querying `risk_assessments` by ID alone can expose cross-tenant `organization_id` values during authorization evaluation; this should be constrained to the current tenant/scope.</violation>
</file>
<file name="pkg/coredata/risk_assessment_node_type.go">
<violation number="1" location="pkg/coredata/risk_assessment_node_type.go:68">
P2: `Scan` should handle `[]byte` sources in addition to `string`; otherwise enum reads can fail depending on driver return type.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
codenem
left a comment
There was a problem hiding this comment.
We should stop creating a tab folder (I think it is already in the guides but if not we can add it)
We should not query all tab in a details page query. The details page ins actually a layout, and each tab is a page in its own folder representing its resources, this is in the guides already.
codenem
left a comment
There was a problem hiding this comment.
I think we should create pkg/risk or pkg/riskmanagement and put the service there like we've started to do with esign, third party, cookie banner etc.
fdc5c0c to
4a5b842
Compare
29d6f7f to
50ceaa6
Compare
|
@cubic-dev-ai please review |
@SachaProbo I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
4 issues found across 65 files
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/console/src/pages/organizations/risk-assessments/_components/CreateThreatDialog.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risk-assessments/_components/CreateThreatDialog.tsx:85">
P2: Add required validation to `processId` so submit shows a field error instead of silently returning.</violation>
</file>
<file name="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentDetailPage.tsx">
<violation number="1" location="apps/console/src/pages/organizations/risk-assessments/RiskAssessmentDetailPage.tsx:120">
P1: Handle GraphQL errors in `onCompleted` before navigating; otherwise failed deletes can be treated as successful and the UI redirects incorrectly.</violation>
</file>
<file name="pkg/coredata/risk_assessment_node.go">
<violation number="1" location="pkg/coredata/risk_assessment_node.go:57">
P1: Authorization attribute lookup is not scope-constrained, which can leak cross-tenant resource existence.
(Based on your team's feedback about returning non-revealing NotFound behavior for cross-scope mismatches.) [FEEDBACK_USED]</violation>
</file>
<file name="pkg/riskmanagement/service.go">
<violation number="1" location="pkg/riskmanagement/service.go:981">
P1: `CreateScenario` does not verify that `threat_id` belongs to the same organization as `risk_id`, allowing cross-organization threat/risk links.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
48e5cc8 to
ddcf0a0
Compare
Introduce a hierarchical risk assessment model with six entity types: - Risk Assessment: top-level container scoped to an organization - Risk Assessment Scope: sub-container for scoping threat modeling exercises within an assessment - Risk Assessment Node: DFD elements typed as ENTITY, BOUNDARY, ASSET, or DATA within a scope - Risk Assessment Process: directed data flows between two nodes - Risk Assessment Threat: descriptive threats attached to a process with a free-text category (e.g. Confidentiality, Integrity) - Risk Scenario: thin join linking a threat to a risk from the register, carrying only a name and description Risk scoring (likelihood, impact, treatment) remains on the existing Risk entity. Threats are purely descriptive. Risk Scenarios connect the threat model to the risk register without duplicating scores. Backend: migration with PG enum for node types, coredata structs, service layer with full CRUD and validation, GraphQL schema with 18 mutations and paginated connections, authorization actions and policies, and base_resolvers.go Node dispatch for all entity types. Frontend: Risk Assessments list page with create dialog, detail page showing scopes as cards with nodes/processes/threats tables, inline create/edit/delete actions on all entities, and a Scenarios tab on the Risk detail page linking threats to risks. Existing RiskGraph.ts hook file removed in favor of colocated queries in page files. E2E tests cover CRUD for all entity types, RBAC, and tenant isolation. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
ddcf0a0 to
30ea177
Compare
Introduce a hierarchical risk assessment model with six entity types:
Risk scoring (likelihood, impact, treatment) remains on the existing Risk entity. Threats are purely descriptive. Risk Scenarios connect the threat model to the risk register without duplicating scores.
Backend: migration with PG enum for node types, coredata structs, service layer with full CRUD and validation, GraphQL schema with 18 mutations and paginated connections, authorization actions and policies, and base_resolvers.go Node dispatch for all entity types.
Frontend: Risk Assessments list page with create dialog, detail page showing scopes as cards with nodes/processes/threats tables, inline create/edit/delete actions on all entities, and a Scenarios tab on the Risk detail page linking threats to risks. Existing RiskGraph.ts hook file removed in favor of colocated queries in page files.
E2E tests cover CRUD for all entity types, RBAC, and tenant isolation.
Deferred to follow-up PRs:
Summary by cubic
Introduces a complete risk assessment system with assessments, scopes, nodes, processes, threats, and scenarios, plus console UI and GraphQL API. Risk scoring stays on Risk; scenarios link threats to risks without duplicating scores.
New Features
pkg/coredatamodels and queries;pkg/riskmanagementservice with validation and full CRUD; RBAC actions for all entities; GraphQL adds OrganizationriskAssessmentsand Riskscenariosconnections, types, and 18 mutations; Node dispatch covers all new types; server wires the service (pkg/probod,pkg/server, GraphQL handler).riskAssessmentRoutes; list/detail pages with inline create/edit/delete for scopes/nodes/processes/threats; Scenarios tab on Risk detail with create/delete; risks list/detail refactored with colocated queries/mutations; removedapps/console/src/hooks/graph/RiskGraph.ts.Migration
20260421T140001Z.sql.core:risk-assessment:*,core:risk-assessment-scope:*,core:risk-assessment-node:*,core:risk-assessment-process:*,core:risk-assessment-threat:*,core:risk-scenario:*.pkg/riskmanagementwiring.Written for commit 30ea177. Summary will update on new commits.