Commit Graph

468 Commits

Author SHA1 Message Date
Émile Ré
c364c3eacb Update packages/cookie-banner/src/client.ts
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Signed-off-by: Émile Ré <nemile.re@gmail.com>
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 13:11:22 +04:00
Émile Ré
f29a2f05cc Fix gpc applied from cookie / api consent
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 13:05:02 +04:00
Émile Ré
4f4bb72760 Clear GPC badge when user overrides consent via preference panel
When the user explicitly changes consent (accept all, reject all, or
customize), clear the gpcApplied flag and remove the gpc-label attribute
from the settings button so the "Opt-Out Preference Signal Honored"
badge no longer displays.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:44:44 +04:00
Émile Ré
98dc04b7de Add Global Privacy Control (GPC) support to cookie banner SDK
When navigator.globalPrivacyControl is true and no prior consent exists,
auto-reject all non-necessary cookies with action "GPC", skip showing
the banner, and display an "Opt-Out Preference Signal Honored" badge on
the settings button (CPRA compliance). GPC labels are hardcoded in the
SDK for en/fr/de/es. Users can still override via the preference panel.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:21:40 +04:00
Émile Ré
2b6f131f43 Fix PR review comments on cookie banner i18n
Address locale normalization for region-tagged values, guard
language detection for non-DOM runtimes, validate DefaultLanguage
on update, pass translated texts through the deactivation flow,
handle slug collisions in migration, add organizations FK, fix
consent migration from name-keyed to slug-keyed data, render all
template placeholders in previews, and wrap helper text for i18n.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:12 +04:00
Émile Ré
fa7a9c96c1 Move cookie detail labels from backend to JS SDK
label_description and label_duration are not user-customizable, so they
don't belong in the backend translation defaults. Hardcode them in the
cookie-banner SDK's i18n module instead.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:12 +04:00
Émile Ré
e24813202b Fix XSS in cookie banner translation rendering
Validate translation string values server-side with NoHTML() and
MaxLen(2000) to reject HTML in the translations JSON blob. On the
client side, escape user-provided template text before innerHTML
injection in banner_description and placeholder_text paths.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:11 +04:00
Émile Ré
165b9ad9d3 Add slug to cookie categories for stable consent identifiers
The category slug provides a stable, URL-safe key used as the
data-cookie-consent attribute value and consent data key, replacing
the fragile category name. This prevents breakage when categories
are renamed.

- Add slug column with unique-per-banner constraint and backfill migration
- Add Slug validator (lowercase alphanumeric + hyphens)
- Propagate slug through GraphQL schema, service layer, and snapshot
- Update console UI with slug field in create/edit forms
- Switch cookie-banner widget to use slug as consent data keys

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:10 +04:00
Émile Ré
bb39daebc5 Move duration translations from server defaults to JS SDK
Duration strings are static and not customizable through the console,
so they belong in the frontend cookie-banner package instead.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:10 +04:00
Émile Ré
f9458fb18a Remove unused available_languages from cookie banner config
The field was populated by the backend and declared in the TS interface
but never consumed by any client-side code. The banner resolves its
language via detectLanguage() and passes it as a query param.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:09 +04:00
Émile Ré
ef60f080f1 Add i18n support to cookie banner JS client
Replace all hardcoded user-facing strings with server-driven
texts from config.texts. Add language detection chain
(data-lang > html lang > navigator.language), pass ?lang
query param on config fetch, and use {{variable}} interpolation
for dynamic content in templates.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:09 +04:00
Émile Ré
4678c58ab0 Add description to cookie banner preference panel
Adds a short description under the preference panel title:
"Choose which cookie categories to allow. Necessary cookies are
always active as they are needed for the site to work."

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-24 12:18:08 +04:00
Émile Ré
d5d77fee8a Stop existing detector before creating a new one in startDetector()
Prevents orphaned detector state when load() is called multiple times.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-23 10:50:57 +04:00
Émile Ré
137b63a47e Add cookie detector to JS SDK for automatic cookie discovery
Overrides document.cookie setter to intercept cookie writes and detect
unknown cookies not present in the banner config. Also scans pre-existing
cookies on startup. Detected cookies are debounced and reported in batches
to the detected-cookies endpoint with inferred durations from max-age/expires.

