Redirect visitors through the compliance portal OAuth initiate
endpoint and remove the verify-magic-link page and routes.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Store website, email, and headquarters on the trust center so
public and admin surfaces read branding from one place. Drop the
trust API organization type and wire console, MCP, CLI, and apps
through the updated schema.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Stop relying on the /trust/{id} path prefix in the public trust app and
serve it from the host root, reading contact and profile data from the
trust center instead of the organization. Mirror the same fragment
ownership change in the compliance portal hero.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Decompose the brand page into profile, domains, visual identity, and
custom link sections, and move frameworks and the NDA card onto the
overview page as dedicated fragment components. Remove the standalone
domain page and redirect its route to brand, where domains now live.
Signed-off-by: Bryan Frimin <bryan@probo.com>
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>
Emit lifecycle events for rights requests created through either the
console or compliance portal. Keep webhook subscription choices in sync
across every API and client surface.
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Sacha Al Himdani <SachaProbo@users.noreply.github.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Size desktop pages to HeaderBand's max-w-5xl column so
they line up with the title and toolbar. Mobile gutter is
unchanged.
Signed-off-by: Émile Ré <emile@probo.com>
Fit-to-width at 100% used a phone-sized inset on all
viewports. Use the HeaderBand px-8 gutter on desktop so
the page aligns with the hero; keep mobile unchanged.
Signed-off-by: Émile Ré <emile@probo.com>
ListItemSkeleton reused a sand-2 fill that read as a
different card; use the real row shell with pulse bars
instead, and shrink the updates skeleton to five rows.
Signed-off-by: Émile Ré <emile@probo.com>
Introduce a v2 z-1…z-6 stacking scale so portaled
menus sit above in-page media, and redirect the
legacy /overview trust-app URL to home.
Signed-off-by: Émile Ré <emile@probo.com>
Embed and build @probo/compliance-portal for the
/trust path and custom-domain SPA so production
ships the v2 portal. Keep apps/trust in the repo
for local use on port 5175; portal takes 5174.
Signed-off-by: Émile Ré <emile@probo.com>
The previous label implied review plus approval, but the action only
approves. Update the consent text to match the new button wording.
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Expose pending access status to assistive tech on
mobile rows, and recompute the visible PDF page
after fit-to-width reflow without writing refs
during render.
Signed-off-by: Émile Ré <emile@probo.com>
Promote the portal burger shell into a reusable
Drawer matching Dialog (thin Base UI + tv slots).
TopBarMobileNav now composes the kit parts.
Signed-off-by: Émile Ré <emile@probo.com>
The responsive burger drawer added openMenu, closeMenu,
and menuTitle only in en-US and fr-FR. Mirror those keys
across the remaining compliance-portal catalogs.
Signed-off-by: Émile Ré <emile@probo.com>
Add a burger drawer below md, fix document-flow
scrolling so PoweredBy sits after content, and
collapse home grids, list rows, toolbars, and
dialogs for smaller viewports. PDF viewer fits
width; updates skeleton mirrors stacked meta.
Signed-off-by: Émile Ré <emile@probo.com>
Address PR review: avoid reintroducing cleared URL markers,
treat already-closed sessions as successful logout, and stop
stale subscribe/sign-out completions from racing the UI.
Signed-off-by: Émile Ré <emile@probo.com>
Visitors can subscribe after sign-in via the Updates
CTA or user menu. Also add trust signOut so Log out
works from the menu.
Signed-off-by: Émile Ré <emile@probo.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>