Commit Graph

3738 Commits

Author SHA1 Message Date
Sacha Al Himdani
d40b114f0f Add document resource to n8n node and MCP sendSigningNotifications tool
Add a complete document resource to the n8n node with 21 operations
covering documents, versions, and signatures — matching the MCP
specification. Also add the sendSigningNotifications tool to the MCP
API for triggering pending signature reminders.

n8n operations: create, get, getAll, update, delete, archive,
unarchive, getVersion, getAllVersions, createDraftVersion,
updateVersion, deleteDraftVersion, publishMajorVersion,
publishMinorVersion, requestApproval, voidApproval, getSignature,
getAllSignatures, requestSignature, cancelSignature,
sendSigningNotifications.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-13 17:31:06 +02:00
Sacha Al Himdani
06c0972551 Add membership and host to user webhook payload
Nest membership ID, role, and state into a membership sub-object
in the user webhook payload. Also emit user:updated webhook when
the membership role is changed. Add X-Probo-Webhook-Host header
to webhook HTTP calls. Skip delete webhook when membership is
not found in SCIM user deletion.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-13 17:14:01 +02:00
Sacha Al Himdani
0826f28867 Fix missing fields in MCP type serializers
Framework was missing OrganizationID, Task was missing MeasureID and
AssignedToID, Asset was missing SnapshotID, AuditLogEntry was missing
Metadata, and Obligation was missing SourceID. All these fields were
defined in the MCP generated types but never set by their converters.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-13 14:40:47 +02:00
Sacha Al Himdani
bfed192421 Upgrade axios to 1.15.0 via npm override
Fixes GitHub security alerts #82, #83, #84:
- Unrestricted Cloud Metadata Exfiltration via Header Injection Chain
- NO_PROXY Hostname Normalization Bypass leading to SSRF
- Prototype Pollution in langsmith-sdk

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-13 14:24:51 +02:00
Sacha Al Himdani
fbb4c29d38 Add document CLI commands
Add list, create, view, update, delete, archive, and unarchive
subcommands under `prb document`.

Add document version subcommands: list-versions, view-version,
create-draft, delete-draft, update-version, publish-major, and
publish-minor.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-13 14:22:50 +02:00
Émile Ré
d2937c53d1 Create initial draft version on banner creation
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 15:46:29 +04:00
Émile Ré
61cd3244df Denormalize organization_id onto cookie entities
Add organization_id to cookie_banner_versions, cookie_categories,
and cookie_consent_records so AuthorizationAttributes can return
it directly without JOINing back to cookie_banners. Document the
pattern in contrib/claude/coredata.md.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:52:21 +04:00
Émile Ré
8ba3034828 Add version detection and draft provisioning on publish
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:52:21 +04:00
Émile Ré
88315f51e1 Add cookie banner versioning with JSONB snapshots
Introduce append-only cookie_banner_versions table with a JSONB
snapshot of consent-relevant configuration (privacy policy URL,
consent mode, expiry, categories and their cookies). Each version
has its own state (DRAFT/PUBLISHED) separate from the banner
lifecycle.

