Introduce a Resolver that owns env lookup and typed parsing for
probod-bootstrap. Env values prefixed with aws://<secret-id> are
fetched from AWS Secrets Manager (plaintext SecretString); each
secret ID is cached per run. Builder now takes a Resolver only.
Prefix every probod-bootstrap input with PROBOD_ so bootstrap config
does not collide with unrelated process environment (for example
AWS_* used by other tooling). Secrets Manager authentication uses
the standard AWS SDK default chain (AWS_REGION, IAM role, profile);
PROBOD_AWS_* vars configure S3 in the generated config only.
Update Helm deployment env names, GNUmakefile dev-config, Lima
provision, e2e testutil, compose.prod.yaml, and docs.
Deployments must rename bootstrap env vars to PROBOD_* (e.g.
AUTH_COOKIE_SECRET → PROBOD_AUTH_COOKIE_SECRET).
BREAKING CHANGE: all env vars are now prefixed by `PROBOD_`.
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
When a new minor version is published, still-REQUESTED signature requests
on the previous version now move onto the newly published version, keeping
the same signature row so the notification schedule (count and last-notified
time) is preserved. SIGNED signatures are left untouched.
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
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>
DocuSign approved our partner integration, so the connector can now
complete a real OAuth2 authorization-code flow. The integration key
has PKCE enabled, so RequiresPKCE is set; the confidential grant still
authenticates the token exchange with Basic auth and replays the
verifier as the documented hardening layer.
A DocuSign user may have access to several accounts, so this replaces
the previous auto-default-account behavior with a Pattern-1 picker:
the user chooses the account after OAuth, the choice is stored on
DocuSignConnectorSettings, and the driver and name resolver resolve
the selected account's data-center base URI from /oauth/userinfo.
Other changes:
- Request the extended scope so the refresh token's 30-day window
rolls on each use; without it the token hard-expires 30 days after
consent and breaks the connection.
- Drop API-key support: DocuSign has no static API key, only OAuth.
- Return ("", nil) from the name resolver on terminal failures so the
source-name worker does not retry a revoked token forever.
- Add a driver test and cassette; the test previously skipped in CI
for lack of a cassette.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
Heroku's connection-status probe used a static ProbeURL, which the
generic probe issues with `Accept: application/json`. Heroku negotiates
the API version through the Accept media type and returns 400 for an
unversioned request, which doProbeRequest reads as "connected" -- so the
probe never caught a revoked token (it only surfaced at the first
ListAccounts).
Probe via a probeHeroku closure that sends
`Accept: application/vnd.heroku+json; version=3` instead. Verified live:
a dead token returns 400 with application/json but 401 with the
versioned header, which doProbeRequest correctly maps to rejected.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
Add Mercury, Apollo.io, Deepgram, ClickHouse Cloud, and Langfuse as
access-review connectors. All are API-key, single-tenant providers
(Pattern 3): the key identifies one tenant, so there is no OAuth flow,
picker UI, or bootstrap/helm configuration.
- Mercury: Bearer token, GET /api/v1/users, cursor pagination.
- Apollo.io: x-api-key header, GET /api/v1/users/search (teammates).
- Deepgram: Token scheme; lists members across every project and
dedupes by member_id, unioning per-project scopes.
- ClickHouse Cloud: HTTP Basic (keyId:keySecret); discovers the org
via GET /v1/organizations, then lists its members.
- Langfuse: HTTP Basic (publicKey:secretKey); a base-URL setting
selects the regional cloud host or a self-hosted instance.
Each adds the enum value, migration, GraphQL binding, provider
Registration, a driver with a cassette-driven test, and a brand logo.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
The API-key connection transport could present a key as a Bearer token,
an x-api-key header, a custom scheme (SSWS/Token), or HTTP Basic with an
empty password (Cursor). None of these can carry a real password, which
providers such as ClickHouse Cloud (keyId:keySecret) and Langfuse
(publicKey:secretKey) require.
Add a fourth mode, APIKeyBasicAuthUserPass, that base64-encodes the
stored "username:password" credential verbatim into Authorization: Basic.
SetBasicAuth cannot express this -- it re-appends a ":" and corrupts the
credential. The mode is wired generically through the registry and the
create-connector resolver and is mutually exclusive with the other
API-key auth modes.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
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>
The lockfile was regenerated with npm 11.6.2, which omits optional
platform-specific dependencies for non-host platforms (npm/cli#4828).
This dropped the @rolldown/binding-linux-x64-gnu entry (vite 8 / rolldown
native binding) and broke Linux CI with "Cannot find native binding".
Regenerated with npm ^11.8.0 so all 15 @rolldown/binding-* platforms are
recorded in the lockfile.
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
Regenerate the stale package-lock and pin patched versions for the
Dependabot-flagged packages (@vitest/browser, form-data, undici,
brace-expansion, js-yaml, esbuild, dompurify, @babel/core, vite,
@opentelemetry/core via posthog-js). Remove the harmful langsmith
override (it forced the vulnerable 0.5.x line) and the zero-effect
lodash-es override.
Signed-off-by: Sacha Al Himdani <sacha@probo.com>
Upgrade golang.org/x/image from v0.41.0 to v0.43.0 to remediate two
vulnerabilities: CVE-2026-33813 (denial of service via malformed WEBP
parsing, fixed in v0.42.0) and CVE-2026-46602 (missing limit on tile
sizes in x/image/tiff, fixed in v0.43.0). The bump also pulls in
golang.org/x/text v0.38.0 transitively.
Signed-off-by: Émile Ré <emile@probo.com>
Introduce BearerChallengeMiddleware on MCP, Console and Connect GraphQL, Files, and OAuth2 userinfo. Call sites record challenge intent in context via NoteUnauthenticated, NoteInvalidToken, and NoteInsufficientScope; the middleware applies resource_metadata, invalid_token, and insufficient_scope on WriteHeader.
OAuth2 access token middleware flags rejected Bearer tokens for invalid_token challenges. Add Authorizer.ScopesForAction for the scope auth-param.
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
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>
Rename the resolver helper to ResourceAliasResolver so it reads as a
resolver rather than a storage-resource-specific accessor, and update
its three call sites in the trust center resolvers.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Replace the trust center alias console and MCP end-to-end tests with
resource alias equivalents exercising the new mutations and tools.
Signed-off-by: Bryan Frimin <bryan@probo.com>
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>
Move the set and remove alias operations out of the trust center
resource into a dedicated resourceAlias resource so n8n workflows can
alias any resource.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Promote the trust-center alias subcommand to a top-level
resource-alias command so aliases can be managed for any resource
from the CLI.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Rename the setTrustCenterAlias and removeTrustCenterAlias MCP tools to
setResourceAlias and removeResourceAlias, backed by the resourcealias
service.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Switch the trust center API to resolve aliased nodes via the
resourcealias service instead of the trust-center-specific alias
resolvers.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Drop the setTrustCenterAlias and removeTrustCenterAlias mutations and
the alias field on Audit in favor of generic setResourceAlias and
removeResourceAlias mutations backed by the resourcealias service.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Introduce a standalone resourcealias package with its own service,
IAM policies, and OAuth2 scopes so alias management no longer lives
inside the trust center services. Remove the trust-center-specific
alias services from probo and trust, and wire the new service into
probod, the server, and the API layer.
Signed-off-by: Bryan Frimin <bryan@probo.com>
The trust_center_aliases table only allowed aliasing trust center
resources. Rename it to resource_aliases and scope uniqueness by
tenant rather than organization so any resource can carry an alias.
Replace the TrustCenterAlias coredata type with a ResourceAlias type
that loads and upserts aliases by resource ID.
Signed-off-by: Bryan Frimin <bryan@probo.com>
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>
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>
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>
OpenAI rejects schemas where optional properties are absent from the
required array. Promote all properties to required and mark formerly
optional ones nullable so the model knows it may pass null.
Also upgrade tool error log level from Warn to Error.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Node lookup now accepts an alias slug in addition to a GID, resolving
it against the organization's alias table before dispatching. Adds
alias fields to Document, AuditReport, and TrustCenterFile.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Adds an alias field to Document, Audit, and TrustCenterFile types.
Introduces setTrustCenterAlias and removeTrustCenterAlias mutations
with proper authorization and error handling.
Signed-off-by: Bryan Frimin <bryan@probo.com>
The sitemap now covers files and audit reports alongside documents
and resolves aliases so human-readable paths appear when configured.
Signed-off-by: Bryan Frimin <bryan@probo.com>