Add data request pages to compliance portal

Let trust-portal data subjects submit and track GDPR/CCPA rights
requests. The new Data Requests page lists the viewer's own requests
and a dialog submits new ones, scoped server-side to the verified
viewer email so former or inactive users can still exercise their
rights. Submission requires magic-link sign-in (reusing the existing
gate) but not the NDA gate.

Extend the shared rights_request enums with RECTIFICATION, OBJECTION
and COMPLAINT types plus a REJECTED state, and keep the console
GraphQL, @probo/helpers and the MCP specification in sync. Expose a
trust GraphQL surface (myRightsRequests query, createRightsRequest
mutation) backed by a trust service and contact-scoped coredata
loaders.

Add the missing v2 UI kit primitives the dialog needs on top of Base
UI: a SegmentedControl radio-cards group, a form Textarea, and a
Field wrapper.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-17 17:57:35 +02:00
parent e7ebab0d58
commit 6623cbc6f2
36 changed files with 1820 additions and 70 deletions

View File

@@ -65,8 +65,8 @@ import {
} from "../../../hooks/graph/RightsRequestGraph";
const updateRequestSchema = z.object({
requestType: z.enum(["ACCESS", "DELETION", "PORTABILITY"]),
requestState: z.enum(["TODO", "IN_PROGRESS", "DONE"]),
requestType: z.enum(["ACCESS", "DELETION", "RECTIFICATION", "PORTABILITY", "OBJECTION", "COMPLAINT"]),
requestState: z.enum(["TODO", "IN_PROGRESS", "DONE", "REJECTED"]),
dataSubject: z.string().optional(),
contact: z.string().optional(),
details: z.string().optional(),

View File

@@ -50,8 +50,8 @@ import { useFormWithSchema } from "#/hooks/useFormWithSchema";
import { useCreateRightsRequest } from "../../../../hooks/graph/RightsRequestGraph";
const schema = z.object({
requestType: z.enum(["ACCESS", "DELETION", "PORTABILITY"]),
requestState: z.enum(["TODO", "IN_PROGRESS", "DONE"]),
requestType: z.enum(["ACCESS", "DELETION", "RECTIFICATION", "PORTABILITY", "OBJECTION", "COMPLAINT"]),
requestState: z.enum(["TODO", "IN_PROGRESS", "DONE", "REJECTED"]),
dataSubject: z.string().optional(),
contact: z.string().optional(),
details: z.string().optional(),