Commit Graph

114 Commits

Author SHA1 Message Date
Sacha Al Himdani
2ebf3c180f Fix crash on third-party details when country is GLOBAL
Intl.DisplayNames rejects the GLOBAL pseudo-region, so label
resolution now handles it explicitly before rendering the picker.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-27 18:56:24 +02:00
Sacha Al Himdani
d61ec8dd65 Add search and status/role/type filters to People
Makes it practical to find people in larger orgs across GraphQL, MCP, CLI, and n8n, with page size raised to 100.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-27 17:20:18 +02:00
Jonathan
a913b0e3b6 Fix eslint & checks
Signed-off-by: Jonathan <contact@grafikart.fr>
2026-07-27 11:52:32 +02:00
Jonathan
a7ff5f07bc Add react i18next to console
Signed-off-by: Jonathan <contact@grafikart.fr>
2026-07-27 11:52:31 +02:00
Émile Ré
00f5d0c4ba Remove orphaned apps/trust frontend
Compliance portal already embeds and serves the public SPA, so the
old @probo/trust app was unused. Drop its Makefile/CI stubs, Relay
project, CORS port, and the helper that only it imported.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-22 14:19:41 +02:00
Bryan Frimin
9724a2ce50 Harden cert provisioning failure and write-back
Rate limits no longer inflate ssl_retry_count into an instant FAILED
path. Centralize outcomes in decideProvisioningOutcome, keep ACME
order state on transient and rate-limit errors, bound each Process
tick with a timeout, and block on FOR UPDATE when persisting a
freshly issued certificate.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 13:20:52 +02:00
Bryan Frimin
bb2f55574f Rename shared packages for portal
Move helpers, emails, and coredata exports to
Compliance Portal names so frontend apps and
workers share one vocabulary.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:25 +02:00
Bryan Frimin
db24d17455 Add console useMutation and rename compliance graphs
Introduce the app-bound useMutation primitive and rename the trust center
graph and reference hooks to compliance page, moving the shared reference
dialogs alongside them. Sweep the compliance page subpages onto the new
mutation hook and the compliance-portal permission strings, and strip the
profile fields from the organization settings form.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-21 15:44:09 +02:00
Émile Ré
6623cbc6f2 Add data request pages to compliance portal
Let trust-portal data subjects submit and track GDPR/CCPA rights
requests. The new Data Requests page lists the viewer's own requests
and a dialog submits new ones, scoped server-side to the verified
viewer email so former or inactive users can still exercise their
rights. Submission requires magic-link sign-in (reusing the existing
gate) but not the NDA gate.

Extend the shared rights_request enums with RECTIFICATION, OBJECTION
and COMPLAINT types plus a REJECTED state, and keep the console
GraphQL, @probo/helpers and the MCP specification in sync. Expose a
trust GraphQL surface (myRightsRequests query, createRightsRequest
mutation) backed by a trust service and contact-scoped coredata
loaders.

Add the missing v2 UI kit primitives the dialog needs on top of Base
UI: a SegmentedControl radio-cards group, a form Textarea, and a
Field wrapper.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-20 14:31:42 +02:00
Sacha Al Himdani
4c57d201a4 Make license declarations consistently MIT
The source headers, LICENSE files, and license metadata had drifted
apart. Align the entire project to MIT:

- Convert every source-file header to the MIT text across all comment
  styles (Go, TS, TSX, JS, MJS, SQL, CSS, GraphQL, shell), including
  SPDX-License-Identifier tags
- Set the root and cookie-banner LICENSE files to the MIT text with a
  "MIT License" title line
- Switch the package.json license fields, Docker image label, and
  cookie-banner README to MIT
- Update docs and the genmodels header generator accordingly
- Normalize copyright lines to a single format
  (Copyright (c) <year(s)> Probo Inc <hello@probo.com>.): unify the
  hello@getprobo.com and hello@probo.inc emails to hello@probo.com and
  the comma-separated years to a hyphenated range

