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>
This commit is contained in:
@@ -2095,6 +2095,7 @@ func (r *Resolver) AddDocumentTool(ctx context.Context, req *mcp.CallToolRequest
|
||||
Classification: input.Classification,
|
||||
DocumentType: input.DocumentType,
|
||||
TrustCenterVisibility: trustCenterVisibility,
|
||||
DefaultApproverIDs: input.DefaultApproverIds,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -2109,12 +2110,18 @@ func (r *Resolver) UpdateDocumentTool(ctx context.Context, req *mcp.CallToolRequ
|
||||
|
||||
svc := r.ProboService(ctx, input.ID)
|
||||
|
||||
var defaultApproverIDs *[]gid.GID
|
||||
if input.DefaultApproverIds != nil {
|
||||
defaultApproverIDs = &input.DefaultApproverIds
|
||||
}
|
||||
|
||||
document, err := svc.Documents.Update(
|
||||
ctx,
|
||||
probo.UpdateDocumentRequest{
|
||||
DocumentID: input.ID,
|
||||
Title: input.Title,
|
||||
TrustCenterVisibility: input.TrustCenterVisibility,
|
||||
DefaultApproverIDs: defaultApproverIDs,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@@ -3928,3 +3935,18 @@ func (r *Resolver) ListMeasureDocumentsTool(ctx context.Context, req *mcp.CallTo
|
||||
|
||||
return nil, types.NewListMeasureDocumentsOutput(docPage), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) VoidDocumentVersionApprovalTool(ctx context.Context, req *mcp.CallToolRequest, input *types.VoidDocumentVersionApprovalInput) (*mcp.CallToolResult, types.VoidDocumentVersionApprovalOutput, error) {
|
||||
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionVoidApproval)
|
||||
|
||||
svc := r.ProboService(ctx, input.DocumentVersionID)
|
||||
|
||||
_, documentVersion, err := svc.DocumentApprovals.VoidApproval(ctx, input.DocumentVersionID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot void document version approval: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.VoidDocumentVersionApprovalOutput{
|
||||
DocumentVersion: types.NewDocumentVersion(documentVersion),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -5159,6 +5159,7 @@ components:
|
||||
type: string
|
||||
enum:
|
||||
- DRAFT
|
||||
- PENDING_APPROVAL
|
||||
- PUBLISHED
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentVersionStatus
|
||||
|
||||
@@ -5495,6 +5496,11 @@ components:
|
||||
trust_center_visibility:
|
||||
$ref: "#/components/schemas/TrustCenterVisibility"
|
||||
description: Trust center visibility
|
||||
default_approver_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Default approver profile IDs
|
||||
|
||||
AddDocumentOutput:
|
||||
type: object
|
||||
@@ -5522,6 +5528,11 @@ components:
|
||||
trust_center_visibility:
|
||||
$ref: "#/components/schemas/TrustCenterVisibility"
|
||||
description: Trust center visibility
|
||||
default_approver_ids:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Default approver profile IDs
|
||||
|
||||
UpdateDocumentOutput:
|
||||
type: object
|
||||
@@ -5860,6 +5871,23 @@ components:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Deleted document version signature ID
|
||||
|
||||
VoidDocumentVersionApprovalInput:
|
||||
type: object
|
||||
required:
|
||||
- document_version_id
|
||||
properties:
|
||||
document_version_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Document version ID
|
||||
|
||||
VoidDocumentVersionApprovalOutput:
|
||||
type: object
|
||||
required:
|
||||
- document_version
|
||||
properties:
|
||||
document_version:
|
||||
$ref: "#/components/schemas/DocumentVersion"
|
||||
|
||||
MeetingOrderField:
|
||||
type: string
|
||||
enum:
|
||||
@@ -8474,6 +8502,15 @@ tools:
|
||||
$ref: "#/components/schemas/CancelSignatureRequestInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/CancelSignatureRequestOutput"
|
||||
- name: voidDocumentVersionApproval
|
||||
description: Void a pending document version approval request
|
||||
hints:
|
||||
readonly: false
|
||||
destructive: true
|
||||
inputSchema:
|
||||
$ref: "#/components/schemas/VoidDocumentVersionApprovalInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/VoidDocumentVersionApprovalOutput"
|
||||
- name: listMeetings
|
||||
description: List all meetings for the organization
|
||||
hints:
|
||||
|
||||
Reference in New Issue
Block a user