Commit Graph

5102 Commits

Author SHA1 Message Date
Bryan Frimin
b49c64b180 Add Korean (ko-KR) translation for compliance portal
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:38 +02:00
Bryan Frimin
fa9603d52e Add Japanese (ja-JP) translation for compliance portal
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:38 +02:00
Bryan Frimin
720dc49be3 Add Italian (it-IT) translation for compliance portal
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:38 +02:00
Bryan Frimin
f081c8fe70 Add Indonesian (id-ID) translation for compliance portal
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:37 +02:00
Bryan Frimin
1774d29591 Add Spanish (es-ES) translation for compliance portal
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:27 +02:00
Bryan Frimin
6ff2cf9946 Add German (de-DE) translation for compliance portal
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:27 +02:00
Bryan Frimin
c61ff9721e Register eleven new compliance-portal locales
Add German, Spanish, Indonesian, Italian, Japanese, Korean, Polish,
Portuguese, Turkish, Ukrainian, and Simplified Chinese to
SUPPORTED_LANGUAGES, and map each one's browser language-tag prefix to
its canonical locale in resolveLanguage() so i18next can be asked to
load it. Catalog JSON for these locales lands in the following
commits.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:15 +02:00
Bryan Frimin
177a5d0361 Rename trust center wording to compliance portal in copy
The English and French compliance-portal strings referred to "trust
center" in a few spots (back-navigation link, empty states) while the
rest of the app already calls this surface the "compliance portal".
Standardize on that term everywhere it appears in copy, and rename the
backing i18n key (backToTrustCenter -> backToCompliancePortal) to
match. Also fixes two spots where the French translation had left
"Compliance Portal" and "trust center" untranslated in English.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-20 15:48:02 +02:00
Émile Ré
776bec7ef8 Add bundling options to put base deps in specific chunks
Signed-off-by: Émile Ré <emile@probo.com>
2026-07-20 14:53:59 +02:00
Émile Ré
a41aa3ce07 Restore gap above new-request footer
The form wrapper broke DialogPopup's column gap, so the
textarea sat flush against the actions. Match SignInForm.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-20 14:41:27 +02:00
Émile Ré
b9d1446a5c Preserve Field aria-describedby on errors
Cloning the control overwrote any existing description
ids. Merge the error id in so hints stay announced.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-20 14:31:43 +02:00
Émile Ré
1c28f63555 Extract bordered list into UI List
Documents and data requests duplicated the same card and
row chrome. A shared List primitive keeps those surfaces
consistent across the portal.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-20 14:31:43 +02:00
Émile Ré
622f1ba67d Address PR review on data request pages
Require a verified viewer email before creating a rights request and
validate the free-text fields with the same SafeText bounds the console
uses, so this public portal mutation stays safe and bounded.

Move myRightsRequests onto the base Query, drop the now-dead count
loaders, and order the RECTIFICATION enum value before PORTABILITY so
the Postgres sort order matches RightsRequestTypes().