Genuine third-party references are intentionally left untouched: the
Lucide icon attributions (Lucide is ISC) and the trivy dependency
license allowlist.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-13 16:21:14 +02:00
Émile Ré
f98b73f073 Upgrade frontend toolchain to latest majors
Bump React 19.2, Relay 21, React Router 8, Vite 8 with
@vitejs/plugin-react 6, ESLint 10, GraphQL 17, TypeScript 6,
@types/node 24, and Tailwind 4.3 across the workspaces.

vite-plugin-react 6 (Vite 8) no longer runs Babel, so the Relay
tagged-template transform now runs through @rolldown/plugin-babel
in the console and trust Vite configs.

Relay 21 ships first-party types and enables the ambiguous-alias
check by default; disable that flag to preserve existing queries
and add explicit usePreloadedQuery type arguments where the new
types no longer infer the operation. TypeScript 6 deprecations and
stricter inference are addressed in tsconfigs and call sites.

Keep n8n-node on ESLint 9 and eslint-plugin-react on 7.37.5, the
newest releases compatible with their toolchains.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 13:51:17 +02:00
Émile Ré
f1fc2dc0e0 Show persistent for local-storage trackers
Local storage, IndexedDB, and cache storage have no expiry yet
persist until explicitly cleared, so a missing max-age should read
as "persistent", not "session" (the latter only fits cookies and
session storage, which end with the session or tab).

Thread the tracker type through humanizeSeconds (helpers) and
humanizeDuration (cookie-banner, with a localized persistent label)
and pass it at every console and banner call site. The consent
record query now selects trackerType so its duration column can
make the same distinction. This mirrors the Go HumanizedDuration
helper that already renders these types as persistent.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 10:46:44 +02:00
Émile Ré
265c56d00b Improve tracker source and first-party cleanup
Surface every CookieSource value in the console: the trackers page
filter was missing the HTTP option and the source badge helper had no
EXTENSION case, so HTTP-sourced rows could not be filtered and
extension-sourced rows rendered the raw enum string.

On the backend, the mark-first-party verdict now blanks the stale
description on both the catalog row and its uncategorised org tracker
patterns. A terminal non-third-party row keeps no vendor link, so a
description naming the (now-cleared) vendor would be misleading; the
mapping worker only copies descriptions into empty rows and never
clears them, so clearing is done explicitly here.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 10:46:43 +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
dependabot[bot]
1a71d15bc5 Bump vitest from 3.2.4 to 4.1.8
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 3.2.4 to 4.1.8.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.8/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 4.1.8
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-02 09:17:46 +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
Cursor Agent
29d8181b2c Add Global vendor country region
Allow vendor country selections to use a Global region alongside
existing country and EU values. The new value is accepted by backend
country-code validation, exposed through GraphQL and MCP schemas, and
shown in the shared country picker label set.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-05-28 18:51:42 +00:00
Sacha Al Himdani
ee22e9f964 Address CodeQL findings: unused imports, missing semicolons, dead conditionals
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-05-12 14:09:35 +02:00
Émile Ré
a911fcc220 Add seconds duration translations to cookie banner
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-05-11 14:52:47 +04:00
Sacha Al Himdani
553901e4ad Add risk publish to document system
Replace the old snapshot-based system for risks with the publish
document system, mirroring the prior vendor / processing activity / DPIA
/ TIA migration. Includes the GraphQL mutation, MCP tool, CLI command,
n8n operation, frontend publish dialog, e2e tests, and a prosemirror
register template covering name, description, category, treatment,
owner, inherent and residual scoring, and notes.

The risk register lives as a generated DocumentTypeRegister document on
the organization, reused across publishes (the major version bumps on
every republish). Approvers can be passed in to create a draft pending
approval; otherwise the version is published immediately. The frontend
Risks page exposes a Publish button and a Document link button when the
document exists, and pre-fills the previous default approvers.

