Commit Graph

1497 Commits

Author SHA1 Message Date
Émile Ré
b5dbdee372 Drop move-to-category confirm dialog
Moving a tracker to a category used to auto-create an org third party in
the mapping worker, so the move was gated behind a confirmation that
warned about it. The worker now only links to an existing vendor and
never creates one, making the prompt inaccurate.

Remove the confirm dialog and move directly on selection, folding the
same-category no-op guard into handleMove.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-11 12:08:22 +02:00
Émile Ré
675fcc4824 Add Import action for catalog vendors in trackers
A tracker pattern resolved only to a catalog vendor now shows an "Import
to third parties" action in its row menu. It calls
importThirdPartyFromCommon for the pattern's common third party and, on
success, links the imported org vendor onto the row so it stops showing
the "Common catalog" badge.

Sibling patterns of the same vendor are backfilled server-side and pick
up the link on the next fetch of the list, so the store update only
needs to reflect the clicked row.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-11 12:08:22 +02:00
Sacha Al Himdani
04a34c9757 Require explicit approver_ids when publishing a document major version
The publish flow ignored a document's stored default approvers and only
requested approval when approver_ids were passed in the call, so a major
publish with no approver_ids silently published directly without routing
through the approval flow — there was no way to tell "caller forgot
approvers" (null) from "caller wants no approval" (empty).

Make approver_ids an explicit choice, enforced once in the service so it
covers every caller (console, MCP, n8n):
- major publish: approver_ids must be set; an empty list publishes
  directly, a non-empty list requests approval.
- minor publish: approver_ids must be omitted (approvers are ignored).

Validate this in PublishDocumentRequest.Validate(), update the console
publish dialog and the n8n publish node to honour the contract, document
it in the MCP tool spec, and cover it with e2e tests.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-11 11:41:30 +02:00
Ludovic Vielle
3475dd0560 Switch console file fields to File download URLs
Replace presigned URL string fields (logoUrl, fileUrl, ndaFileName,
etc.) with nested File references resolved through /api/files/v1/.
Update console Relay queries and e2e coverage accordingly.

Route NDA upload through filemanager.PutFile and return stable IAM
org logo URLs for consistency with the files API.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-11 10:47:28 +02:00
Bryan Frimin
c913e97c35 Add active status field to access entries
Track whether an account is active (enabled) or disabled at the
source system. The field is nullable so existing entries without
this data remain valid.

- DB migration adds active BOOLEAN column to access_entries
- Coredata read/write/upsert/filter wiring for the new column
- Review engine propagates Active from source accounts
- GraphQL schema exposes active on AccessEntry and AccessEntryFilter
- MCP spec, types, and resolvers expose active and fix missing
  account_type filter that was wired in GraphQL but not MCP
- CLI list command adds --active filter flag and ACTIVE output column
- Console campaign detail table shows Active/Disabled status badge
- E2e and unit tests updated to cover the new field

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-11 10:42:53 +02:00
Émile Ré
ed9831a734 Default cookie consent to GDPR and track its source
When IP geolocation does not resolve a country, or resolves one with no
known cookie-consent regulation (common on localhost and unmapped
regions), the banner previously fell back to OPT_OUT with no recorded
regulation. Apply GDPR (OPT_IN) as the safe default in that case so the
strictest consent model wins when origin is unknown.

To keep consent records auditable, stamp each one with a regulation
source of DETECTED (resolved from geolocation) or DEFAULT (fell back to
GDPR). The shared cookiebanner.ResolveRegulation helper centralizes the
decision for both the config and consent endpoints, and the new value is
exposed through GraphQL, MCP, the CLI, the n8n node, and the console
consent-records views.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-10 17:49:41 +02:00
Émile Ré
4e72ad3bea Clarify tracker detection count label
The "Detected Count" label was ambiguous about whether it counted
distinct trackers or report occurrences. The report endpoint upserts
each detected tracker by identifier, so the value is the number of
distinct trackers matched by the pattern. Rename the label to
"Distinct Trackers Detected" to reflect this.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-10 17:49:39 +02:00
Sacha Al Himdani
b6781d3de0 Scope sub-third-parties per parent
Replace the many-to-many junction table with a direct
parent_third_party_id foreign key on third_parties. Each
sub-third-party now belongs to exactly one parent, making
duplicates across parents independent entities.

Replace the firstLevel boolean with an integer level field
(1 = direct, 2+ = parent level + 1) to support arbitrary
nesting depth.

