Commit Graph

5305 Commits

Author SHA1 Message Date
Cursor Agent
b8c3fb086e Separate deadline append for wsl cuddling
require.True cannot sit directly above the deadlines append
under wsl_v5.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 23:08:38 +02:00
Cursor Agent
f844933b7d Fix wsl blank lines in DNS check paths
Separate cancel calls, error checks, and declarations so
golangci wsl_v5 accepts the cuddling rules.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 23:08:38 +02:00
Cursor Agent
fff8319e07 Use SplitSeq for CAA issuer domain labels
go fix on Go 1.26 rewrites strings.Split range loops to
SplitSeq; apply that so lint-go passes.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 23:08:37 +02:00
Cursor Agent
3948f47354 Apply CAA exchange timeout per label
A single dnsExchangeTimeout around CheckCAA let slow empty
answers at child names consume the budget before parent
policy was queried. Give each label its own exchange timeout
inside the climb instead.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 23:08:37 +02:00
Cursor Agent
6a1f6d9273 Restore CAA lookup timeout in provision worker
Keep the previous per-lookup dnsExchangeTimeout around CheckCAA
so rebased dnsclient calls do not drop main's deadline.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 23:08:37 +02:00
Cursor Agent
64ef051d18 Harden DNS CAA and TXT verification
Extract shared DNS checks into dnsclient and fail closed on
truncated or non-success CAA responses. Climb past eTLD+1,
validate RFC 8659 issue-value syntax, and map NXDOMAIN TXT
lookups to the pending-verification path.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 23:08:36 +02:00
Ludovic Vielle
ec65b54583 Release probo-agent/v0.3.0
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 22:48:32 +02:00
Ludovic Vielle
af7f44c0c1 Fix macOS AUTO_UPDATE when updates are disabled
The check read only AutomaticCheckEnabled from /Library/Preferences,
falling back to softwareupdate --schedule when that key was absent.
Both describe automatic checking alone, so a Mac with downloads or
installs turned off still reported PASS. The key is also absent when
a configuration profile manages it, since the value then lives in
/Library/Managed Preferences, a layer never consulted.

Read the five Software Update preferences backing the System Settings
toggles, resolving each from the managed layer before the system one.
macOS treats them as enabled when unset, so only an explicit disabled
value fails. The now-unused softwareupdate binary leaves the command
allowlist.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 22:16:18 +02:00
Ludovic Vielle
2532b0bb6b Add branded Finder icon for Probo Agent.app
The macOS URL-handler bundle had no CFBundleIconFile, so
Finder showed the generic app icon after PKG install. Keep a
single master PNG and generate AppIcon.icns at build time
with sips/iconutil, matching the auditor-mode approach.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 22:16:15 +02:00
Cursor Agent
002437b568 Verify DNS records on the queried child domain
Custom-domain CNAME and SAML TXT checks accepted answers without
confirming the record owner matched the hostname being verified, so
an apex record could satisfy verification for a subdomain. CAA checks
also looked only at the exact hostname and ignored parent policy.

Add dnsverify helpers to compare owner names and walk from the
requested hostname up to the registrable apex for CAA (RFC 6844).
Require matching record owners for CNAME and TXT answers.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 19:34:25 +02:00
Cursor Agent
d100826479 Preserve third party category on partial update
When category was omitted from an MCP, GraphQL, or CLI update payload,
ThirdPartyService.Update overwrote the stored category with OTHER. Only
apply category when the request explicitly includes it, matching other
optional fields on the same update path.

Add an MCP e2e test that updates name without category and asserts the
existing category is unchanged.

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

Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
2026-07-24 19:07:20 +02:00
Sacha Al Himdani
55a1bd03eb Rename My Signatures menu label to Employee Portal
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-24 18:53:41 +02:00
Sacha Al Himdani
eff175f7c1 Release @probo/n8n-nodes-probo/v0.206.2
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-24 18:05:10 +02:00
Sacha Al Himdani
a9e3044b47 Fix n8n Get User organization selection
Connect Organization has no email field. Requesting it made
the Get User GraphQL query fail; align with list/create/update.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-24 17:00:42 +02:00
Ludovic Vielle
cb151c7c5a Release probo-agent/v0.2.0
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 16:54:01 +02:00
Arthur Mayoux
2adcc9ab5c feat(skills): add compliance-portal-commitments skill
Adds a @probo/skills skill for creating and updating the public
commitments (commitment groups and their commitments) shown on a Probo
compliance portal. Commitments are grounded strictly in the
organization's own published Probo policies and written in a factual,
understated engineering voice, following the get context -> draft ->
filter -> publish workflow via the Probo MCP.

