Files
probo/pkg/server/api/trust/v1/graphql/trust_center.graphql
Ludovic Vielle eccef41767 Adopt File type for trust logos and MCP
Trust GraphQL and MCP still exposed presigned URL strings for
trust-center logos while console and connect already serve stable
File.downloadUrl paths. Phase 1 migrates the seven public logo
fields on trust GraphQL and the trust-center file references on MCP
to the shared File type; trust GraphQL NDA stays on fileUrl for a
follow-up.

Trust resolvers load public files through filemanager and map them
with types.NewFile. The trust app Relay queries and components now
read logo.downloadUrl. MCP specification, resolvers, and helpers
are updated in sync, including NDA on MCP where callers already
have file access.

filemanager is split into focused files and its URL surface is
narrowed to GenerateFileURL(file) for stable app URLs and
GeneratePresignedURL for S3 redirects. GetPublicFile remains the
DB entry point when only a file ID is known.

Add trust and MCP e2e coverage for public logo download URLs.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-06-11 16:03:45 +02:00

425 lines
10 KiB
GraphQL

type TrustCenter implements Node {
id: ID!
active: Boolean!
slug: String!
logo: File @goField(forceResolver: true)
darkLogo: File @goField(forceResolver: true)
nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true)
viewerSubscription: MailingListSubscriber @goField(forceResolver: true)
organization: Organization! @goField(forceResolver: true)
documents(
first: Int
after: CursorKey
last: Int
before: CursorKey
): DocumentConnection! @goField(forceResolver: true)
audits(
first: Int
after: CursorKey
last: Int
before: CursorKey
): AuditConnection! @goField(forceResolver: true)
subprocessors(
first: Int
after: CursorKey
last: Int
before: CursorKey
): SubprocessorConnection! @goField(forceResolver: true)
references(
first: Int
after: CursorKey
last: Int
before: CursorKey
): TrustCenterReferenceConnection! @goField(forceResolver: true)
trustCenterFiles(
first: Int
after: CursorKey
last: Int
before: CursorKey
): TrustCenterFileConnection! @goField(forceResolver: true)
complianceFrameworks(
first: Int
after: CursorKey
last: Int
before: CursorKey
): ComplianceFrameworkConnection! @goField(forceResolver: true)
externalUrls(
first: Int
after: CursorKey
last: Int
before: CursorKey
): ComplianceExternalURLConnection! @goField(forceResolver: true)
updates(
first: Int
after: CursorKey
last: Int
before: CursorKey
): MailingListUpdateConnection! @goField(forceResolver: true)
}
enum DocumentType
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
GOVERNANCE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeGovernance")
POLICY @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
PROCEDURE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeProcedure")
PLAN @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePlan")
REGISTER
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeRegister")
RECORD @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeRecord")
REPORT @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeReport")
TEMPLATE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeTemplate")
STATEMENT_OF_APPLICABILITY
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.DocumentTypeStatementOfApplicability"
)
}
type Document implements Node @nda {
id: ID!
title: String!
documentType: DocumentType!
isUserAuthorized: Boolean! @goField(forceResolver: true)
access: DocumentAccess @goField(forceResolver: true)
}
type DocumentConnection @nda {
edges: [DocumentEdge!]!
pageInfo: PageInfo!
}
type DocumentEdge @nda {
cursor: CursorKey!
node: Document!
}
type Framework implements Node @nda {
id: ID!
name: String!
lightLogo: File @goField(forceResolver: true)
darkLogo: File @goField(forceResolver: true)
}
type AuditReport implements Node @nda {
id: ID!
fileName: String!
isUserAuthorized: Boolean! @goField(forceResolver: true)
access: DocumentAccess @goField(forceResolver: true)
}
type Audit implements Node @nda {
id: ID!
name: String
framework: Framework! @goField(forceResolver: true)
reportFile: AuditReport @goField(forceResolver: true)
}
type AuditConnection @nda {
edges: [AuditEdge!]!
pageInfo: PageInfo!
}
type AuditEdge @nda {
cursor: CursorKey!
node: Audit!
}
type ComplianceFramework implements Node
@goModel(
model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.ComplianceFramework"
) {
id: ID!
framework: Framework! @goField(forceResolver: true)
}
type ComplianceFrameworkConnection
@goModel(
model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.ComplianceFrameworkConnection"
) {
edges: [ComplianceFrameworkEdge!]!
pageInfo: PageInfo!
}
type ComplianceFrameworkEdge
@goModel(
model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.ComplianceFrameworkEdge"
) {
cursor: CursorKey!
node: ComplianceFramework!
}
enum SubprocessorCategory
@goModel(model: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategory") {
ANALYTICS
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryAnalytics")
CLOUD_MONITORING
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryCloudMonitoring"
)
CLOUD_PROVIDER
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryCloudProvider"
)
COLLABORATION
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryCollaboration"
)
CUSTOMER_SUPPORT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryCustomerSupport"
)
DATA_STORAGE_AND_PROCESSING
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryDataStorageAndProcessing"
)
DOCUMENT_MANAGEMENT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryDocumentManagement"
)
EMPLOYEE_MANAGEMENT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryEmployeeManagement"
)
ENGINEERING
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryEngineering")
FINANCE
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryFinance")
IDENTITY_PROVIDER
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryIdentityProvider"
)
IT @goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryIT")
MARKETING
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryMarketing")
OFFICE_OPERATIONS
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryOfficeOperations"
)
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryOther")
PASSWORD_MANAGEMENT
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryPasswordManagement"
)
PRODUCT_AND_DESIGN
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryProductAndDesign"
)
PROFESSIONAL_SERVICES
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryProfessionalServices"
)
RECRUITING
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryRecruiting")
SALES @goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategorySales")
SECURITY
@goEnum(value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategorySecurity")
VERSION_CONTROL
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.ThirdPartyCategoryVersionControl"
)
}
type Subprocessor implements Node @nda {
id: ID!
name: String!
description: String
category: SubprocessorCategory!
websiteUrl: String
privacyPolicyUrl: String
countries: [CountryCode!]!
}
type SubprocessorConnection
@goModel(
model: "go.probo.inc/probo/pkg/server/api/trust/v1/types.SubprocessorConnection"
) @nda {
edges: [SubprocessorEdge!]!
pageInfo: PageInfo!
totalCount: Int! @goField(forceResolver: true)
}
type SubprocessorEdge @nda {
cursor: CursorKey!
node: Subprocessor!
}
type TrustCenterReference implements Node @nda {
id: ID!
name: String!
description: String
websiteUrl: String!
logo: File! @goField(forceResolver: true)
}
type TrustCenterReferenceConnection @nda {
edges: [TrustCenterReferenceEdge!]!
pageInfo: PageInfo!
}
type TrustCenterReferenceEdge @nda {
cursor: CursorKey!
node: TrustCenterReference!
}
type TrustCenterFile implements Node @nda {
id: ID!
name: String!
category: String!
isUserAuthorized: Boolean! @goField(forceResolver: true)
access: DocumentAccess @goField(forceResolver: true)
}
type TrustCenterFileConnection @nda {
edges: [TrustCenterFileEdge!]!
pageInfo: PageInfo!
}
type TrustCenterFileEdge @nda {
cursor: CursorKey!
node: TrustCenterFile!
}
type ComplianceExternalURL implements Node {
id: ID!
name: String!
url: String!
rank: Int!
}
type ComplianceExternalURLConnection {
edges: [ComplianceExternalURLEdge!]!
pageInfo: PageInfo!
}
type ComplianceExternalURLEdge {
cursor: CursorKey!
node: ComplianceExternalURL!
}
type TrustCenterAccess implements Node {
id: ID!
email: EmailAddr!
name: String!
createdAt: Datetime!
updatedAt: Datetime!
}
enum DocumentAccessStatus
@goModel(
model: "go.probo.inc/probo/pkg/coredata.TrustCenterDocumentAccessStatus"
) {
REQUESTED
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.TrustCenterDocumentAccessStatusRequested"
)
GRANTED
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.TrustCenterDocumentAccessStatusGranted"
)
REJECTED
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.TrustCenterDocumentAccessStatusRejected"
)
REVOKED
@goEnum(
value: "go.probo.inc/probo/pkg/coredata.TrustCenterDocumentAccessStatusRevoked"
)
}
type DocumentAccess implements Node {
id: ID!
status: DocumentAccessStatus!
}
extend type Mutation {
requestAllAccesses: RequestAccessesPayload! @authentication(required: PRESENT) @nda
exportDocumentPDF(input: ExportDocumentPDFInput!): ExportDocumentPDFPayload!
@authentication(required: OPTIONAL) @nda
exportReportPDF(input: ExportReportPDFInput!): ExportReportPDFPayload!
@authentication(required: OPTIONAL) @nda
exportTrustCenterFile(
input: ExportTrustCenterFileInput!
): ExportTrustCenterFilePayload! @authentication(required: OPTIONAL) @nda
requestDocumentAccess(
input: RequestDocumentAccessInput!
): RequestDocumentAccessPayload! @authentication(required: PRESENT) @nda
requestReportAccess(
input: RequestReportAccessInput!
): RequestReportAccessPayload! @authentication(required: PRESENT) @nda
requestTrustCenterFileAccess(
input: RequestTrustCenterFileAccessInput!
): RequestFileAccessPayload! @authentication(required: PRESENT) @nda
}
type RequestDocumentAccessPayload {
document: Document
}
type RequestReportAccessPayload {
audit: Audit
}
type RequestFileAccessPayload {
file: TrustCenterFile
}
type RequestAccessesPayload {
trustCenterAccess: TrustCenterAccess!
}
input ExportDocumentPDFInput {
documentId: ID!
}
input ExportReportPDFInput {
reportId: ID!
}
input RequestDocumentAccessInput {
documentId: ID!
}
input RequestReportAccessInput {
reportId: ID!
}
input RequestTrustCenterFileAccessInput {
trustCenterFileId: ID!
}
input ExportTrustCenterFileInput {
trustCenterFileId: ID!
}
type ExportDocumentPDFPayload {
data: String!
}
type ExportReportPDFPayload {
data: String!
}
type ExportTrustCenterFilePayload {
data: String!
}