Remove the createThirdPartyThirdPartyMapping and
deleteThirdPartyThirdPartyMapping mutations, the CLI
link/unlink commands, and the corresponding MCP tools.
Creating a child third party now just requires passing
parentThirdPartyId on the existing createThirdParty mutation.

The frontend walks the parentThirdParty chain to build
display names like "Name (Ancestor1/Ancestor2)" and shows
clickable ancestor links on the detail page.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-10 14:15:01 +02:00
Aurélien Sibiril
ec858e58df Add Neon access review driver support
Register Neon as a connector provider and add a new access review
driver that fetches organization members from the Neon API with
cursor-based pagination.

Neon's OAuth is partner-gated, so the connector is API-key only
(Bearer, the default scheme). A personal or organization API key can
belong to several organizations; the operator supplies the ID of the
one to review. The members endpoint exposes per-user MFA state
(has_mfa) and deactivation, which map to the access entry MFA status
and active flag; the stable account UUID (user_id) is used as the
external ID over the membership ID.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-10 00:55:54 +02:00
Aurélien Sibiril
7640376d32 Add Render access review driver support
Register Render as an API-key connector provider and add an access
review driver that fetches workspace members from the Render API
(GET /v1/owners/{ownerId}/members).

Render exposes no partner OAuth program, so the connector authenticates
with a read-scoped API key (Authorization: Bearer) plus the customer's
Workspace ID. The flat members endpoint reports an explicit account
status and MFA flag, surfaced as the Active and MFAStatus fields; the
stable "usr-" id becomes ExternalID. There is no picker -- the
workspace is captured up front via ExtraSettings -- so
SetOrganizationSettings is omitted.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-09 23:54:55 +02:00
Cursor Agent
7a43acd3c2 Add Qovery access review driver support
Register Qovery as a connector provider and add a new access review
driver that fetches organization members from the Qovery API.

Extend API key connection handling with a configurable Authorization
token scheme so Qovery can use "Token" while existing providers
continue to default to Bearer.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-06-09 19:43:47 +02:00
Bryan Frimin
e0c9e4e4a8 Style
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-09 17:19:47 +02:00
Bryan Frimin
5b79b52e23 Promote connector provider infos to a root-level access-review drivers query
Move connectorProviderInfos from Organization to a new root query field
accessReviewDrivers, backed by a deployment-scoped policy so any
authenticated identity can list it without an org-scoped permission check.
Delete the now-unused helper file and update the frontend and e2e tests.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-09 17:19:43 +02:00
Aurélien Sibiril
29b72ebc3b Add Better Stack access review connector
Better Stack exposes team members and pending invitations through its
Uptime API. Wire it as an access-review connector so a Better Stack
team can be reviewed in access-review campaigns.

Better Stack has no third-party OAuth app for listing members (its
OAuth is an end-user MCP sign-in), so the connector authenticates with
a Bearer API token plus the team name that scopes the team-members
listing. The driver paginates /api/v2/team-members, maps roles and
invitation records into account records, and the source name is
resolved from the configured team.

This wires the full surface: the provider enum and migration, the
connector settings, the registry registration with the team-name extra
setting, the GraphQL input and resolver marshaling, the frontend field
mapping and connector logo, and cassette-backed driver tests.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-09 17:07:08 +02:00
Émile Ré
83d36d345f Propagate DB errors and clipboard failures
The common tracker pattern show command swallowed every error from
loading the linked common third party, hiding real database failures
behind silent partial output. Only tolerate ErrResourceNotFound now and
wrap any other error so the command fails loudly.

In the console, the copy-to-clipboard button reported success
unconditionally. Await the clipboard write and surface an error toast
when it rejects, guarding against a missing common tracker id.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-09 17:00:06 +02:00
Émile Ré
223f66c6b7 Add common badge on third party col
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-09 17:00:06 +02:00
Émile Ré
99fdccf1e8 Update common tracker / third party display on trackers and tracker detail pages
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-09 17:00:05 +02:00
Émile Ré
aebb2a1ed0 Surface common tracker pattern link across APIs
Expose the existing tracker_patterns.common_tracker_pattern_id foreign
key on the TrackerPattern type so it is possible to tell whether a
pattern is linked to the global common-tracker catalog (its description
likely came from the seed or the mapping/enrichment agents) or has no
link (added manually or inherited). This is a read-only debugging aid
for agent-generated descriptions; no migration or write path changes.

