mirror of
https://github.com/documenso/documenso.git
synced 2026-07-27 02:15:05 +10:00
chore: merged main
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* One entry in a CSC sign-time session, pinning the bytes (`documentDataId`)
|
||||
* whose digest (`hashB64`) was captured at prep time for a given envelope
|
||||
* item. The `ordinal` is the position of this entry in the session items array
|
||||
* — it lines up with the position-ordered `signatures/signHash` response per
|
||||
* CSC v1.0.4.0 §11.9.
|
||||
*/
|
||||
export const ZCscSessionItemSchema = z.object({
|
||||
envelopeItemId: z.string(),
|
||||
documentDataId: z.string(),
|
||||
hashB64: z.string(),
|
||||
ordinal: z.number().int().nonnegative(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Contract between CSC prep and sign on `CscSession.itemsJson`.
|
||||
*
|
||||
* Built at prep time alongside the captured signedAttrs digests. At sign time
|
||||
* the mutation re-derives each item's digest against the pinned
|
||||
* `documentDataId` bytes and dispatches one batched `signatures/signHash` per
|
||||
* recipient.
|
||||
*/
|
||||
export const ZCscSessionItemsSchema = z.array(ZCscSessionItemSchema);
|
||||
|
||||
export type TCscSessionItem = z.infer<typeof ZCscSessionItemSchema>;
|
||||
export type TCscSessionItems = z.infer<typeof ZCscSessionItemsSchema>;
|
||||
@@ -54,6 +54,13 @@ export const ZDocumentAuditLogTypeSchema = z.enum([
|
||||
'DOCUMENT_ACCESS_AUTH_2FA_REQUESTED', // When ACCESS AUTH 2FA is requested.
|
||||
'DOCUMENT_ACCESS_AUTH_2FA_VALIDATED', // When ACCESS AUTH 2FA is successfully validated.
|
||||
'DOCUMENT_ACCESS_AUTH_2FA_FAILED', // When ACCESS AUTH 2FA validation fails.
|
||||
|
||||
// CSC / TSP signing events.
|
||||
'DOCUMENT_RECIPIENT_CSC_AUTHENTICATED', // Service-scope OAuth complete; CSC credential persisted.
|
||||
'DOCUMENT_RECIPIENT_CSC_AUTHENTICATION_FAILED', // Service-scope OAuth completed but TSP returned a blocking error (empty credential list / invalid cert / refused algorithm).
|
||||
'DOCUMENT_RECIPIENT_CSC_SIGN_REQUESTED', // Recipient clicked Sign; CSC session created with captured per-item hashes.
|
||||
'DOCUMENT_RECIPIENT_CSC_AUTHORIZED', // Credential-scope OAuth complete; SAD attached to the CSC session.
|
||||
'DOCUMENT_RECIPIENT_CSC_SIGNED', // TSP returned signatures and they were embedded into the recipient's PDF bytes.
|
||||
]);
|
||||
|
||||
export const ZDocumentAuditLogEmailTypeSchema = z.enum([
|
||||
@@ -722,6 +729,71 @@ export const ZDocumentAuditLogEventRecipientExpiredSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: Recipient completed CSC service-scope OAuth — credential discovered, certificate persisted.
|
||||
*/
|
||||
export const ZDocumentAuditLogEventDocumentRecipientCscAuthenticatedSchema = z.object({
|
||||
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_CSC_AUTHENTICATED),
|
||||
data: ZBaseRecipientDataSchema.extend({
|
||||
providerId: z.string(),
|
||||
credentialId: z.string(),
|
||||
signatureAlgorithm: z.string(),
|
||||
digestAlgorithm: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: Recipient's CSC service-scope OAuth completed but the TSP returned a blocking error.
|
||||
*/
|
||||
export const ZDocumentAuditLogEventDocumentRecipientCscAuthenticationFailedSchema = z.object({
|
||||
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_CSC_AUTHENTICATION_FAILED),
|
||||
data: ZBaseRecipientDataSchema.extend({
|
||||
providerId: z.string(),
|
||||
reason: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: Recipient initiated TSP signing — CSC session created with per-item hashes.
|
||||
*/
|
||||
export const ZDocumentAuditLogEventDocumentRecipientCscSignRequestedSchema = z.object({
|
||||
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_CSC_SIGN_REQUESTED),
|
||||
data: ZBaseRecipientDataSchema.extend({
|
||||
providerId: z.string(),
|
||||
credentialId: z.string(),
|
||||
sessionId: z.string(),
|
||||
numSignatures: z.number(),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: Recipient completed CSC credential-scope OAuth — SAD attached to session.
|
||||
*/
|
||||
export const ZDocumentAuditLogEventDocumentRecipientCscAuthorizedSchema = z.object({
|
||||
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_CSC_AUTHORIZED),
|
||||
data: ZBaseRecipientDataSchema.extend({
|
||||
providerId: z.string(),
|
||||
credentialId: z.string(),
|
||||
sessionId: z.string(),
|
||||
sadExpiresAt: z.coerce.date(),
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: TSP returned signatures and they were embedded into the recipient's PDF bytes.
|
||||
*/
|
||||
export const ZDocumentAuditLogEventDocumentRecipientCscSignedSchema = z.object({
|
||||
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_CSC_SIGNED),
|
||||
data: ZBaseRecipientDataSchema.extend({
|
||||
providerId: z.string(),
|
||||
credentialId: z.string(),
|
||||
sessionId: z.string(),
|
||||
numItemsSigned: z.number(),
|
||||
signatureAlgorithm: z.string(),
|
||||
digestAlgorithm: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const ZDocumentAuditLogBaseSchema = z.object({
|
||||
id: z.string(),
|
||||
createdAt: z.date(),
|
||||
@@ -770,6 +842,11 @@ export const ZDocumentAuditLogSchema = ZDocumentAuditLogBaseSchema.and(
|
||||
ZDocumentAuditLogEventRecipientUpdatedSchema,
|
||||
ZDocumentAuditLogEventRecipientRemovedSchema,
|
||||
ZDocumentAuditLogEventRecipientExpiredSchema,
|
||||
ZDocumentAuditLogEventDocumentRecipientCscAuthenticatedSchema,
|
||||
ZDocumentAuditLogEventDocumentRecipientCscAuthenticationFailedSchema,
|
||||
ZDocumentAuditLogEventDocumentRecipientCscSignRequestedSchema,
|
||||
ZDocumentAuditLogEventDocumentRecipientCscAuthorizedSchema,
|
||||
ZDocumentAuditLogEventDocumentRecipientCscSignedSchema,
|
||||
]),
|
||||
);
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ export const ZLicenseClaimSchema = z.object({
|
||||
hipaa: z.boolean().optional(),
|
||||
authenticationPortal: z.boolean().optional(),
|
||||
billing: z.boolean().optional(),
|
||||
instanceCscSigning: z.boolean().optional(),
|
||||
cscQesSigning: z.boolean().optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -43,6 +45,13 @@ export type TLicenseClaim = z.infer<typeof ZLicenseClaimSchema>;
|
||||
export type TLicenseRequest = z.infer<typeof ZLicenseRequestSchema>;
|
||||
export type TLicenseResponse = z.infer<typeof ZLicenseResponseSchema>;
|
||||
|
||||
/**
|
||||
* String-literal union of every flag the licence server can grant. Adding a
|
||||
* field to `ZLicenseClaimSchema` automatically extends this type so that
|
||||
* `assertLicensedFor(flag)` and similar helpers stay in sync.
|
||||
*/
|
||||
export type LicenseFlag = keyof TLicenseClaim;
|
||||
|
||||
/**
|
||||
* Schema for the cached license data stored in the file.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* The cryptographic signature tier an envelope is signed at.
|
||||
*
|
||||
* - `SES` — Simple Electronic Signature; the default Documenso flow signed
|
||||
* with the instance-held certificate.
|
||||
* - `AES` — Advanced Electronic Signature; recipient-bound signing through a
|
||||
* Cloud Signature Consortium (CSC) Trust Service Provider.
|
||||
* - `QES` — Qualified Electronic Signature; the eIDAS-qualified variant of
|
||||
* AES, also recipient-bound through a CSC TSP.
|
||||
*
|
||||
* Stored as free-form TEXT on `Envelope.signatureLevel` so the legal-tier
|
||||
* taxonomy can expand without a DB enum migration. Validation lives here.
|
||||
*/
|
||||
export const ZSignatureLevelSchema = z.enum(['SES', 'AES', 'QES']);
|
||||
|
||||
export const SignatureLevel = ZSignatureLevelSchema.enum;
|
||||
|
||||
export type TSignatureLevel = z.infer<typeof ZSignatureLevelSchema>;
|
||||
|
||||
/**
|
||||
* Whether an envelope's signature level routes through a Cloud Signature
|
||||
* Consortium Trust Service Provider (`AES` or `QES`). The single branch point
|
||||
* for TSP-vs-SES runtime divergence — seal handler, download endpoint,
|
||||
* completion email, and send-time PDF prep all key off this.
|
||||
*
|
||||
* Accepts a raw `string` because the Prisma column is TEXT; unknown values
|
||||
* are conservatively treated as non-TSP so a malformed row can't accidentally
|
||||
* trigger TSP-only code paths.
|
||||
*/
|
||||
export const isTspEnvelope = (envelope: { signatureLevel: string }): boolean =>
|
||||
envelope.signatureLevel === SignatureLevel.AES || envelope.signatureLevel === SignatureLevel.QES;
|
||||
@@ -51,6 +51,8 @@ export const ZClaimFlagsSchema = z.object({
|
||||
|
||||
signingReminders: z.boolean().optional(),
|
||||
|
||||
cscQesSigning: z.boolean().optional(),
|
||||
|
||||
/**
|
||||
* Controls whether an organisation is prevented from sending emails.
|
||||
*
|
||||
@@ -128,6 +130,11 @@ export const SUBSCRIPTION_CLAIM_FEATURE_FLAGS: Record<
|
||||
key: 'signingReminders',
|
||||
label: 'Signing reminders',
|
||||
},
|
||||
cscQesSigning: {
|
||||
key: 'cscQesSigning',
|
||||
label: 'QES signing',
|
||||
isEnterprise: true,
|
||||
},
|
||||
disableEmails: {
|
||||
key: 'disableEmails',
|
||||
label: 'Disable emails',
|
||||
|
||||
Reference in New Issue
Block a user