Extracts shared cookie helpers (parseCookieName, parseDuration, isDeletion,
removeCookies) into cookie-utils.ts, used by both activation.ts and
detector.ts. Unifies the duplicated "probo_consent" constant into a single
export from cookie.ts.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-23 10:50:57 +04:00
Sacha Al Himdani
7be92defcc Add missing resources to CLI, MCP, and n8n surfaces
Audit all three API surfaces against the console GraphQL schema and add
missing resources: asset, audit, datum, dpia, evidence upload, measure,
obligation, processing activity, rights request, snapshot, task, tia,
trust center (with references/files), and vendor management CLI
commands; MCP tools for deletes, rights requests, trust center, vendor
contacts/services, and compliance external URLs; n8n nodes for
obligation, finding, task, evidence, processing activity, dpia, tia,
rights request, snapshot, audit log, access review, organization
context, trust center, and additional control/measure/vendor operations.

Include MCP e2e test infrastructure (testutil MCP client with API key
auth and JSON-RPC session management) and tests covering all new MCP
tools.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-22 19:02:22 +02:00
Émile Ré
72443ff32f Use full Probo logo (picto + wordmark) in cookie banner branding
Replace the picto-only SVG with the full Logo component in both the
console theme preview and the cookie-banner web component.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 15:49:56 +04:00
Émile Ré
d71915abd4 Fix PR review comments on cookie banner branding
- Add scope parameter to UpdateShowBranding to prevent cross-tenant updates
- Use cmd.Context() instead of context.Background() in proboctl CLI
- Drop SQL column default after backfill in migration
- Add bounds check for int-to-int32 conversion in PG_POOL_SIZE
- Update branding link to getprobo.com homepage

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 15:22:03 +04:00
Émile Ré
df698b5b21 Change branding copy from "Powered by" to "Privacy by"
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 15:22:02 +04:00
Émile Ré
7102c17b19 Add "Powered by Probo" branding to cookie banner SDK
Renders a subtle branded link at the bottom of both the banner
and preference panel, conditionally hidden via show_branding
config flag. Extracts all icon and HTML template constants into
a shared html.ts module.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 15:22:02 +04:00
Émile Ré
9510d91c61 Align theme preview with real themed banner styles
Fix button layout in ThemePreview to match the actual themed-banner:
wrap buttons in spans to mimic custom element wrappers (preventing
flex: 1 from stretching them), use correct padding/background/max-width,
and set explicit line-height: normal. Also clean up dead flex properties
in themed-banner styles.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:51 +04:00
Émile Ré
ae68196d76 Shrink cookie-banner README and link to docs site
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:51 +04:00
Émile Ré
4a88cc5902 Rework cookie-banner exports: themed banner as default, headless as subpath
Make the themed banner the default "." export and move the headless
components to "./headless". Remove unused VERSION export.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:50 +04:00
Émile Ré
0cb48a4f33 Add accept/reject all buttons to preference panel
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:50 +04:00
Émile Ré
c942aaa7bb Make consent API calls fire-and-forget to avoid blocking UI
The server-side consent record is for audit purposes and does not need
to complete before the UI responds. Local state (cookie, script
activation) is applied synchronously, and the API call runs in the
background with queue fallback on failure.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:50 +04:00
Émile Ré
140e614e4f Fix placeholder style copying and root domain calculation
Only copy dimensional style properties (width, height, margin, etc.)
to placeholders instead of blindly copying all cssText, which could
override layout properties like display: flex.