The field is added in sync across all four API surfaces (GraphQL, MCP,
CLI, n8n) plus the console UI, and covered by e2e assertions for both
the linked and unlinked cases.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-09 17:00:04 +02:00
Sacha Al Himdani
9ac71f948f Update contact email to hello@probo.com
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-09 16:45:23 +02:00
Aurélien Sibiril
4df0e52810 Add SigNoz access review driver
Add a SigNoz connector so its organization members can be pulled into
access-review campaign snapshots. SigNoz authenticates with a
SIGNOZ-API-KEY admin service-account key and a customer-supplied base
URL (a SigNoz Cloud region/tenant host or a self-hosted instance).

The driver lists users via GET /api/v1/user, which returns the role
(ADMIN/EDITOR/VIEWER) inline so admin detection works in a single call,
and maps the SigNoz user status (active / pending_invite / deleted) to
the account active flag. The name resolver reads the organization
display name from GET /api/v2/orgs/me to title the access source.

Wire the provider through the coredata enum and settings, the
connector-provider registry (driver and name-resolver factories), the
console API-key input schema and validation, the access-review source
label, and the SigNoz brand logo.

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-09 15:22:05 +02:00
Sacha Al Himdani
dbf915047d Add risk assessment boundary model
Introduce RiskAssessmentBoundary as a first-class, self-nesting entity that
groups nodes within a risk assessment scope, and thread it through every
surface.

- coredata: new risk_assessment_boundaries table + migration, boundary_id on
  nodes, self-referential parent_boundary_id, entity type registration
- riskmanagement: boundary CRUD service methods, boundary_id wiring on node
  create/update, scope-membership and self-parent validation, nested-subgraph
  Mermaid rendering
- IAM: core:risk-assessment-boundary:{get,list,create,update,delete} actions
  and viewer/auditor read policies
- console GraphQL: RiskAssessmentBoundary type, connection, order enum, CRUD
  mutations, boundaries field on scope, boundaryId on nodes
- CLI: risk-assessment boundary command group and --boundary-id on nodes
- MCP: boundary tools and boundary_id on node tools
- n8n: boundary operations and boundary fields on node operations
- console UI: boundary list/create/edit, boundary selector on nodes, diagram
  refetch on boundary changes

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-09 11:46:41 +02:00
dependabot[bot]
3d1f089685 Bump react-router from 7.14.1 to 7.17.0
Bumps [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) from 7.14.1 to 7.17.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.17.0/packages/react-router)

---
updated-dependencies:
- dependency-name: react-router
  dependency-version: 7.17.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 12:03:34 +02:00
Bryan Frimin
d43526bff4 Add error for already used token
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-05 17:54:51 +02:00
Bryan Frimin
caeac0ed1c Improve UX error message
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-05 17:35:15 +02:00
Ludovic Vielle
c1c351ff81 Update frontend to use reportFile on Audit
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-05 16:16:52 +02:00
Bryan Frimin
44da0e251a Add new supported language
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-05 15:44:05 +02:00
Bryan Frimin
1d36123ead Add dedicated expired magic link page
Instead of a toast, expired magic link tokens now return a TOKEN_EXPIRED
GraphQL error code and redirect users to a dedicated /magic-link-expired
page with a clear CTA to request a new link.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-05 14:33:11 +02:00
Aurélien Sibiril
8253796743 Use Field onValueChange in the Zendesk dialog
Field exposes onValueChange(value) and wires the input's onChange itself,
so the explicit event-typed onChange handler was redundant.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-04 20:58:12 +02:00
Aurélien Sibiril
bc53f603eb Normalize pasted Zendesk subdomain URLs
Pasting a full Zendesk URL with a path or query (e.g.
acme.zendesk.com/agent?x=1) left the trailing segments in place because
the .zendesk.com suffix no longer matched at the end, producing an
invalid site value rejected by the backend. Drop everything from the
first path/query/fragment separator before stripping the suffix.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-04 20:58:11 +02:00
Aurélien Sibiril
09cfbce6e5 Add Zendesk connector logo and connect dialog
Add the Zendesk brand mark under ThirdParties and wire it into the
logo map. Because the customer subdomain is free-form (not a fixed
region list), the connect flow opens a dialog with a subdomain text
input that is sanitized and passed as ?site= to the OAuth initiate
endpoint, mirroring the Datadog multi-site dialog.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-04 20:55:48 +02:00
Aurélien Sibiril
06f3f8aecf Add Okta logo and API-key dialog mapping
Add the Okta brand mark to the ThirdParties atoms (export, logo map,
and ThirdPartyLogo wiring) and map the generic "domain" extra setting
to the oktaDomain field in the add-access-source dialog so the
API-key connect flow submits the org domain.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-04 19:23:26 +02:00
Bryan Frimin
fca7f2a1e6 Fix login redirect password only
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-04 14:37:37 +02:00
Aurélien Sibiril
929bf81161 Add Datadog region selector to connect dialog
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-03 17:16:26 +02:00
Aurélien Sibiril
b4e6f73b78 Merge PostHog self-hosted into a single PostHog provider
Fold POSTHOG_SELF_HOSTED into POSTHOG: one provider now covers Cloud (OAuth + region-pinned API key) and self-hosted (API key + instance URL), since both already share the driver, name resolver, and PostHogConnectorSettings{BaseURL}. The API-key form picks a deployment (Cloud US/EU or self-hosted URL); the resolver requires exactly one of region/instanceUrl.

