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>
This commit is contained in:
@@ -4048,3 +4048,91 @@ func (r *Resolver) ListWebhookEventsTool(ctx context.Context, req *mcp.CallToolR
|
||||
|
||||
return nil, types.NewListWebhookEventsOutput(page), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) ListDocumentVersionApprovalQuorumsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionApprovalQuorumsInput) (*mcp.CallToolResult, types.ListDocumentVersionApprovalQuorumsOutput, error) {
|
||||
r.MustAuthorize(ctx, input.DocumentVersionID, probo.ActionDocumentVersionApprovalList)
|
||||
|
||||
svc := r.ProboService(ctx, input.DocumentVersionID)
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.DocumentVersionApprovalQuorumOrderField]{
|
||||
Field: coredata.DocumentVersionApprovalQuorumOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if input.OrderBy != nil {
|
||||
pageOrderBy = page.OrderBy[coredata.DocumentVersionApprovalQuorumOrderField]{
|
||||
Field: input.OrderBy.Field,
|
||||
Direction: input.OrderBy.Direction,
|
||||
}
|
||||
}
|
||||
|
||||
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
||||
|
||||
p, err := svc.DocumentApprovals.ListQuorums(ctx, input.DocumentVersionID, cursor)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list approval quorums: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewListDocumentVersionApprovalQuorumsOutput(p), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) GetDocumentVersionApprovalQuorumTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionApprovalQuorumInput) (*mcp.CallToolResult, types.GetDocumentVersionApprovalQuorumOutput, error) {
|
||||
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
|
||||
|
||||
svc := r.ProboService(ctx, input.ID)
|
||||
|
||||
quorum, err := svc.DocumentApprovals.GetQuorum(ctx, input.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot get approval quorum: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.GetDocumentVersionApprovalQuorumOutput{
|
||||
ApprovalQuorum: types.NewDocumentVersionApprovalQuorum(quorum),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resolver) ListDocumentVersionApprovalDecisionsTool(ctx context.Context, req *mcp.CallToolRequest, input *types.ListDocumentVersionApprovalDecisionsInput) (*mcp.CallToolResult, types.ListDocumentVersionApprovalDecisionsOutput, error) {
|
||||
r.MustAuthorize(ctx, input.QuorumID, probo.ActionDocumentVersionApprovalList)
|
||||
|
||||
svc := r.ProboService(ctx, input.QuorumID)
|
||||
|
||||
pageOrderBy := page.OrderBy[coredata.DocumentVersionApprovalDecisionOrderField]{
|
||||
Field: coredata.DocumentVersionApprovalDecisionOrderFieldCreatedAt,
|
||||
Direction: page.OrderDirectionDesc,
|
||||
}
|
||||
if input.OrderBy != nil {
|
||||
pageOrderBy = page.OrderBy[coredata.DocumentVersionApprovalDecisionOrderField]{
|
||||
Field: input.OrderBy.Field,
|
||||
Direction: input.OrderBy.Direction,
|
||||
}
|
||||
}
|
||||
|
||||
cursor := types.NewCursor(input.Size, input.Cursor, pageOrderBy)
|
||||
|
||||
var states []coredata.DocumentVersionApprovalDecisionState
|
||||
if input.Filter != nil {
|
||||
states = input.Filter.States
|
||||
}
|
||||
filter := coredata.NewDocumentVersionApprovalDecisionFilter(states)
|
||||
|
||||
p, err := svc.DocumentApprovals.ListDecisions(ctx, input.QuorumID, cursor, filter)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot list approval decisions: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.NewListDocumentVersionApprovalDecisionsOutput(p), nil
|
||||
}
|
||||
|
||||
func (r *Resolver) GetDocumentVersionApprovalDecisionTool(ctx context.Context, req *mcp.CallToolRequest, input *types.GetDocumentVersionApprovalDecisionInput) (*mcp.CallToolResult, types.GetDocumentVersionApprovalDecisionOutput, error) {
|
||||
r.MustAuthorize(ctx, input.ID, probo.ActionDocumentVersionApprovalList)
|
||||
|
||||
svc := r.ProboService(ctx, input.ID)
|
||||
|
||||
decision, err := svc.DocumentApprovals.GetDecision(ctx, input.ID)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("cannot get approval decision: %w", err))
|
||||
}
|
||||
|
||||
return nil, types.GetDocumentVersionApprovalDecisionOutput{
|
||||
ApprovalDecision: types.NewDocumentVersionApprovalDecision(decision),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -82,6 +82,32 @@ components:
|
||||
$ref: "#/components/schemas/OrderDirection"
|
||||
description: Vendor order direction
|
||||
|
||||
DocumentVersionApprovalQuorumOrderBy:
|
||||
type: object
|
||||
required:
|
||||
- field
|
||||
- direction
|
||||
properties:
|
||||
field:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalQuorumOrderField"
|
||||
description: Order field
|
||||
direction:
|
||||
$ref: "#/components/schemas/OrderDirection"
|
||||
description: Order direction
|
||||
|
||||
DocumentVersionApprovalDecisionOrderBy:
|
||||
type: object
|
||||
required:
|
||||
- field
|
||||
- direction
|
||||
properties:
|
||||
field:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalDecisionOrderField"
|
||||
description: Order field
|
||||
direction:
|
||||
$ref: "#/components/schemas/OrderDirection"
|
||||
description: Order direction
|
||||
|
||||
ProfileOrderBy:
|
||||
type: object
|
||||
required:
|
||||
@@ -5164,6 +5190,36 @@ components:
|
||||
- PUBLISHED
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentVersionStatus
|
||||
|
||||
DocumentVersionApprovalQuorumStatus:
|
||||
type: string
|
||||
enum:
|
||||
- PENDING
|
||||
- APPROVED
|
||||
- REJECTED
|
||||
- VOIDED
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentVersionApprovalQuorumStatus
|
||||
|
||||
DocumentVersionApprovalQuorumOrderField:
|
||||
type: string
|
||||
enum:
|
||||
- CREATED_AT
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentVersionApprovalQuorumOrderField
|
||||
|
||||
DocumentVersionApprovalDecisionState:
|
||||
type: string
|
||||
enum:
|
||||
- PENDING
|
||||
- APPROVED
|
||||
- REJECTED
|
||||
- VOIDED
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentVersionApprovalDecisionState
|
||||
|
||||
DocumentVersionApprovalDecisionOrderField:
|
||||
type: string
|
||||
enum:
|
||||
- CREATED_AT
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentVersionApprovalDecisionOrderField
|
||||
|
||||
DocumentStatus:
|
||||
type: string
|
||||
enum:
|
||||
@@ -5362,6 +5418,83 @@ components:
|
||||
format: date-time
|
||||
description: Update timestamp
|
||||
|
||||
DocumentVersionApprovalQuorum:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- organization_id
|
||||
- version_id
|
||||
- status
|
||||
- created_at
|
||||
- updated_at
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approval quorum ID
|
||||
organization_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Organization ID
|
||||
version_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Document version ID
|
||||
status:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalQuorumStatus"
|
||||
description: Approval quorum status
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Creation timestamp
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Update timestamp
|
||||
|
||||
DocumentVersionApprovalDecision:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- organization_id
|
||||
- quorum_id
|
||||
- approver_id
|
||||
- state
|
||||
- created_at
|
||||
- updated_at
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approval decision ID
|
||||
organization_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Organization ID
|
||||
quorum_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approval quorum ID
|
||||
approver_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approver profile ID
|
||||
state:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalDecisionState"
|
||||
description: Decision state
|
||||
comment:
|
||||
type:
|
||||
- string
|
||||
- "null"
|
||||
description: Approval or rejection comment
|
||||
decided_at:
|
||||
type:
|
||||
- string
|
||||
- "null"
|
||||
format: date-time
|
||||
description: Decision timestamp
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Creation timestamp
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Update timestamp
|
||||
|
||||
DocumentVersionSignature:
|
||||
type: object
|
||||
required:
|
||||
@@ -5876,6 +6009,110 @@ components:
|
||||
document_version:
|
||||
$ref: "#/components/schemas/DocumentVersion"
|
||||
|
||||
ListDocumentVersionApprovalQuorumsInput:
|
||||
type: object
|
||||
required:
|
||||
- document_version_id
|
||||
properties:
|
||||
document_version_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Document version ID
|
||||
order_by:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalQuorumOrderBy"
|
||||
description: Order by
|
||||
size:
|
||||
type: integer
|
||||
description: Page size
|
||||
cursor:
|
||||
$ref: "#/components/schemas/CursorKey"
|
||||
description: Page cursor
|
||||
|
||||
ListDocumentVersionApprovalQuorumsOutput:
|
||||
type: object
|
||||
required:
|
||||
- approval_quorums
|
||||
properties:
|
||||
next_cursor:
|
||||
$ref: "#/components/schemas/CursorKey"
|
||||
description: Next cursor
|
||||
approval_quorums:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalQuorum"
|
||||
|
||||
GetDocumentVersionApprovalQuorumInput:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approval quorum ID
|
||||
|
||||
GetDocumentVersionApprovalQuorumOutput:
|
||||
type: object
|
||||
required:
|
||||
- approval_quorum
|
||||
properties:
|
||||
approval_quorum:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalQuorum"
|
||||
|
||||
ListDocumentVersionApprovalDecisionsInput:
|
||||
type: object
|
||||
required:
|
||||
- quorum_id
|
||||
properties:
|
||||
quorum_id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approval quorum ID
|
||||
order_by:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalDecisionOrderBy"
|
||||
description: Order by
|
||||
size:
|
||||
type: integer
|
||||
description: Page size
|
||||
cursor:
|
||||
$ref: "#/components/schemas/CursorKey"
|
||||
description: Page cursor
|
||||
filter:
|
||||
type: object
|
||||
properties:
|
||||
states:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalDecisionState"
|
||||
description: Filter by decision states
|
||||
|
||||
ListDocumentVersionApprovalDecisionsOutput:
|
||||
type: object
|
||||
required:
|
||||
- approval_decisions
|
||||
properties:
|
||||
next_cursor:
|
||||
$ref: "#/components/schemas/CursorKey"
|
||||
description: Next cursor
|
||||
approval_decisions:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalDecision"
|
||||
|
||||
GetDocumentVersionApprovalDecisionInput:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/GID"
|
||||
description: Approval decision ID
|
||||
|
||||
GetDocumentVersionApprovalDecisionOutput:
|
||||
type: object
|
||||
required:
|
||||
- approval_decision
|
||||
properties:
|
||||
approval_decision:
|
||||
$ref: "#/components/schemas/DocumentVersionApprovalDecision"
|
||||
|
||||
SendSigningNotificationsInput:
|
||||
type: object
|
||||
required:
|
||||
@@ -9175,3 +9412,39 @@ tools:
|
||||
$ref: "#/components/schemas/ListWebhookEventsInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/ListWebhookEventsOutput"
|
||||
- name: listDocumentVersionApprovalQuorums
|
||||
description: List approval quorums for a document version
|
||||
hints:
|
||||
readonly: true
|
||||
idempotent: true
|
||||
inputSchema:
|
||||
$ref: "#/components/schemas/ListDocumentVersionApprovalQuorumsInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/ListDocumentVersionApprovalQuorumsOutput"
|
||||
- name: getDocumentVersionApprovalQuorum
|
||||
description: Get a document version approval quorum by ID
|
||||
hints:
|
||||
readonly: true
|
||||
idempotent: true
|
||||
inputSchema:
|
||||
$ref: "#/components/schemas/GetDocumentVersionApprovalQuorumInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/GetDocumentVersionApprovalQuorumOutput"
|
||||
- name: listDocumentVersionApprovalDecisions
|
||||
description: List approval decisions for an approval quorum
|
||||
hints:
|
||||
readonly: true
|
||||
idempotent: true
|
||||
inputSchema:
|
||||
$ref: "#/components/schemas/ListDocumentVersionApprovalDecisionsInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/ListDocumentVersionApprovalDecisionsOutput"
|
||||
- name: getDocumentVersionApprovalDecision
|
||||
description: Get a document version approval decision by ID
|
||||
hints:
|
||||
readonly: true
|
||||
idempotent: true
|
||||
inputSchema:
|
||||
$ref: "#/components/schemas/GetDocumentVersionApprovalDecisionInput"
|
||||
outputSchema:
|
||||
$ref: "#/components/schemas/GetDocumentVersionApprovalDecisionOutput"
|
||||
|
||||
@@ -190,3 +190,64 @@ func NewListDocumentVersionSignaturesOutput(signaturePage *page.Page[*coredata.D
|
||||
DocumentVersionSignatures: signatures,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDocumentVersionApprovalQuorum(q *coredata.DocumentVersionApprovalQuorum) *DocumentVersionApprovalQuorum {
|
||||
return &DocumentVersionApprovalQuorum{
|
||||
ID: q.ID,
|
||||
OrganizationID: q.OrganizationID,
|
||||
VersionID: q.VersionID,
|
||||
Status: q.Status,
|
||||
CreatedAt: q.CreatedAt,
|
||||
UpdatedAt: q.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func NewListDocumentVersionApprovalQuorumsOutput(quorumPage *page.Page[*coredata.DocumentVersionApprovalQuorum, coredata.DocumentVersionApprovalQuorumOrderField]) ListDocumentVersionApprovalQuorumsOutput {
|
||||
quorums := make([]*DocumentVersionApprovalQuorum, 0, len(quorumPage.Data))
|
||||
for _, q := range quorumPage.Data {
|
||||
quorums = append(quorums, NewDocumentVersionApprovalQuorum(q))
|
||||
}
|
||||
|
||||
var nextCursor *page.CursorKey
|
||||
if len(quorumPage.Data) > 0 {
|
||||
cursorKey := quorumPage.Data[len(quorumPage.Data)-1].CursorKey(quorumPage.Cursor.OrderBy.Field)
|
||||
nextCursor = &cursorKey
|
||||
}
|
||||
|
||||
return ListDocumentVersionApprovalQuorumsOutput{
|
||||
NextCursor: nextCursor,
|
||||
ApprovalQuorums: quorums,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDocumentVersionApprovalDecision(d *coredata.DocumentVersionApprovalDecision) *DocumentVersionApprovalDecision {
|
||||
return &DocumentVersionApprovalDecision{
|
||||
ID: d.ID,
|
||||
OrganizationID: d.OrganizationID,
|
||||
QuorumID: d.QuorumID,
|
||||
ApproverID: d.ApproverID,
|
||||
State: d.State,
|
||||
Comment: d.Comment,
|
||||
DecidedAt: d.DecidedAt,
|
||||
CreatedAt: d.CreatedAt,
|
||||
UpdatedAt: d.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func NewListDocumentVersionApprovalDecisionsOutput(decisionPage *page.Page[*coredata.DocumentVersionApprovalDecision, coredata.DocumentVersionApprovalDecisionOrderField]) ListDocumentVersionApprovalDecisionsOutput {
|
||||
decisions := make([]*DocumentVersionApprovalDecision, 0, len(decisionPage.Data))
|
||||
for _, d := range decisionPage.Data {
|
||||
decisions = append(decisions, NewDocumentVersionApprovalDecision(d))
|
||||
}
|
||||
|
||||
var nextCursor *page.CursorKey
|
||||
if len(decisionPage.Data) > 0 {
|
||||
cursorKey := decisionPage.Data[len(decisionPage.Data)-1].CursorKey(decisionPage.Cursor.OrderBy.Field)
|
||||
nextCursor = &cursorKey
|
||||
}
|
||||
|
||||
return ListDocumentVersionApprovalDecisionsOutput{
|
||||
NextCursor: nextCursor,
|
||||
ApprovalDecisions: decisions,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user