Harden the v2 kit primitives: SegmentedControl keeps equal-width cards
(auto-fill), preserves its selection when the active card is toggled,
and forwards an accessible name; Field associates its label and error
by id/aria instead of wrapping the control in a label. Give the type
group an accessible name, require the name field for non-complaint
types, use a timezone-stable reference year, drop the underreporting
header count, and neutralize the response-deadline copy.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-20 14:31:42 +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
Bryan Frimin
e7ebab0d58 Release @probo/n8n-nodes-probo/v0.203.0
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-07-20 12:37:30 +02:00
Bryan Frimin
0cea92ac78 Release prb/v0.200.0
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-07-20 12:36:42 +02:00
Bryan Frimin
52991b9aac Release probod/v0.227.0
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-07-20 12:36:04 +02:00
Cursor Agent
c3845aac19 Re-run CI after GitHub Actions outage
The test-e2e, scan, and Analyze (go) jobs failed during action
download with Service Unavailable, not due to code regressions.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 12:14:42 +02:00
Cursor Agent
4dd9fa0461 Batch-load versions when cancelling signature requests
Archive teardown loaded each document version inside the signature
cancellation loop. Collect version IDs and use LoadByIDs once instead.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 12:14:41 +02:00
Cursor Agent
ac547d3a83 Refactor archive teardown into shared helpers
Move approval void logic into voidPendingApprovalForLatestVersionInTx
on DocumentApprovalService and group signature cancellation with the
existing cancelPreviousMajorSignatureRequestsInTx helpers. Place
archive-specific InTx orchestration beside Archive and Unarchive.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 12:14:41 +02:00
Cursor Agent
366c1f93a1 Fix ambiguous tenant filter in signature load query
LoadRequestedByDocumentID joined document_versions while applying
the unqualified tenant_id scope fragment, which PostgreSQL rejects.
Use the same IN-subquery shape as DeleteRequestedByDocumentID.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 12:13:41 +02:00
Cursor Agent
d2286aa1ac Tear down workflows when archiving documents
Archive and bulk archive now void pending approval quorums and
cancel requested signatures before freezing the document. Unarchive
reverts any leftover pending approval to draft. A migration backfills
archived documents that still carry in-flight workflow rows.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 12:13:41 +02:00
Cursor Agent
e5c7cf9b9c Rename Inherent to Initial in risk module UI
Several risk views already used "Initial" while others still showed
"Inherent". Align user-facing labels across the console, shared UI
components, CLI help, n8n fields, generated documents, and MCP
descriptions. API and database field names are unchanged.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 12:06:46 +02:00
Cursor Agent
aba2ef4cc2 Rename Severity label to Score on risk overview
The risk overview cards label the combined likelihood × impact
value as Severity; use Score instead for consistency with the
rest of the risk page.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-20 08:52:29 +00:00
Émile Ré
94970bea6c Inline the gate-redirect helper in the boundaries
resolveGateRedirect only supplied window.location.href to gateRedirectPath
from two call sites; drop the extra indirection and call gateRedirectPath
directly in the root and page error boundaries.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 19:41:51 +02:00
Émile Ré
3e2651cbe5 Address PR review on the auth gates
Route the full-name and NDA gates from the request-access flows to their
gate pages (deep-linking with the deferred continue URL) instead of a
dead-end toast, so signing or naming resumes the original request; the
shared gate-to-route mapping now lives in one helper reused by the route
boundaries and both request hooks.

Fix the NDA page redirecting to home while also redirecting to the
continue URL once the signature is sealed, surface consent/accept
failures so the sign button isn't silently inert, and build the
request-all continue URL before clearing its marker.

On the backend, return success from updateFullName when the identity has
no organization profile instead of dereferencing a nil profile, which
crashed external trust-center visitors completing the full-name gate.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 19:22:01 +02:00
Émile Ré
4d3cf1f320 Add NDA and full-name gates to compliance portal
Handle NDA_SIGNATURE_REQUIRED and FULL_NAME_REQUIRED the way the trust
app does: the Relay fetch throws the typed errors and the route error
boundaries redirect to /full-name or a new self-contained /nda page,
carrying a continue URL. The request-access hooks move both gates to
onError accordingly (NDA is toast-only, matching trust, since the query
boundary is its primary path).

The NDA page is styled like the document viewer: a header band with the
title, org subtitle, consent, and sign action, over the NDA PDF, with the
same page-navigation and zoom controls. It records the signing events,
accepts the electronic signature, polls until sealed, then returns to the
continue URL.

Also fall back to the email in the top-bar user menu when a member has no
full name yet, and hoist the shared PDF-viewer control labels into the
app common namespace (deduplicating the document viewer and NDA copies,
and collapsing a duplicated common block in the locales).

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 18:45:26 +02:00
Émile Ré
375f5f071e Gate private document access behind sign-in
The document, report, and file "Get Access" buttons were inert. Wire
them to the per-resource access mutations, and gate unauthenticated
requests behind the sign-in dialog: a signed-out click defers the
request in the continue URL and resumes it after sign-in, mirroring the
top-bar request-all flow. Extend useResumeAccessRequest to complete the
deferred per-resource requests and route through the full-name gate.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 17:57:57 +02:00
Émile Ré
4e3e4d8975 Rename LoginForm to SignInForm for consistency
The form and its Relay operation were named after the Figma "Login Form"
layer, but the rest of the feature speaks "sign in" (SignInDialog,
auth.signIn.*, the visible copy). Align the name so the dialog and its
form share one prefix.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 17:43:24 +02:00
Émile Ré
b0dd7b7ad4 Show dialog skeleton over a backdrop in Storybook
The skeleton frame carries the dialog's shadow-6 elevation, which only
reads correctly against the dimmed overlay. Render the story over a
simulated backdrop so the preview matches how the dialog appears.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 17:43:24 +02:00
Émile Ré
a5f184d8e3 Add stories for Dialog and Toaster
Cover the new v2 kit primitives in Storybook: the Dialog (uncontrolled
trigger, controlled open state, and skeleton) and the Toaster (title-only
toasts as the common case, plus a title+description variant).

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 17:43:24 +02:00
Émile Ré
2a10b29859 Add sign-in dialog and request-access gating
The compliance portal's "Get Access" button was inert and the portal
had no way to authenticate or request trust-center access. Add a modal
sign-in flow (magic link + OIDC) that gates the requestAllAccesses
mutation, mirroring the trust app's flow but as a dialog instead of a
full /connect page.

