Display a legal notice requiring the operator to certify they have
obtained verifiable prior consent (GDPR, CAN-SPAM) before bypassing
the confirmation email flow.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
When creating a new subscriber, operators can now check "Skip confirmation email" if they already have the recipient's consent. This creates the subscriber in confirmed status and skips sending the notification email.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Increase MaxCursorSize from 100 to 500 to allow larger page sizes, and set the measures list frontend query to fetch 500 items per page by default.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Remove !queryRef guard and add proper dependency arrays so queries
refetch when organizationId or meetingId changes.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Replace loaderFromQueryLoader/loadQuery in route definitions with
useQueryLoader inside dedicated Loader components, matching the
compliance-page pattern. Use index routes instead of redirect hacks.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Add structured organization context with 5 markdown sections (Product, Architecture, Team, Processes, Customers) editable inline. Meetings are now a tab within the context page. Moved all GraphQL queries from hooks/graph/MeetingGraph.ts into colocated components following new best practices. Updated database schema, backend services, GraphQL resolvers, and MCP API to support the new context fields and structure.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
- Fix import order: react-relay before react-router
- Add parentheses around arrow function parameter
- Sync category filter with URL param changes, not just on mount
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
When clicking a category name in the measure detail breadcrumb, users should be taken back to the measures list with that category filtered. Previously, the breadcrumb linked to a route that wasn't read by the measures page.
Changed the breadcrumb to use a ?category search param instead of a route segment, and updated the measures page to initialize and sync its category filter from the URL. Removed the now-unused category/:categoryId route.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Documents can be archived and unarchived. Archived documents are
read-only, excluded from the trust center, and moved to a dedicated
Archived tab in the document list.
- Add archived_at timestamp and status (ACTIVE/ARCHIVED) PG enum column
- Rename DocumentStatus → DocumentVersionStatus, introduce DocumentStatus
- Archive/unarchive mutations in GraphQL, MCP, and CLI
- Bulk archive/unarchive mutations with Active/Archived tabs in the list
- ABAC policies: write actions denied on archived docs, unarchive denied
on active docs
- Remove control/risk mappings and reset trust center visibility on archive
- Exclude archived documents from mapping dialogs and trust center tab
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Addresses PR review comments: clears selected document IDs when changing
the type filter to prevent bulk actions on hidden rows, updates the Relay
connection ID when the filter changes so mutations target the correct
connection, and fixes eslint indentation violations.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Adds 5 new document types (PLAN, REGISTER, RECORD, REPORT, TEMPLATE), renames ISMS to GOVERNANCE, and implements type-based filtering across GraphQL, MCP, and frontend. Includes migration, enum updates, filter implementation with SQL array support, and frontend dropdown UI with Relay refetch pattern.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Support distinguishing between minor and major non-conformities in findings. Rename the existing NONCONFORMITY enum value to MINOR_NONCONFORMITY and add a new MAJOR_NONCONFORMITY value across all API layers (GraphQL, MCP, CLI) and the database.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Replace the client-side grouped-by-category view (fetching 500 items)
with a flat table using server-side filtering and cursor-based
pagination. Colocate GraphQL queries, fragments, and mutations in the
component file per console CLAUDE.md conventions.
Backend changes add a category filter to the measure list endpoints
(GraphQL, MCP) and a new measureCategories field on Organization.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Remove createPortal and main element ref/state in favor of a simple
fixed overlay with top-12 offset. This avoids React 19 strict mode
violations around ref access during render and setState in effects.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Replace mainRef with useState to avoid accessing ref.current during
render, which is forbidden by React 19's strict ref rules.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Add cleanup function to the useEffect that sets position: relative on
the main element, so the style is restored when the component unmounts.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Clamp the counter with Math.max(0, ...) and use <= 0 check to prevent
the drag overlay from getting stuck when dragLeave fires more than
dragEnter.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Offset the fixed overlay with top-12 so the navigation bar remains
visible and unobstructed during file drag.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
The previous approach attached drag handlers to a content div that
didn't fill the viewport, making the dropzone hard to target. Now
drag detection uses window-level events with a counter for correct
nested element handling, and the full-screen overlay itself becomes
the react-dropzone drop target.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
- Move DialogFooter before type DialogRef to satisfy import-x/order
- Check errors argument in onCompleted callback to avoid treating
GraphQL errors as successful uploads
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
- Fix import order for DialogRef type
- Add explicit type parameter to useMutation
- Remove unnecessary parens around single arrow function arg
- Fix jsx-one-expression-per-line for MB text
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Move uploadAuditReportMutation into CreateAuditDialog and replace
promisifyMutation with a Promise wrapper using native Relay callbacks.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Enable users to drag-and-drop PDF reports onto the audit list page, which automatically opens the create-audit dialog with the file attached. The dialog chains createAudit → uploadAuditReport mutations, with graceful handling for partial failures (audit created but upload failed).
Changes:
- AuditsPage: Add dropzone with visual overlay (dashed border + icon) when dragging PDFs
- CreateAuditDialog: Accept optional file prop, show file info, chain mutations on submit
- Extract audit ID from createAudit response to pass to uploadAuditReport
- Handle upload failure with warning toast, allowing manual upload from audit detail page
- Add react-dropzone dependency to console app
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Add FindingsPage, FindingDetailsPage, and CreateFindingDialog
supporting all finding kinds (nonconformity, observation, exception)
with filtering, sorting, and audit linking.
Remove the separate nonconformity and continual improvement pages,
routes, and graph hooks. Update sidebar navigation, routes, and
components for nullable audit framework field.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Introduce `implemented` enum (IMPLEMENTED/NOT_IMPLEMENTED) and
`not_implemented_justification` (nullable text) fields on the Control
entity across all API surfaces (GraphQL, MCP, CLI), database, frontend,
and SOA export.
The database stores implementation state as a PostgreSQL enum
`control_implementation_state`. Controls default to IMPLEMENTED during
migration. The SOA list and PDF export show implementation status
alongside applicability, with "-" for non-applicable controls.
Justification columns are renamed for clarity: "Justification for
non-applicability" and "Justification for non-implementation".
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
Run make generate in CI lint and test jobs since generated files are
now gitignored. Also include Relay codegen for frontend apps in the
generate target.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Adding TypeScript generics to useMutation, usePaginationFragment,
and useRefetchableFragment in graph hooks and page files causes
cascade type mismatches: string values are not assignable to
generated enum types, and typed refetch functions are incompatible
with SortableTable's generic refetch prop.
Use eslint-disable-next-line relay/generated-typescript-types
instead until the calling code is updated to use enum types.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Fix max-len violations by breaking long lines across multiple
lines. Fix react-hooks/exhaustive-deps by adding missing deps
and removing unnecessary ones. Remove stale eslint-disable
comments in DataTable stories.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Remove unused GraphQL fields (createdAt, updatedAt, totalCount,
__id, sourceId, etc.) from queries and fragments across 50+ files.
Add TypeScript generics to useMutation, usePaginationFragment,
useRefetchableFragment, and useLazyLoadQuery calls to satisfy
relay/generated-typescript-types.
Add justified eslint-disable comments for fields needed by Relay
cache normalization (id) or consumed by sibling components through
fragment spreads.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Centralized graph files (hooks/graph/*.ts) define GraphQL
queries consumed by multiple page components. This architecture
intentionally separates field definitions from usage, triggering
relay/unused-fields and relay/must-colocate-fragment-spreads.
File-level eslint-disable comments suppress these false positives.
Also adds explicit TypeScript generics to useMutation and
usePaginationFragment calls to satisfy relay/generated-typescript-types
without eslint-disable.
Signed-off-by: Bryan Frimin <bryan@getprobo.com>
- Fix redirection after document deletion in detail page
- Fix refetch after publication
- Return proper error when trying to update a published document
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>