Replace the banner state enum (DRAFT/PUBLISHED/DISABLED) with a
simpler ACTIVE/INACTIVE toggle. Link consent records to the
specific published version the visitor accepted.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:52:20 +04:00
Émile Ré
a153427a08 Rename client to service
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:43 +04:00
Émile Ré
c594b10e9f Add consent record operations and rename ConsentRecord to CookieConsentRecord
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:43 +04:00
Émile Ré
327652163f Fix client method names
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:42 +04:00
Émile Ré
15c90b2b72 Fix validation and data access layer
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:42 +04:00
Émile Ré
2cb58d0e32 Fix lint
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:42 +04:00
Émile Ré
992ab642ea Add cookiebanner client
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:42 +04:00
Émile Ré
62c29810a5 Add CookieBannerFilter
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:42 +04:00
Émile Ré
84628683f2 Add migration
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:41 +04:00
Émile Ré
e9330171fe Add new models
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-13 14:50:41 +04:00
Bryan Frimin
43336078f4 Migrate workers to kit/worker
Replace hand-rolled polling loops, semaphores, and WaitGroups
in all 7 background workers with go.gearno.de/kit/worker. Each
worker now implements Handler[T] (Claim/Process) and optionally
StaleRecoverer, gaining automatic Prometheus metrics and
OpenTelemetry tracing. Bumps kit from v0.3.0 to v0.5.0.

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-13 12:25:42 +02:00
Sacha Al Himdani
3ca0fac939 Release v0.165.3
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-10 20:50:06 +02:00
Sacha Al Himdani
f05f0f9572 Fix missing owner ID in MCP datum responses
The NewDatum type conversion helper was not mapping the OwnerID field
from the coredata struct, causing MCP responses for data resources to
return a zero-value owner_id.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-10 20:47:11 +02:00
Sacha Al Himdani
b84fb1fb4a Remove VERSION order field from MCP document versions
CREATED_AT is sufficient for ordering document versions.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-10 20:15:00 +02:00
Sacha Al Himdani
77d493d5ed Release v0.165.2
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-10 19:40:16 +02:00
Sacha Al Himdani
ff8da296e6 Fix MCP snapshot issues for SOA and vendors
- Fix SnapshotsType enum: STATES_OF_APPLICABILITY → STATEMENTS_OF_APPLICABILITY
- Add snapshot filter to ListStatementsOfApplicability MCP tool
- Add missing organization_id to vendor contacts and compliance reports snapshot inserts

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-10 19:20:00 +02:00
Sacha Al Himdani
eb6c06e683 Move document search_vector from documents to document_versions
Now that title lives on document_versions, the full-text search vector
belongs there too. Drop the generated column and GIN index from
documents, recreate them on document_versions, and update the document
filter to query the latest version's search_vector.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 20:01:32 +02:00
Sacha Al Himdani
221afd8b8d Drop dead description column from documents
The description field on Document and EmployeeDocument was never
populated. Remove it from the database, GraphQL schema, and Go types.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 20:01:32 +02:00
Sacha Al Himdani
b63f043849 Move document title ownership from document to version
Title is now owned by document_versions, following the same pattern as
classification and document_type. The documents.title column is made
nullable with a TODO to drop it. Backend loads title from a
latest_versions CTE for ordering purposes only. The frontend resolves
title from the latest version, and DocumentTitleForm now operates on
DocumentVersion using UpdateDocumentVersion mutation.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 20:01:32 +02:00
Sacha Al Himdani
ba386d188b Release v0.165.1
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 19:41:08 +02:00
Sacha Al Himdani
d519361786 Allow authenticated users to query signUpEnabled
The signUpEnabled field used @session(required: NONE) which rejects
authenticated users. Change it to OPTIONAL so the query works regardless
of authentication state, fixing a crash on the sign-up page for
already-logged-in users.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 19:27:10 +02:00
Sacha Al Himdani
ead1d862cd Release v0.165.0
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 18:45:56 +02:00
Sacha Al Himdani
76f6c8f9d1 Show registration unavailable page when signup is disabled
Instead of showing the signup form and returning an internal error on
submit, the SignUpPage now queries signUpEnabled upfront and displays a
friendly message explaining that registration is not available, with a
link back to login.

Adds a signUpEnabled GraphQL query field on the connect/v1 API and
handles ErrSignupDisabled as a FORBIDDEN error in the SignUp resolver.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 18:28:59 +02:00
Sacha Al Himdani
ab5f42ad74 Redesign document approval flow
Replace the per-approver add/remove model with a quorum-based approval
system. Documents now have default approvers that are pre-populated when
requesting approval, and the publish dialog lets users adjust the list
before submitting.

Key changes:

- Add PENDING_APPROVAL document version status with dedicated transitions
- Introduce approval quorums with request/approve/reject/void lifecycle
- Add default approvers per document (stored in document_default_approvers)
  with MERGE-based upsert for efficient sync
- Add NoDuplicates validator for slice fields
- Split ALTER TYPE ADD VALUE migrations into separate files (required by
  PostgreSQL when run inside transactions)
- Use VOIDED consistently for both quorum status and decision state enums
- Expose void/approve/reject through GraphQL and MCP, with e2e tests
- Add approval management UI: publish dialog with approver selection,
  approval list with void support, and external approve/reject page

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 18:18:30 +02:00
Sacha Al Himdani
17f579b8a2 Release v0.164.0
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 13:22:07 +02:00
Sacha Al Himdani
5fd580e995 Rename State of Applicability to Statement of Applicability
Rename the entity across the full stack: database table
(states_of_applicability → statements_of_applicability), Go model,
GraphQL types, MCP specification, CLI commands, frontend components,
routes, and display labels. Includes a migration to rename the table
and its foreign key column.