Risks was the last remaining snapshot type, so this commit also removes
the entire snapshot system: drop snapshotId from the Risk GraphQL type
and RiskFilter; remove RiskSnapshotter, Risks.Snapshot,
InsertRiskSnapshots, and the SnapshotID/SourceID fields on Risk; delete
Snapshot, ControlSnapshot, SnapshotsType, SnapshotOrderField,
Snapshottable, the SnapshotService, the Snapshot console resolvers and
GraphQL schema, the Snapshot MCP types and operations
(list/get/take/listControlSnapshots), the snapshot CLI (prb snapshot),
the snapshot frontend pages, routes, banner, LinkedSnapshotsCard,
SnapshotGraph, snapshot helpers, and the snapshot n8n resource and
control link/unlink snapshot operations. The snapshot_id columns remain
in the database but are now filtered out with snapshot_id IS NULL.

Add Get/Upsert/Clear GeneratedDocumentID methods on Risk backed by a new
risks_document_id column on generated_documents, matching the
ProcessingActivity/Finding/Vendor pattern. The migration command
migrate-risk-snapshots-to-documents uses raw SQL queries instead of the
Go snapshot types, since those are gone.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-05-04 14:13:42 +02:00
Émile Ré
0d257977a1 Refactor cookie banner forms to react-hook-form
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-30 14:05:45 +04:00
Émile Ré
33abbfbb8f Link detected cookies to existing patterns on conflict
When a cookie pattern already exists for a banner, the insert
conflict caused a continue that silently dropped the detected
cookie instead of linking it to the existing pattern. Load the
existing pattern to obtain its ID and proceed with cookie
insertion.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-30 11:46:13 +04:00
Émile Ré
427bbbaf5c Move DurationInput to @probo/ui and scope pattern merge by category
Move the DurationInput component from the console app into @probo/ui
for reuse, add duration formatting helpers to @probo/helpers, and
update pattern merge to group by both category ID and prefix.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-30 11:46:12 +04:00
Émile Ré
2fe77d9ddc Fix review issues in cookie pattern handling
- Fix DurationInput fallback unit from "minutes" to "seconds" and add
  seconds as a selectable unit to prevent silent duration inflation
- Use parseFloat instead of parseInt for duration input to preserve
  fractional values
- Scope prefix merge groups by category ID to prevent cross-category
  merging
- Relink cookies and delete exact patterns even when prefix pattern
  already exists
- Prefer exact matches and longest prefix in pattern selection query
- Fix wrong error type in GetCookiePattern (ErrCookiePatternNotFound)
- Handle singular/plural in humanizeSeconds fallback branch

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-30 11:46:11 +04:00
Émile Ré
5cdaddf8b1 Store cookie durations as max_age_seconds
Replace the free-form duration TEXT column with a nullable
max_age_seconds INTEGER on both cookies and cookie_patterns
tables. The SDK detector now sends raw seconds instead of
humanized strings, eliminating locale-dependent comparisons
in the pattern merge worker. Humanization happens at display
time in the widget and console UI.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-30 11:46:11 +04:00
Sacha Al Himdani
c026f67bd9 Add vendor publish to document system
Replace the old snapshot-based system for vendors with the publish
document system, mirroring the prior processing activity / DPIA / TIA
migration. Includes the GraphQL mutation, MCP tool, CLI command, n8n
operation, frontend publish dialog, e2e tests, and a prosemirror
register template covering vendor profile fields plus per-vendor
sections for services, contacts, risk assessments, compliance reports,
BAA and DPA agreements.

The vendor register lives as a generated DocumentTypeRegister document
on the organization, reused across publishes (the major version bumps
on every republish). Approvers can be passed in to create a draft
pending approval; otherwise the version is published immediately. The
frontend Vendors page exposes a Publish button and a Document link
button when the document exists, and pre-fills the previous default
approvers.