Drop the POSTHOG_SELF_HOSTED enum value, registration, migration, and logo mapping. Extract the deployment selector into a dedicated PostHogDeploymentField component. Point the driver tests at us.posthog.com instead of the legacy app.posthog.com host.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-03 17:00:07 +02:00
Aurélien Sibiril
760f950a48 Simplify PostHog region select rendering
Replace the nested ternary in the extra-settings map with an
early-return body and a shared setter, so the region select and the
free-text field each read cleanly.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-03 17:00:07 +02:00
Aurélien Sibiril
836fbfbe26 Add PostHog source UI with region select
Show a US/EU region dropdown for the PostHog Cloud API-key form and
an instance-URL field for Self-Hosted, map both to the connector inputs,
and register the PostHog logo for the self-hosted provider.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-06-03 17:00:07 +02:00
Émile Ré
9c4b6aff18 Link cookie policy doc and revamp tracker rows
Expose the generated cookie policy Document on the CookieBanner
GraphQL type through a nullable policyDocument field and resolver,
and surface a link to it from the banner configuration header next
to the origin and ID. The link is hidden until a banner version is
published and the document exists.

Rework the tracker table rows: drop the Source column in favour of
a tracker Type badge, and move each tracker's description inline
beneath its name (and into the add/edit row inputs) instead of a
separate Description column.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-02 16:21:01 +02:00
Émile Ré
f702edabf0 Move cookie banner display tab first
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-02 16:21:01 +02:00
Sacha Al Himdani
6e7c96732f Add async third-party vetting
Queue vetting on third_parties with PENDING, PROCESSING,
COMPLETED, and FAILED states. Expose enqueue and status through
GraphQL, MCP, CLI, and n8n, validate vet requests, tune the
worker via config, and poll the detail page while vetting runs.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-02 11:39:51 +02:00
Cursor Agent
4084554daa Add document archive row action
Allow documents to be archived or unarchived directly from the
list row actions, matching the detail-page behavior. Remove the
row from the active or archived connection after the status change
so filtered lists update immediately.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-05-30 11:22:17 -07:00
Émile Ré
1b8bd1895e Rework tracker and resource row actions
Turn the category column into an inline Select so a tracker pattern or
resource can be recategorised in place. On the pattern row the move is
gated by a confirm that surfaces the existing behaviour of promoting or
linking a third party. The remaining row actions (include/exclude and
delete) move into a single action dropdown, leaving only Edit inline.

Add a Max Age column to the pattern table and a Category column to the
resource table, and lay the edit forms out with the name above the
inputs so the description can use the full row width. Shrink the action
column to its content so the freed space goes to the data columns.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-29 15:49:21 +02:00
Émile Ré
12f9dfa352 Expose HTTP cookie source through the console API
The coredata CookieSource enum and the ingestion path both support an
HTTP source, but the GraphQL CookieSource enum never declared it. The
generated marshaler is a plain map lookup with no fallback, so an HTTP
value missed the map and serialized to an empty string. The console UI
treats that empty string as falsy and rendered no source badge at all,
making HTTP-sourced trackers look sourceless.