- skills/compliance-portal-commitments/SKILL.md
- references/voice.md, references/portal-mechanics.md
- CHANGELOG.md entry under Unreleased

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 16:28:08 +02:00
Ludovic Vielle
0dc64e1944 Simplify macOS pkg to one fat darwin.pkg
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:41 +02:00
Ludovic Vielle
385ddfc0bc Fail Windows elevate on UAC cancel
Start-Process failures left $p null, then exit $null made
PowerShell return 0, so install/uninstall looked successful.
Make launch errors terminating and exit nonzero before
reading ExitCode.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:39 +02:00
Ludovic Vielle
6cac6a8775 Split employee devices from DeviceConnection
viewer.enrolledDevices shared DeviceConnection with the admin
org list, so totalCount had to authorize with both
employee-device:list and device:list. Mirror
EmployeeDocumentConnection: a dedicated EmployeeDeviceConnection
without totalCount, and keep DeviceConnection.totalCount for
the org fleet only. Cover assumed-session device:get IDOR in e2e.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:38 +02:00
Ludovic Vielle
85864a580c Install macOS helper from PKG for XPC enroll
Browser enrollment used osascript on every elevate. Ship a signed
privileged helper installed at PKG time so probo:// can enroll over
XPC with no second admin prompt. Add make install/uninstall/clean for
local PKG test loops, and show alerts only on failure.

Mirror the Go lint path for the macOS SPM package: Make
targets, root configs, and a Linux CI job. Keep checks
syntax-only so they do not need a macOS SDK. Format the
existing sources so the new gates start clean.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:37 +02:00
Ludovic Vielle
754d12d583 Skip tray re-register on deep-link enroll
Browser enrollment succeeds once the device is ACTIVE, but the
macOS URL handler failed whenever install re-bootstrapped a tray
LaunchAgent the PKG had already installed. Skip registration when
the plist is current, treat live bootstrap as best-effort, and
exit successfully if the device is already enrolled so retries
do not show "Enrollment failed".

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:35 +02:00
Ludovic Vielle
238c19d509 Add pre-assume enrolled device status query
The /enroll wait UI polled device state via node(), which
requires an assumed org session, so confirmation never
succeeded for unassumed viewers. Expose viewer.enrolledDevice
behind itam:employee-device:get (own-device, skip assumption)
and point the poller at it.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:34 +02:00
Ludovic Vielle
afe0c84881 Ship signed universal macOS probo-agent pkg
Publish a notarized arm64+x86_64 .pkg from CI with the CGO tray
binary, Probo Agent.app, and global LaunchAgent. Keep the
LaunchDaemon enrollment-gated, align its plist path with the
launchd label, and document the Apple signing secrets.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:33 +02:00
Ludovic Vielle
4a56be2e3e Improve probo-agent tray icon and enrollment menu
Replace the placeholder orange-circle tray icon with the monochrome
Probo logo used in auditor-mode. On macOS, show the icon only (no
menu bar title); keep the title on Windows.

Restructure the context menu: status rows with colored indicators,
an Enroll via… submenu for region selection, and a clearer About
label. Surface enrollment errors in native dialogs instead of stderr.

Fix self-hosted enrollment on macOS by reading the hostname from
osascript's returned value; the default dialog output order broke
URL parsing and silently skipped opening the browser.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:32 +02:00
Ludovic Vielle
ae769f52a1 Serialize enrollment install with enrolling.lock
Concurrent enroll-url launches could both pass the enrollment
marker check and run overlapping elevated installs, racing on
LoadOrExchangeAPIKey and overwriting agent.key.

