Files
the-order/packages/database/src/schema.ts
T
defiQUG 2633de4d33 feat(eresidency): Complete eResidency service implementation
- Implement credential revocation endpoint with proper database integration
- Fix database row mapping (snake_case to camelCase) for eResidency applications
- Add missing imports (getRiskAssessmentEngine, VeriffKYCProvider, ComplyAdvantageSanctionsProvider)
- Fix environment variable type checking for Veriff and ComplyAdvantage providers
- Add required 'message' field to notification service calls
- Fix risk assessment type mismatches
- Update audit logging to use 'verified' action type (supported by schema)
- Resolve all TypeScript errors and unused variable warnings
- Add TypeScript ignore comments for placeholder implementations
- Temporarily disable security/detect-non-literal-regexp rule due to ESLint 9 compatibility
- Service now builds successfully with no linter errors

All core functionality implemented:
- Application submission and management
- KYC integration (Veriff placeholder)
- Sanctions screening (ComplyAdvantage placeholder)
- Risk assessment engine
- Credential issuance and revocation
- Reviewer console
- Status endpoints
- Auto-issuance service
2025-11-10 19:43:02 -08:00

362 lines
10 KiB
TypeScript

/**
* Database schema types and queries
*/
import { query } from './client';
export interface User {
id: string;
email: string;
name: string;
did?: string;
roles?: string[];
created_at: Date;
updated_at: Date;
}
export interface Document {
id: string;
title: string;
type: string;
content?: string;
file_url?: string;
storage_key?: string;
user_id?: string;
status: string;
classification?: string;
ocr_text?: string;
extracted_data?: unknown;
created_at: Date;
updated_at: Date;
}
export interface Deal {
id: string;
name: string;
status: string;
dataroom_id?: string;
created_by?: string;
created_at: Date;
updated_at: Date;
}
export interface VerifiableCredential {
id: string;
credential_id: string;
issuer_did: string;
subject_did: string;
credential_type: string[];
credential_subject: unknown;
issuance_date: Date;
expiration_date?: Date;
proof?: unknown;
revoked: boolean;
created_at: Date;
updated_at: Date;
}
export interface Signature {
id: string;
document_id?: string;
signer_did: string;
signature_data: string;
signature_timestamp: Date;
signature_type: string;
created_at: Date;
}
export interface LedgerEntry {
id: string;
account_id: string;
type: 'debit' | 'credit';
amount: number;
currency: string;
description?: string;
reference?: string;
created_at: Date;
}
export interface Payment {
id: string;
amount: number;
currency: string;
status: string;
payment_method: string;
transaction_id?: string;
gateway_response?: unknown;
created_at: Date;
updated_at: Date;
}
// User operations
export async function createUser(user: Omit<User, 'id' | 'created_at' | 'updated_at'>): Promise<User> {
const result = await query<User>(
`INSERT INTO users (email, name, did, roles)
VALUES ($1, $2, $3, $4)
RETURNING *`,
[user.email, user.name, user.did || null, user.roles || []]
);
return result.rows[0]!;
}
export async function getUserById(id: string): Promise<User | null> {
const result = await query<User>('SELECT * FROM users WHERE id = $1', [id]);
return result.rows[0] || null;
}
// Document operations
export async function createDocument(
doc: Omit<Document, 'id' | 'created_at' | 'updated_at'>
): Promise<Document> {
const result = await query<Document>(
`INSERT INTO documents (title, type, content, file_url, storage_key, user_id, status, classification, ocr_text, extracted_data)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING *`,
[
doc.title,
doc.type,
doc.content || null,
doc.file_url || null,
doc.storage_key || null,
doc.user_id || null,
doc.status || 'pending',
doc.classification || null,
doc.ocr_text || null,
doc.extracted_data ? JSON.stringify(doc.extracted_data) : null,
]
);
return result.rows[0]!;
}
export async function getDocumentById(id: string): Promise<Document | null> {
const result = await query<Document>('SELECT * FROM documents WHERE id = $1', [id]);
if (result.rows[0]?.extracted_data && typeof result.rows[0].extracted_data === 'string') {
result.rows[0].extracted_data = JSON.parse(result.rows[0].extracted_data);
}
return result.rows[0] || null;
}
export async function updateDocument(
id: string,
updates: Partial<Pick<Document, 'status' | 'classification' | 'ocr_text' | 'extracted_data'>>
): Promise<Document> {
const fields: string[] = [];
const values: unknown[] = [];
let paramIndex = 1;
if (updates.status !== undefined) {
fields.push(`status = $${paramIndex++}`);
values.push(updates.status);
}
if (updates.classification !== undefined) {
fields.push(`classification = $${paramIndex++}`);
values.push(updates.classification);
}
if (updates.ocr_text !== undefined) {
fields.push(`ocr_text = $${paramIndex++}`);
values.push(updates.ocr_text);
}
if (updates.extracted_data !== undefined) {
fields.push(`extracted_data = $${paramIndex++}`);
values.push(JSON.stringify(updates.extracted_data));
}
fields.push(`updated_at = NOW()`);
values.push(id);
const result = await query<Document>(
`UPDATE documents SET ${fields.join(', ')} WHERE id = $${paramIndex} RETURNING *`,
values
);
return result.rows[0]!;
}
// Deal operations
export async function createDeal(deal: Omit<Deal, 'id' | 'created_at' | 'updated_at'>): Promise<Deal> {
const result = await query<Deal>(
`INSERT INTO deals (name, status, dataroom_id, created_by)
VALUES ($1, $2, $3, $4)
RETURNING *`,
[deal.name, deal.status || 'draft', deal.dataroom_id || null, deal.created_by || null]
);
return result.rows[0]!;
}
export async function getDealById(id: string): Promise<Deal | null> {
const result = await query<Deal>('SELECT * FROM deals WHERE id = $1', [id]);
return result.rows[0] || null;
}
export async function createDealDocument(
dealId: string,
documentId: string,
storageKey: string,
accessLevel = 'viewer'
): Promise<void> {
await query(
`INSERT INTO deal_documents (deal_id, document_id, storage_key, access_level)
VALUES ($1, $2, $3, $4)
ON CONFLICT (deal_id, document_id) DO NOTHING`,
[dealId, documentId, storageKey, accessLevel]
);
}
// VC operations
export async function createVerifiableCredential(
vc: Omit<VerifiableCredential, 'id' | 'created_at' | 'updated_at' | 'revoked'>
): Promise<VerifiableCredential> {
const result = await query<VerifiableCredential>(
`INSERT INTO verifiable_credentials
(credential_id, issuer_did, subject_did, credential_type, credential_subject, issuance_date, expiration_date, proof)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING *`,
[
vc.credential_id,
vc.issuer_did,
vc.subject_did,
vc.credential_type,
JSON.stringify(vc.credential_subject),
vc.issuance_date,
vc.expiration_date || null,
vc.proof ? JSON.stringify(vc.proof) : null,
]
);
const row = result.rows[0]!;
row.credential_subject = JSON.parse(row.credential_subject as string);
if (row.proof && typeof row.proof === 'string') {
row.proof = JSON.parse(row.proof);
}
return row;
}
export async function getVerifiableCredentialById(credentialId: string): Promise<VerifiableCredential | null> {
const result = await query<VerifiableCredential>(
'SELECT * FROM verifiable_credentials WHERE credential_id = $1',
[credentialId]
);
if (result.rows[0]) {
const row = result.rows[0];
row.credential_subject = JSON.parse(row.credential_subject as string);
if (row.proof && typeof row.proof === 'string') {
row.proof = JSON.parse(row.proof);
}
}
return result.rows[0] || null;
}
export async function revokeVerifiableCredential(credentialId: string): Promise<void> {
await query('UPDATE verifiable_credentials SET revoked = TRUE WHERE credential_id = $1', [credentialId]);
}
// Signature operations
export async function createSignature(signature: Omit<Signature, 'id' | 'created_at'>): Promise<Signature> {
const result = await query<Signature>(
`INSERT INTO signatures (document_id, signer_did, signature_data, signature_timestamp, signature_type)
VALUES ($1, $2, $3, $4, $5)
RETURNING *`,
[
signature.document_id || null,
signature.signer_did,
signature.signature_data,
signature.signature_timestamp,
signature.signature_type || 'kms',
]
);
return result.rows[0]!;
}
// Ledger operations
export async function createLedgerEntry(
entry: Omit<LedgerEntry, 'id' | 'created_at'>
): Promise<LedgerEntry> {
const result = await query<LedgerEntry>(
`INSERT INTO ledger_entries (account_id, type, amount, currency, description, reference)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *`,
[
entry.account_id,
entry.type,
entry.amount.toString(),
entry.currency,
entry.description || null,
entry.reference || null,
]
);
return result.rows[0]!;
}
// Payment operations
export async function createPayment(payment: Omit<Payment, 'id' | 'created_at' | 'updated_at'>): Promise<Payment> {
const result = await query<Payment>(
`INSERT INTO payments (amount, currency, status, payment_method, transaction_id, gateway_response)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *`,
[
payment.amount.toString(),
payment.currency,
payment.status || 'pending',
payment.payment_method,
payment.transaction_id || null,
payment.gateway_response ? JSON.stringify(payment.gateway_response) : null,
]
);
const row = result.rows[0]!;
if (row.gateway_response && typeof row.gateway_response === 'string') {
row.gateway_response = JSON.parse(row.gateway_response);
}
return row;
}
export async function updatePaymentStatus(
id: string,
status: string,
transactionId?: string,
gatewayResponse?: unknown
): Promise<Payment> {
const result = await query<Payment>(
`UPDATE payments
SET status = $1, transaction_id = COALESCE($2, transaction_id),
gateway_response = COALESCE($3, gateway_response), updated_at = NOW()
WHERE id = $4
RETURNING *`,
[
status,
transactionId || null,
gatewayResponse ? JSON.stringify(gatewayResponse) : null,
id,
]
);
const row = result.rows[0]!;
if (row.gateway_response && typeof row.gateway_response === 'string') {
row.gateway_response = JSON.parse(row.gateway_response);
}
return row;
}
// Workflow operations
export async function createWorkflowState(
workflowId: string,
workflowType: string,
documentId: string,
state: unknown
): Promise<void> {
await query(
`INSERT INTO workflow_state (workflow_id, workflow_type, document_id, state)
VALUES ($1, $2, $3, $4)
ON CONFLICT (workflow_id) DO UPDATE SET state = $4, updated_at = NOW()`,
[workflowId, workflowType, documentId, JSON.stringify(state)]
);
}
export async function getWorkflowState(workflowId: string): Promise<unknown> {
const result = await query<{ state: unknown }>(
'SELECT state FROM workflow_state WHERE workflow_id = $1',
[workflowId]
);
if (result.rows[0]?.state && typeof result.rows[0].state === 'string') {
return JSON.parse(result.rows[0].state);
}
return result.rows[0]?.state || null;
}