Handle multi-part TLDs (e.g. .co.uk, .com.au) when computing the root
domain for cookie deletion.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:50 +04:00
Émile Ré
2b59a10c14 Add ARIA attributes and focus management to cookie banner
Improve accessibility across the cookie banner components: add
aria-modal/aria-labelledby/aria-describedby on dialog cards, aria-label
on icon-only buttons and category toggles, aria-expanded on cookie
detail disclosure, aria-hidden on decorative SVGs, and auto-focus into
dialogs when they become visible.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:50 +04:00
Émile Ré
9a92ebd51a Add placeholder overlays for blocked cookie-consent elements
When visual elements (iframe, img, video, etc.) are blocked due to
missing cookie consent, display a styled placeholder that explains
which cookie category must be accepted and offers a link to open
the preference panel.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:50 +04:00
Émile Ré
1fb0464948 Add element deactivation with cookie removal on consent withdrawal
When a user changes their consent preferences, elements for rejected
categories are now deactivated: data attributes are restored, resources
are unloaded, and associated cookies are removed.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:49 +04:00
Émile Ré
0e3c79b0e8 Forward data-reopen-widget from script tag in IIFE entry point
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:49 +04:00
Émile Ré
68fffbf2f3 Add reopen-widget attribute and probo-settings-link element
Allow customers to replace the built-in floating settings button with
their own re-open trigger (e.g. a footer link) by either placing a
<probo-settings-link> element anywhere on the page or manually setting
reopen-widget="custom" on the root. The settings-link auto-hides the
floating button on connect via a reopen-widget attribute change event.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:49 +04:00
Émile Ré
6391d276d9 Clean up settings button CSS custom properties
Remove undocumented --probo-settings-bottom variable and use the
shared --probo-z-index variable instead of --probo-settings-z-index.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:48 +04:00
Émile Ré
55d81e21eb Fix preference panel close returning to banner when consent exists
When a visitor with existing consent opened the preference panel via
the floating settings button and closed it, the state was always set
to "banner" instead of "hidden". Now check hasConsent so closing the
panel returns to the floating button when preferences are already saved.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:48 +04:00
Émile Ré
9ec6922fde Hide empty categories in cookie banner preference panel
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:48 +04:00
Émile Ré
fab95413df Improve UI of themed banner
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-22 11:34:48 +04:00
Sacha Al Himdani
b603d04d8d Assets as document: replace snapshot with publish workflow
Remove assets from the snapshot system and replace with a publish-based
document workflow that generates versioned ProseMirror documents.

- Remove snapshot_id/source_id from asset and asset_vendor models
- Delete AssetFilter (no longer needed without snapshot filtering)
- Add PublishAssetList service, GraphQL mutation, MCP tool, CLI command,
  and n8n operation
- Add asset_list_document_id column to generated_documents table
- Generate ProseMirror documents with asset inventory tables
  (name, type, amount, data types stored, owner, vendors)
- Add AssetListDocument resolver on Organization type
- Update frontend to remove snapshot routes/params and add publish dialog
- Add e2e tests for asset publish (immediate, with approvers, reuse, RBAC)
- Add migration script for converting legacy asset snapshots to documents
- Exclude ASSETS from snapshot type lists and e2e snapshot tests
- Move generated_documents SQL to coredata methods on Datum and Asset
- Clear generated document and SOA references on soft delete and archive

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-21 19:36:17 +02:00
Sacha Al Himdani
e1148f812e Replace implemented column with CMMI maturity level
Drop the boolean implemented/not-implemented state in favor of a
mandatory CMMI maturity level enum (NONE, INITIAL, MANAGED, DEFINED,
QUANTITATIVELY_MANAGED, OPTIMIZING) stored as a Postgres enum type.

The migration backfills existing rows (NOT_IMPLEMENTED → NONE,
IMPLEMENTED → INITIAL), makes the column NOT NULL, and drops the old
implemented column and its enum type.

- maturityLevel is required on CreateControlInput and non-nullable (!)
  in the GraphQL schema
- CLI displays human-readable CMMI labels instead of raw enum tokens
- SOA table and published document use a single Maturity column in
  place of the old Implemented + Maturity columns
