Commit Graph

1746 Commits

Author SHA1 Message Date
Émile Ré
86077e6c27 Set up i18next with lazy per-route catalogs
Wire i18next into the compliance portal with a custom backend built on
import.meta.glob, so each _locales/*.json becomes its own lazily loaded
chunk keyed by a namespace derived from the folder path. The active
language is resolved from the browser, collapsing any fr*/en* tag to
fr-FR/en-US with en-US as the ultimate fallback; fallbackLng then only
covers individual missing keys.

Add an app-level default namespace catalog and switch the documents
page title to a translation key to exercise the lazy-loading path.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-28 13:58:14 +02:00
Émile Ré
6ec7efb4fc Use layout skeleton as the root route fallback
On a hard reload the root route briefly showed a generic centered pulse
(PageSkeleton) while the layout chunk downloaded, then snapped to the
topbar skeleton. Point the root Fallback at MainLayoutSkeleton so the
chunk-load fallback matches the loader's own skeleton and the transition
is seamless. PageSkeleton is now unused and removed.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 22:35:20 +02:00
Émile Ré
fe8ac00c70 Add Trust Center hero and page headers
Build the Trust Center landing hero and the nav page headers on a shared
HeaderBand shell. The home page loads its own query and feeds the Hero
(org headline, description, and contact info) via a colocated fragment;
the Documents, Subprocessors, Updates, and Data Requests pages use a
PageHeader (size-7 title, optional count, inline actions). Switch the
layout body to the grey sand-2 canvas so the white header bands read as
surfaces on top.

Split the header UI into focused components rather than one
over-configurable Hero: HeaderBand owns the band, Hero the landing
content, PageHeader the nav-page content. Add a hostname helper under
lib/url and standardize the 1024px container on the max-w-5xl token.

The Documents/Subprocessors filter/search/tabs toolbars and item counts
are deferred until the matching v2 components and queries exist.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 22:33:03 +02:00
Émile Ré
68eaabe0ea Add Trust Center top bar to compliance portal
Build the Trust Center top navigation in a Relay-wired layout route. The
portal now mounts a Relay environment and provider, and the root layout
loads a query whose fragment feeds the TopBar: brand, ghost-pill nav with
an active state from the router, and a guest "Get Access" button versus an
authenticated user menu. Placeholder section routes keep the nav links and
active state functional until real pages land.

Wire the Relay tagged-template transform via @rolldown/plugin-babel and
set the router basename to the /trust/{slug} path prefix so the app
resolves under its served path.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 21:55:09 +02:00
Émile Ré
4656469c47 Drop unused eslint-plugin-relay-types from apps
The @probo/eslint-plugin-relay-types shim only types an
`eslint-plugin-relay` import, which no app makes anymore now that
linting runs through the single root eslint.config.mjs. The apps'
tsconfig.node.json even pulled it in for a per-app eslint.config.mjs
that no longer exists.