Introduce the two v2 UI-kit primitives this depends on: a headless
Base UI Dialog and a styled Toaster (mutation toasts had no host yet).
Wire the top-bar button to open the dialog, resume the deferred access
request once authenticated, and add standalone routes for magic-link
verification and the full-name gate.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 17:43:22 +02:00
Émile Ré
828bd70371 Fix lint issues
Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 15:07:29 +02:00
Émile Ré
c1336d845c Hide empty commitment groups on the portal
Groups with no cards render nothing, but the section still reserved its
eyebrow slot for the first group by index and kept its padded wrapper,
leaving a stray "Security Commitments" label misplacement and an empty
gap when every group was empty.

Filter out cardless groups before rendering so the eyebrow lands on the
first visible group and the whole section collapses when nothing renders.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 15:07:29 +02:00
Émile Ré
e6dcb7ea00 Add commitment reordering with rank move buttons
Let admins reorder commitment groups and the cards within each group from
the console Commitments tab using up/down buttons, driven by the existing
rank-aware update mutations.

Make the (parent, rank) unique constraints on the commitment tables
DEFERRABLE INITIALLY DEFERRED. Reordering shifts several rows in one
UPDATE, which transiently duplicates a rank and tripped the immediately
enforced constraint with a 23505 error. This matches the other
rank-ordered tables (references, compliance frameworks).

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 15:07:29 +02:00
Émile Ré
0b146a4054 Add configurable compliance portal commitment cards
The compliance portal home page rendered security-commitment cards from
a hardcoded placeholder POJO. Back them with real, per-organization data
that admins configure in the console and the portal loads over the trust
center GraphQL API.

Model two entities under the trust center: a commitment group (title,
description, rank) and a commitment card (icon, eyebrow, title,
description, rank). The card icon is a curated enum mapped to a Phosphor
icon in the portal. New entities adopt the compliance_portal_ prefix as
the start of the broader rename away from trust_center_ naming.

Expose the groups and cards read-only on the public trust API and with
full CRUD on the console API, add a Commitments tab to the compliance
page, and replace the placeholder section with a Relay-driven one.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 15:07:29 +02:00
Sacha Al Himdani
936162d5c7 Resolve document publish approvers from defaults
The MCP publishDocument tool required callers to pass approver_ids and
to distinguish an omitted list (rejected) from an empty one (direct
publish), a null-vs-empty subtlety that is awkward for an LLM to get
right.

Drop approver_ids from the MCP tool and resolve a major publish's
approvers from the document's default approvers instead: an approval is
requested when the document has default approvers, otherwise the version
is published directly. Default approvers are configured with addDocument
or updateDocument.

Replace a document's default approvers on every major publish that
supplies an explicit list, even when the list is empty, so a direct
publish through the GraphQL API clears stale approvers instead of
leaving them behind (previously the empty case skipped the update).

Expose the default-approver behaviour as a separate entry point,
PublishVersionWithDefaultApprovers, that loads the defaults and
delegates to PublishVersion. PublishVersion keeps its explicit-approver
contract for the GraphQL API.

Require only the publish permission to publish a version, whether or not
it opens an approval quorum, and drop the now-unused request-approval
action.

Fold the publish steps into the publishMinor and publishMajor primitives
shared by both the single and bulk publish paths, and drop the redundant
InTx suffix from RequestApproval and emitDocumentEvent, which already
take a transaction argument.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-16 14:17:59 +02:00
Émile Ré
6abe5f84f8 Fix stale document viewer navigation races
Dispose the viewer query when the alias changes so navigating between
documents shows the skeleton instead of the previous document. Guard the
export completion against the current id so a slow export can't overwrite
a newer document's preview. Split the documents tab state into requested
and loaded refs so an out-of-order or failed refetch can't leave the list
showing a different tab than the toolbar.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 13:12:56 +02:00
Émile Ré
6054c92899 Add document viewer to the compliance portal
Add a full-page viewer at /documents/:alias that resolves the aliased
node, exports its watermarked bytes, and renders them: PDFs via react-pdf
with page navigation and zoom, images inline, and a download fallback for
other file types. Unauthorized visitors see a locked state.

Wire the documents list "View" action to link into the viewer (fragments
now select alias) and drop the previous open-in-new-tab helpers, since the
viewer owns the export.

Bound MainLayout to the viewport so the top bar and footer stay fixed and
the page area scrolls on its own; the viewer then keeps its toolbar fixed
while the PDF body scrolls, matching the design.