Remove snapshot mode entirely from vendors and their sub-entities: drop
snapshotId/sourceId from GraphQL Vendor type and VendorFilter; remove
SnapshotsTypeVendors from the snapshot registry and delete
Vendors.Snapshot, VendorSnapshotter interface and all
*.InsertVendorSnapshots methods on contacts, services, risk
assessments, compliance reports, BAA and DPA. Drop the snapshot routes
and banner from the frontend. The snapshot_id columns remain in the
database but are now filtered out with snapshot_id IS NULL.

Add Get/Upsert/Clear GeneratedDocumentID methods on Vendor backed by a
new vendors_document_id column on generated_documents, matching the
ProcessingActivity/Finding/Obligation pattern.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-29 16:24:29 +02:00
Sacha Al Himdani
bdb16d4abe Add finding and obligation publish to document system
Replace the old snapshot-based approach with the new publish document
system for findings and obligations. Includes GraphQL mutations, MCP
tools, CLI commands, e2e tests, frontend publish dialogs, and
snapshot-to-document migration tools.

Remove snapshot mode entirely from findings and obligations: drop
snapshotId from GraphQL schemas, filters, resolvers, MCP spec, frontend
routes, pages, and helpers. The snapshot_id column remains in the
database but is now filtered out with snapshot_id IS NULL.

Remove auditor's ability to publish SoA.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-28 13:12:58 +02:00
Sacha Al Himdani
b603d04d8d Assets as document: replace snapshot with publish workflow
Remove assets from the snapshot system and replace with a publish-based
document workflow that generates versioned ProseMirror documents.

- Remove snapshot_id/source_id from asset and asset_vendor models
- Delete AssetFilter (no longer needed without snapshot filtering)
- Add PublishAssetList service, GraphQL mutation, MCP tool, CLI command,
  and n8n operation
- Add asset_list_document_id column to generated_documents table
- Generate ProseMirror documents with asset inventory tables
  (name, type, amount, data types stored, owner, vendors)
- Add AssetListDocument resolver on Organization type
- Update frontend to remove snapshot routes/params and add publish dialog
- Add e2e tests for asset publish (immediate, with approvers, reuse, RBAC)
- Add migration script for converting legacy asset snapshots to documents
- Exclude ASSETS from snapshot type lists and e2e snapshot tests
- Move generated_documents SQL to coredata methods on Datum and Asset
- Clear generated document and SOA references on soft delete and archive

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-21 19:36:17 +02:00
Alejandro Juan
da91afc2a7 Add CMMI maturity level to compliance controls
Adds an optional CMMI 0-5 maturity level field to Control to support
ISO 27001 clause 9.1 effectiveness measurement and HITRUST CSF maturity
requirements. The field is nullable, framework-agnostic, and exposed
across all four API surfaces (GraphQL, MCP, CLI, n8n) plus the
generated SoA document.

Signed-off-by: Alejandro Juan <alejandrojuan@alejandrojuan.com>
2026-04-21 11:06:36 +02:00
Sacha Al Himdani
55563226cb Data as document: replace snapshot with publish workflow
Mirror the SOA-to-document migration for the data list. Remove data
from the snapshot system and add a publish workflow that generates a
ProseMirror document for the full organization data inventory.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-20 14:44:00 +02:00
Sacha Al Himdani
c635492f75 SOA as document: replace export with publish workflow
Statements of Applicability are no longer exported as one-off PDFs.
Instead, each SOA owns a persistent document that accumulates versions
over time, following the same publish/approve lifecycle as authored
documents.

Publishing without approvers publishes immediately; publishing with
approvers creates a draft pending approval via the existing quorum
system. SOAs can also store default approvers that are pre-populated in
the publish dialog.

The SOA is removed from the snapshot system — applicability statements
are now queried directly (snapshot_id IS NULL) rather than through
snapshot copies.

A standalone migration script (cmd/migrate-soa-snapshots-to-documents)
converts existing SOA snapshots into documents with proper ProseMirror
content, preserving version history and approval decisions.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-16 00:01:13 +02:00
Sacha Al Himdani
5fd580e995 Rename State of Applicability to Statement of Applicability
Rename the entity across the full stack: database table
(states_of_applicability → statements_of_applicability), Go model,
GraphQL types, MCP specification, CLI commands, frontend components,
routes, and display labels. Includes a migration to rename the table
and its foreign key column.

