feat(06-01): install packages + extend schema + generate migration

- installed signature_pad, @react-email/render, @react-email/components
- added signingTokens table (jti pk, documentId, expiresAt, usedAt)
- added auditEvents table with auditEventTypeEnum (6 event types)
- added signedFilePath, pdfHash, signedAt columns to documents table
- generated and applied migration 0005_signing_flow.sql
This commit is contained in:
Chandler Copeland
2026-03-20 11:24:02 -06:00
parent 6cf228c779
commit fa68a1bcb4
6 changed files with 1060 additions and 1 deletions

View File

@@ -57,6 +57,9 @@ export const documents = pgTable("documents", {
preparedFilePath: text("prepared_file_path"),
/** Email addresses collected at prepare time: assigned client email + any CC addresses. */
emailAddresses: jsonb("email_addresses").$type<string[]>(),
signedFilePath: text("signed_file_path"),
pdfHash: text("pdf_hash"),
signedAt: timestamp("signed_at"),
});
export const documentsRelations = relations(documents, ({ one }) => ({
@@ -66,3 +69,32 @@ export const documentsRelations = relations(documents, ({ one }) => ({
export const clientsRelations = relations(clients, ({ many }) => ({
documents: many(documents),
}));
export const auditEventTypeEnum = pgEnum('audit_event_type', [
'document_prepared',
'email_sent',
'link_opened',
'document_viewed',
'signature_submitted',
'pdf_hash_computed',
]);
export const signingTokens = pgTable('signing_tokens', {
jti: text('jti').primaryKey(),
documentId: text('document_id').notNull()
.references(() => documents.id, { onDelete: 'cascade' }),
createdAt: timestamp('created_at').defaultNow().notNull(),
expiresAt: timestamp('expires_at').notNull(),
usedAt: timestamp('used_at'),
});
export const auditEvents = pgTable('audit_events', {
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
documentId: text('document_id').notNull()
.references(() => documents.id, { onDelete: 'cascade' }),
eventType: auditEventTypeEnum('event_type').notNull(),
ipAddress: text('ip_address'),
userAgent: text('user_agent'),
metadata: jsonb('metadata').$type<Record<string, unknown>>(),
createdAt: timestamp('created_at').defaultNow().notNull(),
});