Widen sidebar from 260px to 280px to fit the longer label.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-09 13:06:06 +02:00
Émile Ré
050073ab3c Fix TextLength to count characters instead of bytes
Use utf8.RuneCountInString so multi-byte characters like é count as one
character. Add a unicode test case to cover this.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-09 14:47:48 +04:00
Émile Ré
7cd4606278 Validate document content length by extracted text, not JSON size
Add Node.TextLength() to walk the ProseMirror tree and sum actual user
text. Introduce ProseMirrorDocumentMaxTextLength validator that enforces
a 50k character limit on extracted text, paired with a 500k byte safety
cap on the raw JSON string. Extend e2e tests for content length.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-09 14:47:48 +04:00
Bryan Frimin
303455ded6 Move framework_id into filter in ListControlsInput spec
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-09 12:41:08 +02:00
Bryan Frimin
b005b92c77 Fix famework_id filer not working
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
2026-04-09 12:37:26 +02:00
dependabot[bot]
dee3f02c41 Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) from 1.42.0 to 1.43.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.42.0...v1.43.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
  dependency-version: 1.43.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-09 08:30:27 +00:00
dependabot[bot]
9d5dd680ef Bump go.opentelemetry.io/otel/sdk from 1.42.0 to 1.43.0
Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.42.0 to 1.43.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.42.0...v1.43.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-version: 1.43.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-08 20:17:37 +00:00
Sacha Al Himdani
7cd8cd6455 Release v0.163.2
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-08 16:53:49 +02:00
Sacha Al Himdani
643cf4661a Fix MCP updateRisk not forwarding note field
The MCP UpdateRiskTool resolver was not passing the Note field
to the UpdateRiskRequest, causing note updates via MCP to be
silently ignored. The GraphQL resolver already forwarded it
correctly.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-08 16:43:35 +02:00
Aurélien Sibiril
22ccfaa30f Replace Organization.googleWorkspaceOAuth2Scopes with SCIMBridgeTypeInfo
A Google-Workspace-specific field on the generic Organization type
was future-hostile: each new SCIM bridge type would need its own
top-level field. Replace with a generic SCIMBridgeTypeInfo type
queried through Organization.scimBridgeTypes, parallel to the
ConnectorProviderInfo pattern in console/v1.

ConnectorList looks up the Google Workspace entry from the list
and passes its scopes to GoogleWorkspaceConnector as before.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
ec42409219 Expose oauth2Scopes on Connector instead of AccessSource
The AccessSource.oauth2Scopes field duplicated knowledge that
naturally belongs on the Connector object that AccessSource
already exposes via its connector field. Move it to Connector so
every type that holds a connector (AccessSource, SCIMBridge, etc.)
can reach the scopes through the connector relationship.

AccessSourceRow now queries accessSource.connector { oauth2Scopes }
in its reconnect flow.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
53d6ab09cb Fully expand r.Get call for connectors/complete handler
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
266e6cc788 Fix import order for accessSourceMutations imports
eslint import-x/order sorts case-insensitively, so the lowercase
accessSourceMutations imports must precede the AddAccessSourceDialog
imports in both files.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
614b4a2384 Read OAuth2 scopes from GraphQL on the connector frontend
Each component that initiates an OAuth2 flow now reads its scopes
from the colocated Relay fragment instead of a hardcoded TypeScript
map. The five live call sites pass scopes to the backend via the
new ?scope= query parameter.

Drop the dead CreateAccessSourceDialog React component and rename
the file to accessSourceMutations.ts since only the mutation export
was used.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
247cae14fa Expose OAuth2 scopes via GraphQL fields
Add per-context fields so the frontend can read scopes from the
type that owns each connection:

- ConnectorProviderInfo.oauth2Scopes: access review providers
- AccessSource.oauth2Scopes: access review reconnect flow
- Organization.slackOAuth2Scopes (console): compliance page Slack
- Organization.googleWorkspaceOAuth2Scopes (connect): SCIM bridge

Resolvers delegate to the constants declared in each owning Go
module. The Google Workspace field lives on Organization, not on
SCIMConfiguration, so the Connect button can read it before any
SCIM configuration exists.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
56c042b7ed Add OAuth2 scope sources for access review, slack, googleworkspace
Each module that initiates an OAuth2 flow now declares its scopes
in its own package instead of duplicating them in the frontend or
in shared connector config:

- pkg/accessreview/drivers: per-provider scopes for the access
  review drivers
- pkg/slack: scopes for the compliance page integration
- pkg/iam/scim/bridge/provider/googleworkspace: scopes for the
  SCIM provisioning bridge

These constants are surfaced to the frontend via GraphQL fields
so the frontend never hardcodes scope strings.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00
Aurélien Sibiril
e006f335b2 Pass OAuth2 scopes to connector at initiate time
Add an InitiateOptions struct to the Connector interface so each
caller can declare the scopes it needs instead of having them baked
into the connector at registration. The HTTP handler reads repeated
?scope= query parameters from /connectors/initiate and forwards them.

Also restore GOOGLE_WORKSPACE and LINEAR provider definitions which
were silently dropped from the bootstrap config refactor.

Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
2026-04-08 11:05:12 +02:00