Add an exclusive flock on {configDir}/enrolling.lock for the
full install path and re-check IsEnrolled under that lock so
only one install exchanges a token and configures the device.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:30 +02:00
Ludovic Vielle
1329f2a28e Add tray browser enrollment with region picker
The tray helper carried a ServerURL default that nothing read.
Unenrolled users can now open the console /enroll page from the
menu: US, EU, or self-hosted in production, or --server for dev.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 15:08:29 +02:00
Ludovic Vielle
952851c743 Seed device fleet and document agent
Populate varied device posture states in seed data and link the
probo-agent release guide from AGENTS.md.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:28 +02:00
Ludovic Vielle
6dbbd70229 Add console devices UI
Add org admin device management, employee self-service enrollment,
posture views, and owner assignment across console routes.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:27 +02:00
Ludovic Vielle
d0dd87c6c7 Add probo-agent binary, installer, and CI
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:25 +02:00
Ludovic Vielle
b442e1ed76 Add device agent library
Provide enrollment, elevated install, posture checks, keystore, and
system-tray helpers shared by the probo-agent binary.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:24 +02:00
Ludovic Vielle
e767dd8377 Add device enrollment API and agent protocol
Expose ITAM REST endpoints for agents, console GraphQL for device
management, and wire probod bootstrap with enrollment e2e coverage.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:23 +02:00
Ludovic Vielle
1f79453386 Add device data model and ITAM service
Introduce device, posture, and enrollment-token entities with ITAM
service policies for agent-managed fleet inventory.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-24 15:08:21 +02:00
Aurélien Sibiril
fa3b7dc2b3 Add docs button to the API-key connect dialog
The Add Source card links to a connector's docs, but the API-key
connect dialog did not, so a user filling in an API key had no path
to the setup instructions. Add a "Documentation" button to the dialog
footer, styled like Cancel and on the left of the Cancel/Connect row,
shown only when the provider has a docs page.

Extract the rendering into a shared ConnectorDocumentationLink
component with a link/button variant (the card keeps the quiet link,
the dialog uses the button) and give DialogFooter an optional start
slot for left-aligned footer content.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-07-24 14:50:18 +02:00
Aurélien Sibiril
b1a67aba00 Link connector docs in the Add Source dialog
The access review Add Source dialog listed each connector with no
path to its setup documentation. Connectors that have a published
docs page on probo.com now surface a "Documentation" link on the
card, opening the page in a new tab; connectors without a page show
nothing extra.

The link is data-driven from the connector registry: a new
DocumentationURL on the provider Registration, populated for the 12
documented providers via a single accessReviewDocsURL helper, is
surfaced as a nullable documentationUrl on ConnectorProviderInfo and
rendered by the console only when present. This keeps the registry
the single source of truth and adds no client-side provider map.

The links resolve once the probo.com access-review docs pages are
deployed; until then they 404, so deploy the docs alongside this
change.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-07-24 14:50:18 +02:00
Bryan Frimin
b963730433 Release probod/v0.234.0 2026-07-24 14:24:30 +02:00
Sacha Al Himdani
bcd05a2e55 Reject empty SAML NameIDs on login
Empty NameID values were stored as '' and occupied the
unique saml_subject index, causing duplicate-key failures
on later logins. Reject blank NameIDs during assertion
validation, return a clear error when a NameID is already
linked to another account, and stop returning internal
errors from the SAML consume endpoint.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-24 14:03:30 +02:00
Bryan Frimin
e12351e0f4 Require verified certs for portal redirect hosts
AddCustomDomain only validates the domain's format before inserting
the row; certificate issuance then runs asynchronously. Every host
that row resolved to was accepted by the OIDC, magic-link, and
compliance-portal OAuth `continue` redirect allowlists, so anyone
could self-register an org, claim an arbitrary domain, and have
users redirected there right after a real login. Found while
re-checking GHSA-r9mf-88r7-g6j9 against the compliance portal
rework: the original session-transfer leak is gone, but this open
redirect on the same allowlist was not.

