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>
Uses the Loader + Page + Fragment pattern so the snippet page fetches
its own data instead of relying on Outlet context.
Signed-off-by: Émile Ré <emile@getprobo.com>
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>
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>
ConnectionHandler.getConnection could not find the cookies
connection because orderBy was implicitly treated as a filter.
Add filters: [] to the @connection directive and document the
filters rule in contrib/claude/relay.md.
Signed-off-by: Émile Ré <emile@getprobo.com>
The create, delete, and move cookie mutations were not updating
the Relay store connections, so the UI only reflected changes
after a page reload. Add @connection and @appendEdge/@deleteEdge
directives, and a store updater for the move mutation.
Also document mutation store update rules in contrib/claude/relay.md.
Signed-off-by: Émile Ré <emile@getprobo.com>
langsmith <=0.5.18 leaks streamed LLM output past redaction controls
(GHSA-rr7j-v2q5-chgv). The transitive pin via @n8n/ai-utilities held
@langchain/classic at 1.0.5 which required langsmith ^0.3.64, blocking
the upgrade. Add npm overrides for @langchain/classic (^1.0.27) and
langsmith (^0.5.19) to resolve all three langsmith advisories.
The lockfile refresh bumps eslint-plugin-react-hooks from 7.0.1 to
7.1.0 which enables the react-hooks/refs and set-state-in-effect
rules. Fix the resulting lint errors:
- PDFPreview (console + trust): read currentPage through a ref synced
via useEffect, keeping the setState updater pure and ref access
outside of render
- MeasuresPage: remove redundant categoryFilter state that mirrored
urlCategory, use a ref to detect URL changes and trigger refetch
as the single source of category refetches
- WebhooksSettingsPage: defer loadEvents via requestAnimationFrame
to avoid synchronous setState within the effect body
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
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>
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>
Moving a cookie between categories previously required two sequential
updateCookieCategory mutations, which was not atomic and could leave
data in an inconsistent state if the second call failed. This adds a
dedicated moveCookieToCategory mutation that performs both updates in
a single transaction.
Signed-off-by: Émile Ré <emile@getprobo.com>
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>
Move the PageHeader into CookieBannersOverviewPage directly since
the layout had only one child route left after extracting the "new"
route as a sibling, making the wrapper unnecessary.
Signed-off-by: Émile Ré <emile@getprobo.com>
Category reordering previously required two separate
updateCookieCategory calls to swap ranks, which was not
atomic. Replace with a single reorderCookieCategory mutation
that shifts all affected ranks in one SQL statement, and
remove the rank field from UpdateCookieCategoryInput.
Signed-off-by: Émile Ré <emile@getprobo.com>
Replace generic names (commitMutation, commitCreate, isInFlight, etc.)
with names derived from the graphql tagged-template variable minus the
Mutation suffix. Add naming convention rule to contrib/claude/relay.md.
Signed-off-by: Émile Ré <emile@getprobo.com>
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>
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>
Implement a full OAuth2 2.0 and OpenID Connect 1.0 authorization
server with support for authorization code flow (with PKCE),
refresh token rotation, device authorization grant, dynamic
client registration, token introspection, and token revocation.
Includes database schema, coredata layer, service logic, HTTP
handlers, OIDC discovery endpoint, and JWKS publishing.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
The custom updater on the SCIM disconnect mutation ran on every
response and nulled organization.scimConfiguration in the Relay store
-- including on error responses, which flipped the UI to the
"disconnected" state even when the backend had actually rejected the
delete.
Replace the updater with a @deleteRecord directive on the returned
deletedScimConfigurationId, matching the pattern already used in
SCIMConfiguration.tsx. @deleteRecord is a no-op when the returned id
is null, so error responses no longer produce a false-positive UI
update.
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
Statements of Applicability are no longer exported as one-off PDFs.
Instead, each SOA owns a persistent document that accumulates versions
over time, following the same publish/approve lifecycle as authored
documents.
Publishing without approvers publishes immediately; publishing with
approvers creates a draft pending approval via the existing quorum
system. SOAs can also store default approvers that are pre-populated in
the publish dialog.
The SOA is removed from the snapshot system — applicability statements
are now queried directly (snapshot_id IS NULL) rather than through
snapshot copies.
A standalone migration script (cmd/migrate-soa-snapshots-to-documents)
converts existing SOA snapshots into documents with proper ProseMirror
content, preserving version history and approval decisions.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Add server-side validation in BulkRequestSignatures, RequestSignature,
and RequestApproval to load the referenced profiles and verify none
have an ended contract before proceeding. Returns ErrProfileContractEnded
if a profile's contract_end_date is in the past, surfaced as a CONFLICT
GraphQL error in all three resolvers.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Move the paginated people query from PeopleGraph.ts into
SignatureDocumentsDialog.tsx following colocated query conventions
and pass excludeContractEnded: true to hide people whose contract has ended.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
- Remove the right-side drawer and display document properties in a
3-column Card below the page header
- Move status badge to the PageHeader (right-aligned, matching
compliance page style)
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Add inherentRiskScore and residualRiskScore to the mutation fragment so
the Relay store gets updated scores. On the backend, use RETURNING to
get the recomputed values from the database generated columns.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
The controls tab used useRefetchableFragment which only showed the
first 20 controls with no "Show more" button, while the tab badge
displayed the actual total count. Switch to usePaginationFragment
to enable proper pagination via the SortableTable component.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Replace the three separate draft mutations (createDraftDocumentVersion,
updateDocumentVersion, deleteDraftDocumentVersion) with automatic draft
lifecycle management inside updateDocument. The backend now auto-creates
a draft when a published document is edited, updates the existing draft
on subsequent edits, and auto-deletes the draft when content reverts to
match the published version.
A new deleteDocumentDraft mutation provides explicit draft deletion.
Backend:
- Merge version-level fields (content, title, classification,
documentType) into UpdateDocumentRequest
- Convert CreateDraft, UpdateVersion, DeleteDraft into private
transaction helpers called from Update
- Update returns (*Document, *DocumentVersion, error) with the version
present only when a draft exists
Frontend:
- Remove all create/update/delete draft mutations from components
- Auto-save via updateDocument with layout refetch on draft status
transitions while preserving editor cursor (data-generation key)
- Title, type, and classification editable on published versions
(backend auto-creates draft)
- Forms use react-hook-form values option to stay synced with Relay
fragment data across draft/publish transitions
API surface (GraphQL, MCP, CLI, n8n) updated consistently:
- Removed: createDraftDocumentVersion, updateDocumentVersion,
deleteDraftDocumentVersion
- Added: deleteDocumentDraft (document-level)
- Updated: updateDocument accepts content, classification, documentType
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>