Widen sidebar from 260px to 280px to fit the longer label.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 13:06:06 +02:00
Sacha Al Himdani
9a418a7711 Move document type from document to document version
Follow the same pattern used for classification: document type now lives
exclusively on DocumentVersion. A migration copies existing values from
documents to their versions. The document filter uses a subquery on the
latest version. All three API surfaces (GraphQL, MCP, CLI), resolvers,
frontend, and e2e tests are updated accordingly.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-02 16:32:38 +02:00
Bryan Frimin
a2f0a37b7b Add UNKNOWN and NOT_IMPLEMENTED measure states
Introduce two new measure states across the full stack: database
migration, Go coredata, GraphQL schema, MCP specification, and
frontend UI (labels, badge variants, and colors).

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-02 10:59:25 +02:00
Émile Ré
bd3869e0f0 Remove gif from allowed image types
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-03-31 19:05:46 +04:00
Émile Ré
687148e2c1 Unify dropzone accept prop with accept helpers
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-03-31 19:05:46 +04:00
Sacha Al Himdani
851e585b9b Add ISC license headers to Go, TypeScript, and SQL files
Add ISC license headers to all .go, .ts, .tsx, and .sql files
using each file's git history to determine the correct copyright
year or year range. Trademarked icons (brand logos, vendor logos,
compliance framework logos) are excluded.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-31 13:31:30 +02:00
Bryan Frimin
4f54241382 Add document types filtering and rename ISMS to GOVERNANCE
Adds 5 new document types (PLAN, REGISTER, RECORD, REPORT, TEMPLATE), renames ISMS to GOVERNANCE, and implements type-based filtering across GraphQL, MCP, and frontend. Includes migration, enum updates, filter implementation with SQL array support, and frontend dropdown UI with Relay refetch pattern.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-19 12:31:39 +01:00
Bryan Frimin
c8df8b0c87 Update TS types for nullable audit framework
The console GraphQL schema made Audit.framework nullable which
requires updating the TrustCenterDocumentAccess type and its
helper to handle the optional framework field.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-17 15:05:33 +01:00
Bryan Frimin
a82e353a47 Update shared helpers for findings
Add new finding statuses (RISK_ACCEPTED, MITIGATED, FALSE_POSITIVE)
to the registry status helper. Update snapshot type references to
use FINDINGS instead of NONCONFORMITIES and CONTINUAL_IMPROVEMENTS.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-03-17 15:05:33 +01:00
Sacha Al Himdani
fe241fc136 Add social links
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-11 12:10:57 +01:00
Sacha Al Himdani
66a7d6c3e8 Update vendor compliance report UI
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-03-11 10:28:39 +01:00
Émile Ré
a42fc4fa61 Reimplement remove / create in console
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-02-19 16:12:57 +04:00
Émile Ré
ad122f8b2e Rework the UI of vendor row on compliance page
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-02-04 18:38:48 +04:00
Émile Ré
baad2f8a34 Display URL host on compliance page organization sidebar ENG-53
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-28 09:40:03 +04:00
Émile Ré
27428377c6 Remove prettier in favor of @stylistic/eslint-plugin
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-22 12:51:42 +04:00
Bryan Frimin
e5c8d83219 Fix missing relay provider employee page
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-01-17 10:35:50 -08:00
Émile Ré
6a97be5d8e Replug custom domain setting
Signed-off-by: Émile Ré <nemile.re@gmail.com>
2026-01-17 10:27:45 -08:00
Émile Ré
433c081d22 OrganizationsPage switch to MembershipCard and add membership session state
Signed-off-by: Émile Ré <nemile.re@gmail.com>
2026-01-17 10:10:20 -08:00
Sacha Al Himdani
4ed3f5a067 Change state of applicability
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-01-16 22:56:00 +01:00