Add the HTTP member to the GraphQL enum so the value round-trips, and
fold the duplicated tracker-type and tracker-source badge helpers from
three components into a shared @probo/helpers module, adding an explicit
HTTP label while consolidating.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-29 12:56:36 +02:00
Émile Ré
7f4a66b310 Skip third-party promotion for uncategorised trackers
Catalog resolution (common_tracker_pattern_id) still runs for every
pattern, but promoteThirdParty is now gated on the tracker's cookie
category: patterns still sitting in the uncategorised bucket are not
promoted to an org ThirdParty until the user moves them to a real
category, which re-triggers the worker via SetMappingRequested.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-29 10:07:30 +02:00
Émile Ré
33ddba9770 Do not use avatar for tracker third party
Signed-off-by: Émile Ré <emile@probo.com>
2026-05-29 10:07:30 +02:00
Émile Ré
af4b8a3476 Show third parties on banner trackers page
Wire the new CookieBanner.linkedThirdParties aggregation and the
TrackerPattern.thirdParty / commonThirdParty fields into the trackers
configuration UI. Three surfaces change:

CookieBannerTrackersPage: a new dedicated "Third party" column sits
between Name and Source so the link is visible at a glance, and a
fourth Select to the right of the category filter exposes the deduped
list returned by linkedThirdParties. The Select sends the chosen GID
straight through; the backend dispatches on the entity-type prefix
(ThirdParty vs CommonThirdParty), so the frontend stays oblivious to
which table the filter ends up hitting. The "%other" branch of the
union is filtered out before render to keep TypeScript happy if the
backend grows the union later.

TrackerPatternRow: extends the row fragment with thirdParty and
commonThirdParty, prefers the org-scoped link (mirroring the resolver
priority), and renders an Avatar + name. The org-scoped ThirdParty has
no logoUrl in the schema today so the Avatar falls back to initials;
CommonThirdParty supplies its catalog logo.

TrackerPatternPropertiesSection: same priority logic in a PropertyRow
under Category, so the detail page surfaces the same information.

The third-party Select uses the same set as the underlying patterns,
so picking a value never produces an empty list — the linkedThirdParties
resolver only walks rows the user can see.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-29 10:07:29 +02:00
Cursor Agent
0920785bdf Add Metabase access review source
Implement Metabase as a first-class access review connector backed by
GET /api/user, including account mapping and error handling in the
driver. Register the provider with API-key auth metadata and required
instance URL settings so connectors can be created and resolved
consistently.

Expose Metabase through the console GraphQL and UI flows by adding the
provider enum value, API-key extra setting field wiring, and source
label mapping. Add migration support for the connector_provider enum and
cover driver/provider behavior with focused tests.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
2026-05-28 18:36:36 -07:00
Cursor Agent
f5a632ffac Add Grafana access review connector support
Add Grafana as an access review connector-backed source.

This introduces a Grafana access-review driver, provider registration,
and connector settings for the Grafana base URL. It also wires the
new provider through GraphQL and access-review UI input mapping so
API-key connectors can be created from the product.

A connector_provider enum migration is included so Grafana can be
persisted in existing databases.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-05-28 18:35:01 -07:00
Cursor Agent
dd547471e6 Disable role sorting in people list
The role order field is not supported on the GraphQL profile ordering
path, which makes role-based sorting fail at runtime.

Keep the role column visible for users who can manage roles, but render
it as a regular table header instead of a sortable one.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-05-28 12:23:18 -07:00
Bryan Frimin
80be22fe8a Show SCIM error message
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-05-28 09:46:26 -07:00
Sacha Al Himdani
c78a713adf Refactor risks frontend to follow page arborescence conventions
- Split layout's monolithic query: each child route now owns its query
  via its own *PageLoader + *Page (overview/measures/documents/controls/
  obligations/scenarios).
- Rename tabs/RiskXTab.tsx -> <resource>/RiskXPage.tsx; drop UI-named
  tabs/ and dialogs/ folders.
- Move FormRiskDialog, PublishRiskListDialog and the extracted RiskRow
  into _components/ as named exports.
- Move risk form fragment ownership into FormRiskDialog: define
  FormRiskDialog_risk in the dialog and pass plain data to useRiskForm
  so spread sites colocate cleanly without disable comments.
- Align risk components with react-components.md naming: rename Relay
  fragments to ComponentName_typeName and replace 'type Props' aliases
  with 'interface ComponentNameProps'.
- Guard risk pages against null node and mutation errors: add
  __typename narrowing to every node(id) query, surface deleteRisk
  errors via toast, and resolve the confirm promise on error so the
  dialog no longer hangs.
- Replace deprecated useMutationWithToasts (FormRiskDialog) and
  useLazyLoadQuery (LinkScenarioDialog) with useMutation+useToast and
  useQueryLoader+usePreloadedQuery.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-05-28 15:02:09 +02:00