- Remove ControlImplementationState type and all implemented references
  across backend, frontend, CLI, MCP, n8n, and E2E tests

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-21 11:06:36 +02:00
Alejandro Juan
da91afc2a7 Add CMMI maturity level to compliance controls
Adds an optional CMMI 0-5 maturity level field to Control to support
ISO 27001 clause 9.1 effectiveness measurement and HITRUST CSF maturity
requirements. The field is nullable, framework-agnostic, and exposed
across all four API surfaces (GraphQL, MCP, CLI, n8n) plus the
generated SoA document.

Signed-off-by: Alejandro Juan <alejandrojuan@alejandrojuan.com>
2026-04-21 11:06:36 +02:00
Émile Ré
1574600c72 Use fragment and add confirm
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-21 11:40:22 +04:00
Émile Ré
7cd8c516b9 Add uncategorised cookie category
Replace the `required` boolean column on cookie_categories with a `kind`
enum (NORMAL, NECESSARY, UNCATEGORISED). The Necessary category remains
undeletable and always-on for consent; the new Uncategorised category is
also undeletable but users can opt out of it.

When a category is deleted, its cookies are merged into the Uncategorised
category (lazy-created for legacy banners that don't have one yet).

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-21 11:40:21 +04:00
Émile Ré
465f43d359 Refactor UX to remove useless page
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 17:47:06 +04:00
Sacha Al Himdani
6c5c1fa818 Remove meeting feature
Drop meetings and meeting_attendees tables, remove all meeting-related
code across GraphQL, MCP, CLI, N8N, webhooks, frontend, and e2e tests.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-20 15:37:39 +02:00
Sacha Al Himdani
55563226cb Data as document: replace snapshot with publish workflow
Mirror the SOA-to-document migration for the data list. Remove data
from the snapshot system and add a publish workflow that generates a
ProseMirror document for the full organization data inventory.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-20 14:44:00 +02:00
Sacha Al Himdani
5b8918bd5a Add approval quorum and decision read tools
Expose document version approval quorums and decisions
through MCP, CLI, and n8n. This lets users inspect who
approved or rejected a document version, including the
rejection comment, without relying solely on the audit
log.

MCP tools: listDocumentVersionApprovalQuorums,
getDocumentVersionApprovalQuorum,
listDocumentVersionApprovalDecisions,
getDocumentVersionApprovalDecision.

CLI commands: document list-approval-quorums,
view-approval-quorum, list-approval-decisions,
view-approval-decision.

n8n operations: Get/Get Many Approval Quorums and
Approval Decisions on the Document resource.

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-04-20 10:45:17 +02:00
Émile Ré
80a4d44e6d Add CSS custom properties for font size and button radius
Expose --probo-font-size and --probo-btn-radius so customers
can scale typography and button shape without overriding
internals. The type scale now uses calc() offsets from the
base variable. The settings button defaults now follow
--probo-accent so a single accent change updates both the
banner and the floating button.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:36 +04:00
Émile Ré
0ab448691d Fix race between initClient and disconnectedCallback
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:36 +04:00
Émile Ré
bc766ae5c9 Fix event listener and observer leaks in cookie banner
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:35 +04:00
Émile Ré
11a63b5dec Add readme
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:35 +04:00
Émile Ré
4da05b1368 Stop exposing internals
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:35 +04:00
Émile Ré
1e306e5076 Rename default banner to themed banner
Rename src/default/ to src/themed-banner/, update class names
(ProboDefaultBanner → ProboThemedBanner), style constant
(DEFAULT_STYLES → THEMED_STYLES), registration function
(registerDefault → registerThemedBanner), and adjust build
entrypoints and package.json exports accordingly.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:35 +04:00
Émile Ré
2e066c82ad Remove shadow DOM from headless components
Headless components are behavioral wrappers meant to be styled
by the consumer with regular CSS. Shadow DOM on each child
created unnecessary style boundaries with no visual content to
protect. Only ProboSettingsButton retains its own shadow root
since it renders encapsulated styled markup.

Also removes the auto-registerComponents() side effect from
the main entrypoint so consumers opt in explicitly.

Signed-off-by: Émile Ré <emile@getprobo.com>
2026-04-20 10:52:35 +04:00