Gate those allowlists on the domain's certificate having reached
Active or Renewing status, which only happens once DNS has pointed
at Probo's edge and an ACME challenge has actually succeeded.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-24 08:38:17 +02:00
Sacha Al Himdani
5c5f60d5e1 Render longer vetting notes as markdown
Keep more of the orchestrator assessment text,
skipping profile fields already on the third party,
and render the notes as markdown in the console.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-23 08:50:22 +02:00
Aurélien Sibiril
3805afc806 Fix PostHog source disconnected on EU cloud OAuth
The connection-status probe and the access-review driver each had
their own copy of the "try us.posthog.com, then eu.posthog.com"
region-discovery loop, and they drifted. The driver skips a region
that rejects the token (wrong region) and uses the one that answers
2xx; the probe instead returned "credential rejected" on the first
region's 401/403, before ever trying the second.

PostHog Cloud US and EU are separate deployments, so an EU OAuth
token is a 401 on us.posthog.com, which is probed first. The probe
bailed there and marked the source disconnected, while access-review
campaigns -- which use the driver -- kept working.

Delete the probe's copy and delegate to the driver's now-exported
ResolvePostHogRegion, the single resolver the campaign also uses. It
flags a credential every region rejected (ErrPostHogCredentialRejected)
apart from a transient failure on the token's own region, so the probe
marks a source disconnected only for a genuinely dead token and does
not flap on a passing 5xx.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-07-22 22:44:41 +02:00
Sacha Al Himdani
386962dff6 Fix npm audit vulnerabilities in Vitest and transitive deps.
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-22 19:40:25 +02:00
Bryan Frimin
eaea090ac4 Style
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 17:59:01 +02:00
Bryan Frimin
318bbd40ef Release probod/v0.233.0 2026-07-22 17:56:12 +02:00
Bryan Frimin
0b577cda40 Fix global rate limit ACME
Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-07-22 17:53:20 +02:00
Émile Ré
0f7b639d2f Freeze backdrop pose when the pointer leaves
Leaving mid-ease left the 150ms transition running toward the last
target; snapshot the computed transform and clear transition instead.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-22 17:42:39 +02:00
Émile Ré
0689ac7d14 Defer parallax snap until pointer is idle
Reset the enter-ease timer on each move so transition:none cannot
cut off a retargeted interpolation mid-flight.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-22 17:42:39 +02:00
Émile Ré
1fc453f839 Smooth backdrop parallax on pointer enter
The first eased frame was cancelled by the next pointermove flipping
transition to none, which snapped the blur when entering at an edge.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-22 17:42:39 +02:00
Émile Ré
87f1ee9081 Add pointer parallax to logo backdrops
MediaTile and BackdropCard share opposite-pointer blur tracking over
the full card, with Figma-matched opacity/zoom per surface, eased
enter, and a frozen pose on leave.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-22 17:42:38 +02:00
Aurélien Sibiril
a0ead155db Trim access-review connector comments
Cut verbose inline comments across the access-review connector changes:
the mechanical fact stays at the read site, while incident backstory
("millions of error logs in prod") and provider-specific rationale (why
Clerk reviews the wrong population) move to the commit history where they
belong. Also tighten a loose "a 4xx" to "an auth/not-found 4xx" so the
terminal-classification contract is not overstated. No behavior change.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-07-22 17:27:55 +02:00
Aurélien Sibiril
a7bcbbcd85 Document Cloudflare per_page floor and Vercel teamId
Note that Cloudflare requires per_page in 5..50 so nobody optimizes
it back to per_page=1, which returned 400 and, before terminal
classification, produced a 400 storm. Also correct a stale team_id
reference in the Vercel user-fetch comment: the OAuth callback
surfaces the team as teamId.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-07-22 17:27:55 +02:00
Aurélien Sibiril
d18127503d Pin Vercel OAuth callback team parameter name
The Vercel connector reads the team from the camelCase teamId callback
parameter, unlike the snake_case params most providers use. Nothing
guarded the name, so a regression back to team_id would silently drop
the team on every Vercel connect and leave the source resolving no
users.

Extract the read into vercelCallbackTeamID and pin the exact parameter
name with a test, since the surrounding handler needs a live connector
registry and database to exercise directly.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-07-22 17:27:55 +02:00