Add measure-document linking

Introduce the ability to link measures to documents, following the
existing pattern used by controls and risks. This includes:

- Database migration for measures_documents join table
- Coredata MeasureDocument struct with insert/delete operations
- Document service methods for listing/counting by measure ID
- Measure service CreateDocumentMapping/DeleteDocumentMapping methods
- Cleanup of measure-document mappings on document archive
- GraphQL mutations, inputs, payloads, and Measure.documents field
- DocumentConnection.TotalCount support for measure resolver
- MCP linkMeasure/unlinkMeasure updated to support documents
- MCP listMeasureDocuments tool
- Frontend MeasureDocumentsTab with LinkedDocumentsCard integration
- Authorization actions for measure document mapping
- E2e tests for measure document mapping

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-04-03 09:38:38 +02:00
parent 8de7add203
commit ef2e99d86c
16 changed files with 903 additions and 50 deletions

View File

@@ -2492,6 +2492,15 @@ type Measure implements Node {
filter: ControlFilter
): ControlConnection! @goField(forceResolver: true)
documents(
first: Int
after: CursorKey
last: Int
before: CursorKey
orderBy: DocumentOrder
filter: DocumentFilter
): DocumentConnection! @goField(forceResolver: true)
createdAt: Datetime!
updatedAt: Datetime!
@@ -3830,6 +3839,12 @@ type Mutation {
deleteRiskDocumentMapping(
input: DeleteRiskDocumentMappingInput!
): DeleteRiskDocumentMappingPayload!
createMeasureDocumentMapping(
input: CreateMeasureDocumentMappingInput!
): CreateMeasureDocumentMappingPayload!
deleteMeasureDocumentMapping(
input: DeleteMeasureDocumentMappingInput!
): DeleteMeasureDocumentMappingPayload!
createRiskObligationMapping(
input: CreateRiskObligationMappingInput!
): CreateRiskObligationMappingPayload!
@@ -4571,6 +4586,16 @@ input DeleteRiskDocumentMappingInput {
documentId: ID!
}
input CreateMeasureDocumentMappingInput {
measureId: ID!
documentId: ID!
}
input DeleteMeasureDocumentMappingInput {
measureId: ID!
documentId: ID!
}
input CreateRiskObligationMappingInput {
riskId: ID!
obligationId: ID!
@@ -5331,6 +5356,16 @@ type DeleteRiskDocumentMappingPayload {
deletedDocumentId: ID!
}
type CreateMeasureDocumentMappingPayload {
measureEdge: MeasureEdge!
documentEdge: DocumentEdge!
}
type DeleteMeasureDocumentMappingPayload {
deletedMeasureId: ID!
deletedDocumentId: ID!
}
type CreateRiskObligationMappingPayload {
riskEdge: RiskEdge!
obligationEdge: ObligationEdge!