Add the react-pdf dependency with the pdf.js worker bundled via Vite (for
CSP safety) and a headless v2 Separator kit component for the toolbar.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 11:14:51 +02:00
Émile Ré
99990d6f6b Address code review on documents and UI skeletons
Fold the review feedback from the documents page work into the shared
components and helpers:

- Toaster: give the close control the kit's focus-visible ring, and wrap
  the title/description in Toast.Content so stacked toasts get Base UI's
  height measurement and overflow handling.
- TabsSkeleton: spread rest before the fixed aria-hidden so the
  decorative subtree can't be exposed to assistive tech.
- DocumentsPage: reconcile the active tab against the tab the preloaded
  query actually loaded with, so a tab change during the initial preload
  no longer shows the wrong slice.
- Grouping: drop the duplicated bucketing helpers and reuse the shared
  groupBy from @probo/helpers, keeping field-specific sorting/labeling in
  the callers.
- Documents list items: extract a shared DocumentEntry row and a
  useExportAndOpen hook so the three item components stop repeating the
  export/access behavior while keeping their own fragments.
- Subprocessors skeleton: reuse SelectSkeleton/TextFieldSkeleton instead
  of hand-rolled placeholders.
- useDocumentTab: derive DocumentTab and URL validation from a single
  DOCUMENT_TABS source of truth.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-16 09:57:52 +02:00
Émile Ré
4c599c17f4 Align subprocessors header spacing with the design
Give the toolbar a 64px min-height so its controls are vertically
centered, and make the header band flush at the bottom. This widens the
gap above the toolbar and trims the oversized space below it to match
the Figma hero. Mirror the header in the skeleton so it does not jump
when data loads.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-15 19:31:15 +02:00
Émile Ré
bce75355c0 Extract documents page layout into a tv variant
The results container hand-wrote its layout classes and toggled the
dimmed state with a string-interpolated conditional. Move both the page
shell and the busy/dimmed state into a documentsLayout tv variant, and
reuse it in the skeleton so the loading and loaded layouts share one
source of truth.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-15 19:26:29 +02:00
Émile Ré
e546f24148 Adopt the shared v2 Toaster from the auth branch
Replace the minimal placeholder Toaster with the richer implementation
already built on compliance-portal-auth (per-type icons plus warning and
info variants, and its stories). Both branches now share the exact same
component and app-root wiring, so they converge instead of colliding
when they merge. Align App.tsx provider ordering to match.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-15 19:26:29 +02:00
Émile Ré
158861ccdd Add documents page to the compliance portal
Build the Trust Center documents page: a unified list of published
documents, uploaded files, and audit reports, grouped into category
sections. An All/Public/Private tab bar filters the list by trust
center visibility.

Expose that filter over the trust v1 API by adding a
TrustCenterVisibility enum and a shared TrustCenterVisibilityFilter
input, wiring it through the documents, audits, and trustCenterFiles
connections down to the existing coredata SQL filters. "All" keeps the
default public+private slice; the other tabs pin a single visibility.

Access controls are display-only for now (auth is handled separately):
authorized or public entries open their exported PDF via the export
mutations, requested entries show a pending state, and everything else
shows an inert Get Access affordance.

Add the v2 Tabs and Toaster kit components (Base UI headless) needed by
the page and mount a toast provider at the app root for mutation
feedback.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-15 19:26:29 +02:00
Sacha Al Himdani
3c3276a90b Release @probo/n8n-nodes-probo/v0.202.1
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-15 18:51:47 +02:00
Sacha Al Himdani
05d3f17ae7 Release probod/v0.226.1
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-15 18:50:40 +02:00
Sacha Al Himdani
e62524b160 Bump golang.org/x/text to v0.39.0 for CVE-2026-56852
Upgrade the indirect golang.org/x/text dependency from v0.38.0 to
v0.39.0 to remediate CVE-2026-56852. Running go mod tidy also carried
along golang.org/x/tools and golang.org/x/telemetry to their matching
versions.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-15 18:27:16 +02:00
Sacha Al Himdani
f14d8115b6 Fix n8n ProboTrigger node package review issues
- Log delete failures in deleteSubscription instead of swallowing them
- Correct codex node prefix to @probo/n8n-nodes-probo.proboTrigger
- Replace unsupported codex categories with Development and Utility

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-15 18:02:14 +02:00
Sacha Al Himdani
6a9ef1468f Release @probo/n8n-nodes-probo/v0.202.0
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-15 17:00:16 +02:00
Sacha Al Himdani
54af2f7846 Release probod/v0.226.0
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-15 16:58:56 +02:00