Remove the devDependency and the `types` entry from each app's
node tsconfig, and drop the stale eslint.config.mjs include. The
shim stays for packages/eslint-config, its real consumer.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:06 +02:00
Émile Ré
ff966b462e Promote useMutation to the @probo/relay package
Extract the awaitable useMutation into @probo/relay as a
createUseMutation factory that delegates feedback to an injected
MutationNotifier, keeping the package free of UI and i18n
dependencies. compliance-portal binds it to its Base UI toast +
i18next + formatError stack and imports it by explicit path
(#/lib/relay/useMutation), dropping the lone intra-app barrel; a
compliance-portal-scoped no-restricted-imports rule forbids
react-relay's useMutation.

Bring packages/relay and packages/routes into the shared ESLint
scope and fix the violations that surfaced, and deprecate the
legacy withQueryRef / loaderFromQueryLoader helpers. Document the
shared-hook pattern and the "index.ts for package entrypoints only"
rule in the relay, hooks, and app-arborescence guides.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:05 +02:00
Émile Ré
023fb70a58 Add routing foundation to compliance-portal
Wire up react-router with a root layout route and an index home page,
following the single-arborescence conventions: pages live under pages/,
routes are built from AppRoute via routeFromAppRoute, and route bundles
load lazily behind a Suspense fallback.

Add the @probo/routes and @probo/react-lazy workspace dependencies that
the route setup relies on.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:05 +02:00
Émile Ré
eabf46c5cb Add HTTP endpoint helpers to compliance-portal
Introduce a lib/http module with buildEndpoint and getPathPrefix,
extracted from the trust app so the compliance portal can resolve its
GraphQL endpoint with the same path-prefix handling.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:05 +02:00
Émile Ré
18d4b8aa02 Add compliance-portal bundle entrypoint on v2 theme
The compliance-portal scaffold had an index.html pointing at a
src/main.tsx that did not exist, and carried stale config copied
from another app, so the bundle could not build.

Add the React entrypoint (main.tsx, App.tsx), a Tailwind index.css
wired to the standalone v2 theme, and vite-env.d.ts for the CSS
side-effect import and env typing. Scope the Tailwind @source scan
to packages/ui/src/v2 since this is a v2-only build, and use v2
color and type scales in index.html and App.

Drop the deprecated baseUrl from tsconfig.app.json and remove the
invalid react() babel relay option, which is unsupported by
@vitejs/plugin-react 6 and unneeded until Relay queries exist.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:05 +02:00
Émile Ré
c9cc46d359 Migrate compliance-portal to the global ESLint config
The compliance-portal app still carried the per-workspace ESLint
scaffold that the rest of the monorepo dropped when linting was
centralized into the root eslint.config.mjs. It defined its own
local config, lint script, and lint-only devDeps, and was not
covered by the root lint script, so it was never linted.

Remove the local eslint.config.mjs, the lint script, and the
eslint/@probo/eslint-config devDeps, then add the app to the root
appDirs so the shared ts, react, and relay rule sets apply to it.

Replace the explicit per-directory list in the root lint script
with a bare `eslint .`, which the root config was already designed
for via its globalIgnores. Ignore pkg/** so the vendored minified
JS under the Go tree is not linted.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:04 +02:00
Émile Ré
5bc6452eb6 Scaffold compliance-portal frontend app
Add the root configuration files for apps/compliance-portal, the
refactor of the legacy trust center SPA. The scaffold mirrors the
existing trust app (Vite, Tailwind, Relay, TypeScript project
references, ESLint) and targets the trust v1 GraphQL schema, which
the compliancepage backend already serves under /api/trust/v1.

Wire the app into the root relay.config.json with a dedicated
complianceportal project so the Relay compiler emits artifacts for
its sources. External dependencies are pinned to current latest
versions rather than matching the older majors used by the other
apps.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-26 18:52:04 +02:00
Sacha Al Himdani
45b434dd99 Redirect employee to tab list for missing documents
When an email link points to an employee signature or approval document
that has been deleted or is no longer accessible to the user, the detail
pages rendered an infinite spinner. Redirect to the signatures/approvals
tab list instead, both when the document resolves to null and when it has
no accessible versions.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-06-24 19:13:29 +02:00
Cursor Agent
002c91ba11 Fix third party assessment header
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Sacha Al Himdani <SachaProbo@users.noreply.github.com>
2026-06-23 15:04:20 +00:00
Sacha Al Himdani
a8e8e3e0e7 Allow signature requests only on current published version
Requesting a signature only validated that the version was PUBLISHED, so a
signature could be requested on a superseded (older) published version. Reject
versions that are not the document's current published major/minor, and hide
the request button in the console for non-current versions.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-06-23 16:39:18 +02:00
Bryan Frimin
87f769a816 Style
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-22 11:40:18 +02:00
Bryan Frimin
cb7fb8f5e9 Split trust node lookup into node and aliasedNode
The trust node query previously accepted a String and resolved both GIDs
and slugs through one field, which forced the frontend to lose the ID
type guarantee. Restore node(id: ID!) as a strict GID lookup and add a
dedicated aliasedNode(alias: String!) that parses a GID first and falls
back to slug resolution before delegating to Node.

Inline the former nodeByGID switch directly into Node and drop the helper
file. Point the trust DocumentPage query at aliasedNode so slug-or-ID URLs
keep working.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-22 11:40:17 +02:00
Bryan Frimin
a81d3921cf Use resource alias mutations in compliance page
Update the compliance page alias field and list items to call the
generic setResourceAlias and removeResourceAlias mutations instead of
the trust-center-specific ones, and drop the now-removed audit alias
field usage.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-22 11:40:16 +02:00
Bryan Frimin
92b1264603 Fix alias resolver, field blur, and sitemap URLs
The audit alias resolver returned raw service errors. Log them
and return gqlutils.Internal like other resolvers in the file.

Remove-only users could edit the alias field to a new value that
was never saved. Reset local state when set permission is missing,
and catch mutation rejections on blur.

Sitemap generation appended audit report file IDs without
deduplication, which could emit duplicate document URLs when
multiple audits share the same report file.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-22 11:38:51 +02:00
Bryan Frimin
cd52e7fb0c Use alias slugs for navigation in trust center
Document, file, and audit rows now navigate to /documents/<alias>
when an alias is set, falling back to the resource ID otherwise.
The document page query accepts a string ID to support both forms.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-22 11:38:51 +02:00
Bryan Frimin
391ec141e3 Show alias field in compliance page list items
Adds an editable alias column to the documents, files, and audits
tables so operators can set and clear aliases from the console.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-22 11:38:50 +02:00
Émile Ré
4d28dab2f4 Centralize ESLint into a single root config
Replace the duplicated per-workspace eslint.config.mjs files in
apps/console, apps/trust, packages/ui, and packages/eslint-config with
one root eslint.config.mjs that reuses the shared @probo/eslint-config
rule sets and scopes them per directory. Linting now runs from the repo
root, so pin the type-checked project service root and broaden the
import-x resolver to every workspace tsconfig (the #/* aliases live in
each app's tsconfig.app.json).

Drop the now-redundant per-package lint scripts and lint-only devDeps,
and add a root lint script that runs eslint over the four dirs with
multithreading restored via --concurrency auto, then lints n8n-node
through a direct workspace call. packages/n8n-node keeps its own
external preset.

Collapse the redundant lint-js -> npm-lint Makefile chain into a single
lint-js target and update the make docs accordingly.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 16:47:43 +02:00
Émile Ré
4348c409a1 Fix lint findings on upgraded console pages
Wrap the usePreloadedQuery calls whose explicit type arguments pushed
them past the 120-character limit, and merge the two duplicate
@probo/helpers imports in FrameworkControlPage into one. These were
flagged by reviewdog on the dependency-upgrade PR.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 14:31:30 +02:00
Émile Ré
abb641111a Fix rela type issue
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 14:27:25 +02:00
Émile Ré
7e943c8105 Drop merged GraphQL schema for split files
Relay no longer needs a single merged schema.graphql: each project in
relay.config.json now reads the split graphql/*.graphql files directly
via `schema` (base.graphql) plus `schemaExtensions`. gqlgen already
consumed the split files, so the merge step only fed Relay and the
optional IDE GraphQL extension.

Remove the merge machinery (contrib/merge-graphql-schema.sh, the
RELAY_SCHEMAS make rules, and the gitignore entry) and drop the
graphql-config files (apps/trust/graphql.config.yml and the root
package.json graphql field); the Relay extension provides schema-aware
language features from relay.config.json on its own.

relay-compiler keeps generated artifacts in sync (stale ones are
removed automatically), so the relay npm script just runs the local
relay-compiler and the make target delegates to it.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 13:51:17 +02:00
Émile Ré
89427845c4 Fix type-aware lint errors on OAuth tokens page
The linter's project service ignores the generated Relay artifacts,
so the untyped usePreloadedQuery call left viewer as an error type and
triggered no-unsafe-argument/member-access errors. Pass the explicit
query generic like the sibling audit-log page does.

Drop the redundant GraphQLError cast on the revoke error handler since
formatError already accepts the callback's error type.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-19 13:51:17 +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é
f56d3daa2c Make tracker pattern category editable on detail page
The category property on the tracker pattern detail page was
read-only text. Wire in the existing MoveToCategorySelect and the
moveTrackerPatternToCategory mutation so a pattern can be recategorized
directly from its detail view, matching the table-row behaviour.

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
Ludovic Vielle
26c5002932 Add identity-scoped OAuth token management
Let users create, list, and revoke manual bearer tokens from
/me/oauth-tokens, scoped to their identity rather than an
organization. Manual tokens store a null client_id and are
authorized with a self-manage IAM policy.

Wire Connect GraphQL on Identity (list, create, revoke), add
console UI with scoped create flow and credentials dialog, and
cover the flow in e2e tests. Fix list pagination ordering and
keep the Relay connection in sync after create.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-18 20:08:49 +02:00
Ludovic Vielle
3ebb221a9b Add OAuth2 API scope registration and enforcement
Register v1 API scopes in coredata, advertise them in OIDC discovery
and protected-resource metadata, show them on the consent screen, and
enforce scope-to-action mapping in the IAM Authorizer before policy
evaluation.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-18 19:07:25 +02:00
Sacha Al Himdani
f462b124e6 Batch signature and approval notifications via debounced worker
Replace the immediate per-document approval email and the manual
"send signing notifications" action with a single debounced worker that
batches pending requests per recipient and organization.

The worker (go.gearno.de/kit/worker) polls on an interval (default 5m)
and claims one (organization, recipient) group at a time, sending one
consolidated signing email and/or one approval email per recipient/org
that lists every document awaiting their signature or approval. The
claim is a conditional UPDATE that doubles as concurrency-safe dedup, so
several workers never email the same group twice.

Each request is notified once it has been pending past the debounce
delay (default 15m), then reminded at 1x, 2x and 3x the reminder
interval (default 1 day) after the previous email, after which it stops.
New last_notified_at and notification_count columns on signatures and
approval decisions drive the debounce, the widening reminder cadence and
the four-email cap.

Email copy lists each document with its title, type and a deep link to
the employee page. Removed the inline approval-on-publish email, the
SendSigningNotifications service method/mutation/MCP tool, its IAM action,
and the related console UI and n8n operation.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-06-18 15:39:04 +02:00
Bryan Frimin
2c8ae26ea1 Open OIDC child session when assuming organization
OIDC login dropped organization_id before the provider redirect, so
callbacks with an existing matching root session never created an org
child session. Persist organization_id in OIDC state, open the child
session on callback, and forward the parameter from the sign-in UI.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-18 12:11:01 +02:00
Émile Ré
579a382947 Remove tmp modifications
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-18 11:44:14 +02:00
Émile Ré
f49d7846e4 Make v2 theme a standalone colors config
Turn the v2 theme into a build-level standalone color system instead
of a runtime-scoped add-on. Reset Tailwind's default palette and keep
only transparent, black, white, and the Radix scales, so an app opts
into v2 by importing it in place of the v1 theme.

Drop the redundant [data-theme="v2"] block: isolation now comes from
the separate import, and the inline utilities never read those tokens.
Update the v2 color guide to describe build-level isolation.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-18 11:44:13 +02:00
Cursor Agent
c195320649 Add document delete confirmation
Route document deletion through explicit confirmation dialogs so single and bulk delete actions require users to acknowledge the destructive operation before the mutation runs.

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

Co-authored-by: Sacha Al Himdani <SachaProbo@users.noreply.github.com>
2026-06-17 07:55:00 +00:00
Ludovic Vielle
8094e7cfd0 Truncate access review roles with badge list
Long role strings in the access review table broke row layout when
drivers joined many roles into one comma-separated value. Expose
roles as a string array in GraphQL by splitting the stored role at
the API layer, and render the first three roles as badges with a
"+X more" popover for the rest.

Closes ENG-459.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-16 11:25:31 +02:00
Sacha Al Himdani
bf20ca1a90 Add esign to document signatures
Employee document signatures recorded an acknowledgment with no
cryptographic proof, unlike document approvals which already create
and accept an electronic signature on every decision.

Mirror the approval flow on the sign path: generate the signed
document PDF, create-and-accept an esign record, and persist its id
on the document_version_signatures row through a new
electronic_signature_id column. Capture the signer IP and user agent
in the resolver, and re-check the published/archived preconditions
inside the transaction so the seal cannot race document state.

Make the consent wording a single backend source of truth shared by
the text that is sealed and the text shown in the UI. Define
DocumentSignatureConsentText and DocumentApprovalConsentText in the
probo service package and the NDA copy in the trust service, each
owned by the flow that uses it, and stop esign from appending the
generic clause to caller-provided consent text so approvals no
longer seal a duplicated sentence.

Expose the resolved consent text through GraphQL on
EmployeeDocumentVersion and DocumentVersionApprovalDecision, and have
the signing, approval, and NDA pages render it from the API instead
of hard-coded strings, mirroring how the NDA page already worked.

Align the wording with the actual interaction: the buttons read
"Review and sign" and "Review and approve", the clauses reference
those actions, and the inaccurate "typing my full name" phrasing is
removed everywhere.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-15 19:18:42 +02:00
Bryan Frimin
eed6bf579d Refactor access review campaign source API
Expose campaign sources as first-class nodes, paginate fetch attempts
instead of denormalized status fields, and bind entries to their
campaign snapshot. Update GraphQL, MCP, CLI, console, and e2e coverage
to match.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-15 16:49:08 +02:00
Bryan Frimin
8d8a5ebb26 Probe every access review connector on status check
Bad API keys and expired OAuth tokens showed Connected because
probes ran only for OAuth2 and many providers had no ProbeURL.
Add a registry ProbeConnection dispatcher with static, dynamic,
and custom probes so all 41 providers are checked on demand.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-15 16:49:07 +02:00
Bryan Frimin
26d64a970f Remove deleted source badge from campaign detail
The badge did not help reviewers act on campaign entries once a
source snapshot is attached.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-15 16:49:07 +02:00
Bryan Frimin
a30a714fcd Style
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-15 16:48:54 +02:00
Bryan Frimin
4b64e59da4 Introduce access-review source snapshot and normalize naming
Decouple each campaign from the live access-review sources it was started
with by introducing a per-campaign source snapshot table
(access_review_campaign_sources). The snapshot captures the source name,
category, and connector at start time, so a review remains coherent even
after the underlying source is edited or deleted. Fetch tracking becomes
an append-only log (access_review_campaign_source_fetch_attempts) that
preserves every attempt with its own status and error rather than
overwriting a single row.

Rename the shared access-review tables and enums to use a consistent
access_review_ prefix throughout:

  access_entries          → access_review_entries
  access_sources          → access_review_sources
  access_source_category  → access_review_source_category
  access_entry_*          → access_review_entry_*

The same rename propagates to every coredata type, service, GraphQL
schema, MCP specification, CLI command, frontend component, and e2e test.
The accessreview package gains dedicated actions.go and policies.go files
for its own IAM policy set, mirroring the agentrun package pattern.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-15 15:33:22 +02:00
Sacha Al Himdani
99d568d07d Fix activate login path
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-12 12:53:15 +02:00
Ludovic Vielle
eccef41767 Adopt File type for trust logos and MCP
Trust GraphQL and MCP still exposed presigned URL strings for
trust-center logos while console and connect already serve stable
File.downloadUrl paths. Phase 1 migrates the seven public logo
fields on trust GraphQL and the trust-center file references on MCP
to the shared File type; trust GraphQL NDA stays on fileUrl for a
follow-up.

Trust resolvers load public files through filemanager and map them
with types.NewFile. The trust app Relay queries and components now
read logo.downloadUrl. MCP specification, resolvers, and helpers
are updated in sync, including NDA on MCP where callers already
have file access.

filemanager is split into focused files and its URL surface is
narrowed to GenerateFileURL(file) for stable app URLs and
GeneratePresignedURL for S3 redirects. GetPublicFile remains the
DB entry point when only a file ID is known.

Add trust and MCP e2e coverage for public logo download URLs.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-11 16:03:45 +02:00
Ludovic Vielle
e06f3e0520 Migrate Connect org logos to File type
Replace Organization.logoUrl and horizontalLogoUrl with nested File
objects whose downloadUrl points at /api/files/v1/public/{id}, matching
the Console migration.

Org logos are FileVisibilityPublic and served without HTTP auth, so
Connect File.downloadUrl is built eagerly in NewFile with no field-level
authorize. Logo loading moves to iam.OrganizationService.LogoFile and
HorizontalLogoFile; the old URL generators are removed.

Sync IAM Relay components and n8n organization operations. Add an e2e
test for Connect multipart logo upload and ExecuteConnectWithFile.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-11 13:55:44 +02:00
Sacha Al Himdani
c7e2fc209f Use probo.com for bare and marketing domain references
Replace the bare `getprobo.com` domain and the `www.getprobo.com`
marketing host with `probo.com` / `www.probo.com` across the codebase.
Functional subdomains (app, console, notification, custom, test,
cookie-banner, compliance) keep their existing `getprobo.com` hosts,
and changelog entries are left untouched.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-11 13:46:10 +02:00
Émile Ré
6757c07bd5 Fix fragment
Signed-off-by: Émile Ré <emile@probo.com>
2026-06-11 12:29:25 +02:00
Émile Ré
e685ce436e Restyle tracker row and category select
Stack the tracker type badge above the pattern name and drop the
separate Type column so the now-wider row reads more compactly; the
edit row spans the reduced column count. Tint script-sourced rows light
blue (excluded styling still wins when both apply).

Make the move-to-category select stand out when the tracker sits in a
real category by switching it to the highlighted pill variant, and align
its ghost-variant padding so the label does not shift horizontally
between categorised and uncategorised rows.

Signed-off-by: Émile Ré <emile@probo.com>
2026-06-11 12:08:23 +02:00
É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