diff --git a/.cursor/rules/packages/email.mdc b/.cursor/rules/packages/email.mdc
index 2d0f3843a..dd03ffb43 100644
--- a/.cursor/rules/packages/email.mdc
+++ b/.cursor/rules/packages/email.mdc
@@ -189,7 +189,7 @@ await sendEmail({
template:
})
```
diff --git a/README.md b/README.md
index 8a4cdc093..ecec7d169 100644
--- a/README.md
+++ b/README.md
@@ -50,11 +50,11 @@
π· **Incorporation** (wip) - Captable, Inc. helps you incorporate your company in minutes, with all the necessary legal documents and filings taken care of.
-π· **Cap table management** (wip) - Captable, Inc. helps you keep track of your companyβs ownership structure, including who owns what percentage of the company, how much stock/options has been issued, and more.
+π· **Cap table management** (wip) - Captable, Inc. helps you keep track of your company's ownership structure, including who owns what percentage of the company, how much stock/options has been issued, and more.
β
**Fundraise** - Captable, Inc. can help you raise capital, whether its signing standard or custom SAFE or creating and managing fundraising rounds, tracking investor commitments, and more.
-β
**Investor updates** - Delight your investors and team members by sending them regular updates on your companyβs progress.
+β
**Investor updates** - Delight your investors and team members by sending them regular updates on your company's progress.
β
**eSign Documents** - Sign SAFE, NDA, contracts, offere letters or any type of documents with Captable Sign.
@@ -78,7 +78,9 @@ We have a community of developers, designers, and entrepreneurs who are passiona
- [Next.js](https://nextjs.org)
- [Tailwind](https://tailwindcss.com)
-- [Prisma ORM](https://prisma.io)
+- [Drizzle ORM](https://orm.drizzle.team)
+- [tRPC](https://trpc.io)
+- [NextAuth.js](https://next-auth.js.org)
---
@@ -106,7 +108,7 @@ When contributing to Captable, Inc., whether on GitHub or in ot
- Install Docker & Docker Compose
- Fork & clone the forked repository
-- Install node and pnpm. (optional)
+- Install node and bun. (optional)
- Copy `.env.example` to `.env`
```bash
diff --git a/apps/captable/README.md b/apps/captable/README.md
index 8a4cdc093..c61efadc8 100644
--- a/apps/captable/README.md
+++ b/apps/captable/README.md
@@ -78,9 +78,34 @@ We have a community of developers, designers, and entrepreneurs who are passiona
- [Next.js](https://nextjs.org)
- [Tailwind](https://tailwindcss.com)
-- [Prisma ORM](https://prisma.io)
+- [Drizzle ORM](https://orm.drizzle.team)
---
+
Background Jobs
+
+Captable uses a custom job queue system for handling background tasks like:
+- π§ Email notifications (welcome, password reset, invites)
+- π PDF generation (e-signatures, documents)
+- π Data processing and synchronization
+
+**Development Setup:**
+```bash
+# Start with job processing (recommended)
+bun dx
+
+# Or start jobs separately
+bun run jobs:dev
+```
+
+**Job Management:**
+```bash
+bun run jobs # Process pending jobs
+bun run test-jobs # Queue sample test jobs
+bun run jobs stats # View queue statistics
+```
+
+Jobs are automatically processed in production via Cron jobs.
+
Getting started
When contributing to Captable, Inc., whether on GitHub or in other community spaces:
@@ -106,7 +131,7 @@ When contributing to Captable, Inc., whether on GitHub or in ot
- Install Docker & Docker Compose
- Fork & clone the forked repository
-- Install node and pnpm. (optional)
+- Install node and bun. (optional)
- Copy `.env.example` to `.env`
```bash
@@ -117,10 +142,10 @@ When contributing to Captable, Inc., whether on GitHub or in ot
```bash
- # With pnpm installed
- pnpm dx
+ # With bun installed
+ bun dx
- # Without pnpm installed
+ # Without bun installed
docker compose up
```
@@ -129,8 +154,8 @@ When contributing to Captable, Inc., whether on GitHub or in ot
```bash
- docker compose exec app pnpm db:migrate
- docker compose exec app pnpm db:seed
+ docker compose exec app bun db:migrate
+ docker compose exec app bun db:seed
```
@@ -143,15 +168,15 @@ When contributing to Captable, Inc., whether on GitHub or in ot
- Emails will be intercepted: [http://localhost:8025](http://localhost:8025)
- SMTP will be on PORT `http://localhost:1025`
- Postgres will be on PORT `http://localhost:5432`
- - Prisma studio will be on PORT `http://localhost:5555`
+ - Database studio will be on PORT `http://localhost:5555`
- Frequently used commands
- `docker compose up` - Start the development environment
- `docker compose down` - Stop the development environment
- `docker compose logs -f` - View logs of the running services
- `docker compose up --build` - Rebuild the docker image
- - `docker compose run app pnpm db:migrate` - Run database migrations
- - `docker compose run app pnpm db:seed` - Seed the database
+ - `docker compose run app bun db:migrate` - Run database migrations
+ - `docker compose run app bun db:seed` - Seed the database
---
@@ -218,23 +243,23 @@ When contributing to Captable, Inc., whether on GitHub or in ot
- Run the following command to install dependencies
```bash
- pnpm install
+ bun install
```
- Run the following command to migrate and seed the database
```bash
- pnpm db:migrate
- pnpm db:seed
+ bun db:migrate
+ bun db:seed
```
- Run the following command to start the development server
```bash
- pnpm dev
+ bun dev
# On a different terminal, run the following command to start the mail server
- pnpm email:dev
+ bun email:dev
```
- App will be running on [http://localhost:3000](http://localhost:3000)
@@ -243,10 +268,10 @@ When contributing to Captable, Inc., whether on GitHub or in ot
- Postgres will be on PORT `http://localhost:5432`
- Frequently used commands
- - `pnpm dev` - Start the development server
- - `pnpm email:dev` - Start the mail server
- - `pnpm db:migrate` - Run database migrations
- - `pnpm db:seed` - Seed the database
+ - `bun dev` - Start the development server
+ - `bun email:dev` - Start the mail server
+ - `bun db:migrate` - Run database migrations
+ - `bun db:seed` - Seed the database
Implement your changes
diff --git a/apps/captable/app/api/cron/cleanup-jobs/route.ts b/apps/captable/app/api/cron/cleanup-jobs/route.ts
new file mode 100644
index 000000000..a1ab26cac
--- /dev/null
+++ b/apps/captable/app/api/cron/cleanup-jobs/route.ts
@@ -0,0 +1,30 @@
+import { logger } from "@captable/logger";
+import { cleanupJobs } from "@captable/queue";
+import { type NextRequest, NextResponse } from "next/server";
+
+const log = logger.child({ module: "cron-cleanup" });
+
+export async function GET(request: NextRequest) {
+ // Verify cron secret
+ const authHeader = request.headers.get("authorization");
+ if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
+ return new Response("Unauthorized", { status: 401 });
+ }
+
+ try {
+ const cleaned = await cleanupJobs(7); // Clean jobs older than 7 days
+
+ log.info({ cleaned }, "Job cleanup completed");
+
+ return NextResponse.json({
+ success: true,
+ cleaned,
+ });
+ } catch (error) {
+ log.error({ error }, "Job cleanup failed");
+ return NextResponse.json(
+ { error: "Internal server error" },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/captable/app/api/cron/process-jobs/route.ts b/apps/captable/app/api/cron/process-jobs/route.ts
new file mode 100644
index 000000000..207411eb9
--- /dev/null
+++ b/apps/captable/app/api/cron/process-jobs/route.ts
@@ -0,0 +1,63 @@
+import { logger } from "@captable/logger";
+import { processJobs } from "@captable/queue";
+import { type NextRequest, NextResponse } from "next/server";
+import "@/jobs"; // Import to register all jobs
+
+const log = logger.child({ module: "cron-jobs" });
+
+export async function GET(request: NextRequest) {
+ // Verify cron secret for security
+ const authHeader = request.headers.get("authorization");
+ const expectedAuth = `Bearer ${process.env.CRON_SECRET}`;
+
+ if (!expectedAuth || authHeader !== expectedAuth) {
+ log.warn({ authHeader }, "Unauthorized cron job access attempt");
+ return new Response("Unauthorized", { status: 401 });
+ }
+
+ try {
+ const startTime = Date.now();
+
+ // Process jobs in batches
+ let totalProcessed = 0;
+ let batchCount = 0;
+ const maxBatches = 10; // Prevent infinite loops
+
+ while (batchCount < maxBatches) {
+ const processed = await processJobs(20); // Process 20 jobs per batch
+ totalProcessed += processed;
+ batchCount++;
+
+ if (processed === 0) {
+ break; // No more jobs to process
+ }
+
+ // Small delay between batches
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ }
+
+ const duration = Date.now() - startTime;
+
+ log.info(
+ {
+ totalProcessed,
+ batches: batchCount,
+ duration,
+ },
+ "Cron job processing completed",
+ );
+
+ return NextResponse.json({
+ success: true,
+ processed: totalProcessed,
+ batches: batchCount,
+ duration,
+ });
+ } catch (error) {
+ log.error({ error }, "Cron job processing failed");
+ return NextResponse.json(
+ { error: "Internal server error" },
+ { status: 500 },
+ );
+ }
+}
diff --git a/apps/captable/components/onboarding/forgot-password/index.tsx b/apps/captable/components/onboarding/forgot-password/index.tsx
index 1e26204bb..93f320118 100644
--- a/apps/captable/components/onboarding/forgot-password/index.tsx
+++ b/apps/captable/components/onboarding/forgot-password/index.tsx
@@ -40,7 +40,7 @@ const ForgotPassword = () => {
},
});
const onSubmit = async (values: z.infer) => {
- await mutateAsync(values.email);
+ await mutateAsync(values);
};
return (
diff --git a/apps/captable/jobs/auth-verification-email.ts b/apps/captable/jobs/auth-verification-email.ts
index aa786c6d9..f361b0fc2 100644
--- a/apps/captable/jobs/auth-verification-email.ts
+++ b/apps/captable/jobs/auth-verification-email.ts
@@ -1,7 +1,8 @@
-import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "auth-verification-email-job" });
export type AuthVerificationEmailPayloadType = {
email: string;
@@ -11,6 +12,8 @@ export type AuthVerificationEmailPayloadType = {
const sendAuthVerificationEmail = async (
payload: AuthVerificationEmailPayloadType,
) => {
+ log.info({ email: payload.email }, "Sending auth verification email");
+
// Dynamic import to avoid build-time processing
const { render } = await import("@captable/email");
const { AccountVerificationEmail } = await import(
@@ -28,14 +31,30 @@ const sendAuthVerificationEmail = async (
subject: "Verify your account",
html,
});
+
+ log.info(
+ { email: payload.email },
+ "Auth verification email sent successfully",
+ );
};
export { sendAuthVerificationEmail };
export class AuthVerificationEmailJob extends BaseJob {
readonly type = "email.auth-verify";
+ protected readonly options = {
+ maxAttempts: 5, // Critical for account verification
+ retryDelay: 1000,
+ priority: 3, // High priority
+ };
- async work(job: Job): Promise {
- await sendAuthVerificationEmail(job.data);
+ async work(payload: AuthVerificationEmailPayloadType): Promise {
+ await sendAuthVerificationEmail(payload);
}
}
+
+// Create and register the job instance
+const authVerificationEmailJob = new AuthVerificationEmailJob();
+authVerificationEmailJob.register();
+
+export { authVerificationEmailJob };
diff --git a/apps/captable/jobs/base.ts b/apps/captable/jobs/base.ts
deleted file mode 100644
index c4a22e5f8..000000000
--- a/apps/captable/jobs/base.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { env } from "@/env";
-import type { JOB_TYPES } from "@/lib/constants/job";
-import { singleton } from "@/lib/singleton";
-import { logger } from "@captable/logger";
-import pgBoss from "pg-boss";
-
-type JobTypes = typeof JOB_TYPES;
-
-const log = logger.child({ module: "jobs" });
-
-export type JobType = {
- [Key in keyof JobTypes]: `${Key}.${JobTypes[Key][number]}`;
-}[keyof JobTypes];
-
-interface Job {
- type: JobType;
- options: pgBoss.SendOptions;
- start: () => Promise;
- work: (job: pgBoss.Job) => Promise;
- emit: (data: T) => Promise;
-}
-
-export abstract class BaseJob implements Job {
- protected boss: pgBoss;
- abstract readonly type: JobType;
- readonly options = { retryLimit: 3, retryDelay: 1000 };
-
- constructor() {
- this.boss = boss;
- }
-
- async start(): Promise {
- await this.boss.work(
- this.type,
- this.work.bind(this) as unknown as pgBoss.WorkHandler,
- );
- }
-
- abstract work(job: pgBoss.Job): Promise;
-
- async emit(data: T, options?: pgBoss.SendOptions): Promise {
- await this.boss.send(this.type, data, options ?? this.options);
- }
- async bulkEmit(data: Omit, "name">[]): Promise {
- await this.boss.insert(
- data.map((items) => ({ ...items, name: this.type })),
- );
- }
-}
-
-export class JobManager {
- private readonly boss: pgBoss;
- // biome-ignore lint/suspicious/noExplicitAny:
- private jobs = new Map>();
-
- constructor(boss: pgBoss) {
- this.boss = boss;
- }
-
- // biome-ignore lint/suspicious/noExplicitAny:
- register(job: new (boss: pgBoss) => Job): JobManager {
- const jobInstance = new job(this.boss);
- this.jobs.set(jobInstance.type, jobInstance);
- return this;
- }
-
- async start(): Promise {
- const startTime = Date.now();
- log.info("Starting pg-boss job queue manager");
-
- await this.boss.start();
-
- const endTime = Date.now();
- const elapsedTime = endTime - startTime;
-
- log.info(
- `Successfully started pg-boss job queue manager in ${elapsedTime}ms`,
- );
-
- for (const [jobName, job] of this.jobs.entries()) {
- const jobStartTime = Date.now();
- log.info(`Registering pg-boss job:${jobName}`);
-
- await job.start();
-
- const jobEndTime = Date.now();
- const jobElapsedTime = jobEndTime - jobStartTime;
-
- log.info(
- `Successfully registered pg-boss job:${jobName} in ${jobElapsedTime}ms`,
- );
- }
- }
-}
-
-export const boss = singleton(
- "pg-boss",
- () =>
- new pgBoss({
- connectionString: env.DATABASE_URL,
- max: 5,
- retryBackoff: true,
- retryLimit: 4,
- archiveCompletedAfterSeconds: 60 * 60 * 2, // 2 hours
- deleteAfterDays: 2,
- retentionDays: 2,
- }),
-);
diff --git a/apps/captable/jobs/esign-confirmation-email.ts b/apps/captable/jobs/esign-confirmation-email.ts
index d8ffc74d9..b7bf87728 100644
--- a/apps/captable/jobs/esign-confirmation-email.ts
+++ b/apps/captable/jobs/esign-confirmation-email.ts
@@ -1,7 +1,8 @@
-import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "esign-confirmation-email-job" });
export type EsignConfirmationEmailPayloadType = {
documentName: string;
@@ -11,12 +12,24 @@ export type EsignConfirmationEmailPayloadType = {
name: string;
logo?: string | null;
};
- recipient: { name?: string | null; email: string };
+ recipient: {
+ name?: string | null;
+ email: string;
+ };
};
const sendEsignConfirmationEmail = async (
payload: EsignConfirmationEmailPayloadType,
) => {
+ log.info(
+ {
+ email: payload.recipient.email,
+ document: payload.documentName,
+ company: payload.company.name,
+ },
+ "Sending esign confirmation email",
+ );
+
// Dynamic import to avoid build-time processing
const { render } = await import("@captable/email");
const { EsignConfirmationEmail } = await import("@captable/email/templates");
@@ -33,15 +46,37 @@ const sendEsignConfirmationEmail = async (
await sendMail({
to: [payload.recipient.email],
- subject: `Document signed: ${payload.documentName}`,
+ subject: `Document signed confirmation - ${payload.documentName}`,
html,
});
+
+ log.info(
+ {
+ email: payload.recipient.email,
+ document: payload.documentName,
+ company: payload.company.name,
+ },
+ "Esign confirmation email sent successfully",
+ );
};
+export { sendEsignConfirmationEmail };
+
export class EsignConfirmationEmailJob extends BaseJob {
readonly type = "email.esign-confirmation";
+ protected readonly options = {
+ maxAttempts: 3,
+ retryDelay: 1000,
+ priority: 1, // Normal priority for confirmations
+ };
- async work(job: Job): Promise {
- await sendEsignConfirmationEmail(job.data);
+ async work(payload: EsignConfirmationEmailPayloadType): Promise {
+ await sendEsignConfirmationEmail(payload);
}
}
+
+// Create and register the job instance
+const esignConfirmationEmailJob = new EsignConfirmationEmailJob();
+esignConfirmationEmailJob.register();
+
+export { esignConfirmationEmailJob };
diff --git a/apps/captable/jobs/esign-email.ts b/apps/captable/jobs/esign-email.ts
index 2ba582c06..fc7102a66 100644
--- a/apps/captable/jobs/esign-email.ts
+++ b/apps/captable/jobs/esign-email.ts
@@ -1,8 +1,8 @@
-import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import { db, eq, esignRecipients, templates } from "@captable/db";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "esign-email-job" });
export type EsignEmailPayloadType = {
documentName?: string;
@@ -24,6 +24,15 @@ export type EsignEmailPayloadType = {
};
const sendEsignEmail = async (payload: EsignEmailPayloadType) => {
+ log.info(
+ {
+ recipientEmail: payload.recipient.email,
+ documentName: payload.documentName,
+ company: payload.company?.name,
+ },
+ "Sending esign email",
+ );
+
// Dynamic import to avoid build-time processing
const { render } = await import("@captable/email");
const { EsignEmail } = await import("@captable/email/templates");
@@ -44,12 +53,34 @@ const sendEsignEmail = async (payload: EsignEmailPayloadType) => {
subject: `${payload.sender?.name} has sent you a document to sign`,
html,
});
+
+ log.info(
+ {
+ recipientEmail: payload.recipient.email,
+ documentName: payload.documentName,
+ company: payload.company?.name,
+ },
+ "Esign email sent successfully",
+ );
};
+export { sendEsignEmail };
+
export class EsignEmailJob extends BaseJob {
readonly type = "email.esign-notification";
+ protected readonly options = {
+ maxAttempts: 3,
+ retryDelay: 1500,
+ priority: 2, // High priority for legal documents
+ };
- async work(job: Job): Promise {
- await sendEsignEmail(job.data);
+ async work(payload: EsignEmailPayloadType): Promise {
+ await sendEsignEmail(payload);
}
}
+
+// Create and register the job instance
+const esignEmailJob = new EsignEmailJob();
+esignEmailJob.register();
+
+export { esignEmailJob };
diff --git a/apps/captable/jobs/esign-pdf.ts b/apps/captable/jobs/esign-pdf.ts
index 0ec9287d7..dce63ba3f 100644
--- a/apps/captable/jobs/esign-pdf.ts
+++ b/apps/captable/jobs/esign-pdf.ts
@@ -1,4 +1,3 @@
-import { BaseJob } from "@/jobs/base";
import {
type EsignGetTemplateType,
completeEsignDocuments,
@@ -7,11 +6,11 @@ import {
} from "@/server/esign";
import { getPresignedGetUrl } from "@/server/file-uploads";
import { db } from "@captable/db";
-import type { Job } from "pg-boss";
-import {
- EsignConfirmationEmailJob,
- type EsignConfirmationEmailPayloadType,
-} from "./esign-confirmation-email";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+import { esignConfirmationEmailJob } from "./esign-confirmation-email";
+
+const log = logger.child({ module: "esign-pdf-job" });
export type EsignPdfPayloadType = {
fields: EsignGetTemplateType["fields"];
@@ -38,8 +37,13 @@ export type EsignPdfPayloadType = {
export class EsignPdfJob extends BaseJob {
readonly type = "generate.esign-pdf";
+ protected readonly options = {
+ maxAttempts: 2, // PDF generation is heavy, limit retries
+ retryDelay: 5000, // Longer delay for PDF processing
+ priority: 3, // High priority for document processing
+ };
- async work(job: Job): Promise {
+ async work(payload: EsignPdfPayloadType): Promise {
const {
bucketKey,
data,
@@ -53,48 +57,110 @@ export class EsignPdfJob extends BaseJob {
templateId,
recipients,
company,
- } = job.data;
+ } = payload;
- const modifiedPdfBytes = await generateEsignPdf({
- bucketKey,
- data,
- fields,
- audits,
- templateName,
- });
- const { fileUrl: _fileUrl, ...bucketData } = await uploadEsignDocuments({
- buffer: Buffer.from(modifiedPdfBytes),
- companyId,
- templateName,
- });
+ log.info(
+ {
+ templateId,
+ templateName,
+ companyId,
+ recipientCount: recipients.length,
+ },
+ "Starting esign PDF generation",
+ );
+
+ try {
+ const modifiedPdfBytes = await generateEsignPdf({
+ bucketKey,
+ data,
+ fields,
+ audits,
+ templateName,
+ });
- await db.transaction(async (tx) => {
- await completeEsignDocuments({
- bucketData: bucketData,
+ log.info(
+ {
+ templateId,
+ templateName,
+ pdfSize: modifiedPdfBytes.length,
+ },
+ "PDF generated successfully",
+ );
+
+ const { fileUrl: _fileUrl, ...bucketData } = await uploadEsignDocuments({
+ buffer: Buffer.from(modifiedPdfBytes),
companyId,
- db: tx,
- requestIp,
- templateId,
templateName,
- uploaderName: sender.name || "Captable",
- userAgent,
});
- });
- const file = await getPresignedGetUrl(bucketData.key);
+ log.info(
+ {
+ templateId,
+ bucketKey: bucketData.key,
+ },
+ "PDF uploaded to storage",
+ );
+
+ await db.transaction(async (tx) => {
+ await completeEsignDocuments({
+ bucketData: bucketData,
+ companyId,
+ db: tx,
+ requestIp,
+ templateId,
+ templateName,
+ uploaderName: sender.name || "Captable",
+ userAgent,
+ });
+ });
+
+ log.info(
+ {
+ templateId,
+ templateName,
+ },
+ "Esign documents completed in database",
+ );
- const recipientData: { data: EsignConfirmationEmailPayloadType }[] =
- recipients.map((recipient) => ({
- data: {
- fileUrl: file.url,
+ const _file = await getPresignedGetUrl(bucketData.key);
+
+ // Send confirmation emails to all recipients
+ const emailPromises = recipients.map((recipient) =>
+ esignConfirmationEmailJob.emit({
documentName: templateName,
recipient,
company,
senderName: sender.name || "Captable",
senderEmail: sender.email as string,
- },
- }));
+ }),
+ );
- await new EsignConfirmationEmailJob().bulkEmit(recipientData);
+ await Promise.all(emailPromises);
+
+ log.info(
+ {
+ templateId,
+ templateName,
+ recipientCount: recipients.length,
+ },
+ "Esign PDF job completed successfully",
+ );
+ } catch (error) {
+ log.error(
+ {
+ templateId,
+ templateName,
+ error: error instanceof Error ? error.message : String(error),
+ },
+ "Esign PDF job failed",
+ );
+ throw error;
+ }
}
}
+
+// Create and register the job instance
+const esignPdfJob = new EsignPdfJob();
+esignPdfJob.register();
+
+export { esignPdfJob };
diff --git a/apps/captable/jobs/index.ts b/apps/captable/jobs/index.ts
new file mode 100644
index 000000000..0c26de88f
--- /dev/null
+++ b/apps/captable/jobs/index.ts
@@ -0,0 +1,31 @@
+// Import all job files to register them
+import "./password-reset-email";
+import "./member-inivite-email";
+import "./auth-verification-email";
+import "./share-update-email";
+import "./share-data-room-email";
+import "./esign-email";
+import "./esign-confirmation-email";
+import "./esign-pdf";
+
+// Re-export job instances for direct usage
+export { passwordResetEmailJob } from "./password-reset-email";
+export { memberInviteEmailJob } from "./member-inivite-email";
+export { authVerificationEmailJob } from "./auth-verification-email";
+export { shareUpdateEmailJob } from "./share-update-email";
+export { shareDataRoomEmailJob } from "./share-data-room-email";
+export { esignEmailJob } from "./esign-email";
+export { esignConfirmationEmailJob } from "./esign-confirmation-email";
+export { esignPdfJob } from "./esign-pdf";
+
+// Re-export queue functions for direct usage
+export {
+ addJob,
+ addJobs,
+ processJobs,
+ cleanupJobs,
+ getStats,
+ getRegisteredProcessors,
+ clearProcessors,
+ register,
+} from "@captable/queue";
diff --git a/apps/captable/jobs/member-inivite-email.ts b/apps/captable/jobs/member-inivite-email.ts
index ea459c916..96aef8ea4 100644
--- a/apps/captable/jobs/member-inivite-email.ts
+++ b/apps/captable/jobs/member-inivite-email.ts
@@ -1,7 +1,8 @@
-import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "member-invite-email-job" });
export type MemberInviteEmailPayloadType = {
email: string;
@@ -11,6 +12,14 @@ export type MemberInviteEmailPayloadType = {
};
const sendMemberInviteEmail = async (payload: MemberInviteEmailPayloadType) => {
+ log.info(
+ {
+ email: payload.email,
+ company: payload.companyName,
+ },
+ "Sending member invite email",
+ );
+
// Dynamic import to avoid build-time processing
const { render } = await import("@captable/email");
const { MemberInviteEmail } = await import("@captable/email/templates");
@@ -28,14 +37,33 @@ const sendMemberInviteEmail = async (payload: MemberInviteEmailPayloadType) => {
subject: `You're invited to join ${payload.companyName}`,
html,
});
+
+ log.info(
+ {
+ email: payload.email,
+ company: payload.companyName,
+ },
+ "Member invite email sent successfully",
+ );
};
export { sendMemberInviteEmail };
export class MemberInviteEmailJob extends BaseJob {
readonly type = "email.member-invite";
+ protected readonly options = {
+ maxAttempts: 3,
+ retryDelay: 1500,
+ priority: 2, // Higher priority for invites
+ };
- async work(job: Job): Promise {
- await sendMemberInviteEmail(job.data);
+ async work(payload: MemberInviteEmailPayloadType): Promise {
+ await sendMemberInviteEmail(payload);
}
}
+
+// Create and register the job instance
+const memberInviteEmailJob = new MemberInviteEmailJob();
+memberInviteEmailJob.register();
+
+export { memberInviteEmailJob };
diff --git a/apps/captable/jobs/password-reset-email.ts b/apps/captable/jobs/password-reset-email.ts
index c55475cbf..46ac8c468 100644
--- a/apps/captable/jobs/password-reset-email.ts
+++ b/apps/captable/jobs/password-reset-email.ts
@@ -1,7 +1,8 @@
-import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "password-reset-email-job" });
export type PasswordResetEmailPayloadType = {
email: string;
@@ -11,6 +12,8 @@ export type PasswordResetEmailPayloadType = {
const sendPasswordResetEmail = async (
payload: PasswordResetEmailPayloadType,
) => {
+ log.info({ email: payload.email }, "Sending password reset email");
+
// Dynamic import to avoid build-time processing
const { render } = await import("@captable/email");
const { PasswordResetEmail } = await import("@captable/email/templates");
@@ -26,14 +29,27 @@ const sendPasswordResetEmail = async (
subject: "Reset your password",
html,
});
+
+ log.info({ email: payload.email }, "Password reset email sent successfully");
};
export { sendPasswordResetEmail };
export class PasswordResetEmailJob extends BaseJob {
readonly type = "email.password-reset";
+ protected readonly options = {
+ maxAttempts: 5, // Email is critical
+ retryDelay: 2000,
+ priority: 1, // High priority
+ };
- async work(job: Job): Promise {
- await sendPasswordResetEmail(job.data);
+ async work(payload: PasswordResetEmailPayloadType): Promise {
+ await sendPasswordResetEmail(payload);
}
}
+
+// Create and register the job instance
+const passwordResetEmailJob = new PasswordResetEmailJob();
+passwordResetEmailJob.register();
+
+export { passwordResetEmailJob };
diff --git a/apps/captable/jobs/share-data-room-email.ts b/apps/captable/jobs/share-data-room-email.ts
index e92d43daa..9937739e8 100644
--- a/apps/captable/jobs/share-data-room-email.ts
+++ b/apps/captable/jobs/share-data-room-email.ts
@@ -1,48 +1,78 @@
import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import { render } from "@captable/email";
-import { ShareDataRoomEmail } from "@captable/email/templates";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "share-data-room-email-job" });
export type ShareDataRoomEmailPayloadType = {
- to: string;
- dataRoom: string;
+ dataRoomId: string;
+ dataRoomName: string;
+ recipientName: string | null;
+ link: string;
+ email: string;
companyName: string;
senderName: string;
- link: string;
- recipientName?: string | null;
};
-const sendShareDataRoomEmail = async ({
- to,
- dataRoom,
- companyName,
- senderName,
- link,
- recipientName,
-}: ShareDataRoomEmailPayloadType) => {
+const sendShareDataRoomEmail = async (
+ payload: ShareDataRoomEmailPayloadType,
+) => {
+ log.info(
+ {
+ email: payload.email,
+ dataRoomId: payload.dataRoomId,
+ company: payload.companyName,
+ },
+ "Sending share data room email",
+ );
+
+ const { render } = await import("@captable/email");
+ const { ShareDataRoomEmail } = await import("@captable/email/templates");
+
const html = await render(
ShareDataRoomEmail({
- dataRoom,
- companyName,
- senderName,
- link,
- recipientName,
+ senderName: payload.senderName,
+ recipientName: payload.recipientName,
+ companyName: payload.companyName,
+ dataRoom: payload.dataRoomName,
+ link: payload.link,
}),
);
await sendMail({
- to: [to],
- subject: `${senderName} shared a data room with you`,
+ to: [payload.email],
+ subject: `${payload.senderName} shared a data room with you`,
html,
});
+
+ log.info(
+ {
+ email: payload.email,
+ dataRoomId: payload.dataRoomId,
+ company: payload.companyName,
+ },
+ "Share data room email sent successfully",
+ );
};
+export { sendShareDataRoomEmail };
+
export class ShareDataRoomEmailJob extends BaseJob {
readonly type = "email.share-data-room";
+ protected readonly options = {
+ maxAttempts: 3,
+ retryDelay: 1000,
+ priority: 2, // High priority for data room access
+ };
- async work(job: Job): Promise {
- await sendShareDataRoomEmail(job.data);
+ async work(payload: ShareDataRoomEmailPayloadType): Promise {
+ await sendShareDataRoomEmail(payload);
}
}
+
+// Create and register the job instance
+const shareDataRoomEmailJob = new ShareDataRoomEmailJob();
+shareDataRoomEmailJob.register();
+
+export { shareDataRoomEmailJob };
diff --git a/apps/captable/jobs/share-update-email.ts b/apps/captable/jobs/share-update-email.ts
index 9a3173840..74967f0b0 100644
--- a/apps/captable/jobs/share-update-email.ts
+++ b/apps/captable/jobs/share-update-email.ts
@@ -1,7 +1,8 @@
-import { env } from "@/env";
-import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
-import type { Job } from "pg-boss";
+import { logger } from "@captable/logger";
+import { BaseJob } from "@captable/queue";
+
+const log = logger.child({ module: "share-update-email-job" });
export type ShareUpdateEmailPayloadType = {
to: string;
@@ -13,6 +14,15 @@ export type ShareUpdateEmailPayloadType = {
};
const sendShareUpdateEmail = async (payload: ShareUpdateEmailPayloadType) => {
+ log.info(
+ {
+ to: payload.to,
+ company: payload.companyName,
+ update: payload.updateTitle,
+ },
+ "Sending share update email",
+ );
+
// Dynamic import to avoid build-time processing
const { render } = await import("@captable/email");
const { ShareUpdateEmail } = await import("@captable/email/templates");
@@ -32,12 +42,34 @@ const sendShareUpdateEmail = async (payload: ShareUpdateEmailPayloadType) => {
subject: `${payload.senderName} shared an update with you`,
html,
});
+
+ log.info(
+ {
+ to: payload.to,
+ company: payload.companyName,
+ update: payload.updateTitle,
+ },
+ "Share update email sent successfully",
+ );
};
+export { sendShareUpdateEmail };
+
export class ShareUpdateEmailJob extends BaseJob {
readonly type = "email.share-update";
+ protected readonly options = {
+ maxAttempts: 3,
+ retryDelay: 1000,
+ priority: 1,
+ };
- async work(job: Job): Promise {
- await sendShareUpdateEmail(job.data);
+ async work(payload: ShareUpdateEmailPayloadType): Promise {
+ await sendShareUpdateEmail(payload);
}
}
+
+// Create and register the job instance
+const shareUpdateEmailJob = new ShareUpdateEmailJob();
+shareUpdateEmailJob.register();
+
+export { shareUpdateEmailJob };
diff --git a/apps/captable/jobs/start.ts b/apps/captable/jobs/start.ts
index 9ed363376..90a239891 100644
--- a/apps/captable/jobs/start.ts
+++ b/apps/captable/jobs/start.ts
@@ -1,23 +1,10 @@
-import { AuthVerificationEmailJob } from "@/jobs/auth-verification-email";
-import { JobManager, boss } from "@/jobs/base";
-import { EsignConfirmationEmailJob } from "@/jobs/esign-confirmation-email";
-import { EsignEmailJob } from "@/jobs/esign-email";
-import { EsignPdfJob } from "@/jobs/esign-pdf";
-import { MemberInviteEmailJob } from "@/jobs/member-inivite-email";
-import { PasswordResetEmailJob } from "@/jobs/password-reset-email";
-import { ShareDataRoomEmailJob } from "@/jobs/share-data-room-email";
-import { ShareUpdateEmailJob } from "@/jobs/share-update-email";
+// Import all jobs to register them with the new queue system
+import "@/jobs";
-export async function startJobs() {
- const jobs = new JobManager(boss)
- .register(AuthVerificationEmailJob)
- .register(ShareUpdateEmailJob)
- .register(ShareDataRoomEmailJob)
- .register(MemberInviteEmailJob)
- .register(PasswordResetEmailJob)
- .register(EsignEmailJob)
- .register(EsignConfirmationEmailJob)
- .register(EsignPdfJob);
-
- await jobs.start();
+// Jobs are now auto-registered when imported
+// No need for manual job manager startup
+export function startJobs() {
+ // All jobs are automatically registered when the module is imported
+ // The Queue will process them via cron jobs
+ console.log("Jobs are auto-registered and ready for processing");
}
diff --git a/apps/captable/package.json b/apps/captable/package.json
index 70f5e9394..fc26a2eb9 100644
--- a/apps/captable/package.json
+++ b/apps/captable/package.json
@@ -9,7 +9,10 @@
"start": "next start",
"check-types": "tsc --noEmit",
"format": "biome format --write",
- "lint": "biome check"
+ "lint": "biome check",
+ "jobs": "bun run scripts/dev/jobs.ts",
+ "jobs:dev": "bun run scripts/dev/jobs.ts process --watch",
+ "test-jobs": "bun run scripts/dev/test-jobs.ts"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.812.0",
@@ -19,6 +22,7 @@
"@captable/auth": "*",
"@captable/db": "*",
"@captable/email": "*",
+ "@captable/queue": "*",
"@captable/rbac": "*",
"@captable/utils": "*",
"@hono/zod-openapi": "^0.19.6",
@@ -73,7 +77,6 @@
"nodemailer": "^7.0.3",
"papaparse": "^5.5.3",
"pdf-lib": "^1.17.1",
- "pg-boss": "^10.2.0",
"pushmodal": "^1.0.5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
diff --git a/apps/captable/scripts/dev/README.md b/apps/captable/scripts/dev/README.md
new file mode 100644
index 000000000..c032cfa6c
--- /dev/null
+++ b/apps/captable/scripts/dev/README.md
@@ -0,0 +1,76 @@
+# Development Scripts
+
+This directory contains development utilities for the Captable application.
+
+## Jobs Script (`jobs.ts`)
+
+Process jobs from the queue system.
+
+### Usage
+
+```bash
+# Process all pending jobs once
+bun run jobs
+
+# Process jobs continuously (watch mode)
+bun run jobs:dev
+
+# Show queue statistics
+bun run jobs stats
+
+# Clean up old completed jobs
+bun run jobs cleanup
+```
+
+### Watch Mode
+
+The watch mode (`--watch` flag) continuously monitors the job queue and processes jobs as they appear. This is useful during development when you want jobs to be processed automatically.
+
+- Checks for new jobs every 5 seconds when idle
+- Processes jobs immediately when found
+- Gracefully handles shutdown with Ctrl+C
+
+## Test Jobs Script (`test-jobs.ts`)
+
+Queue sample jobs for testing purposes.
+
+### Usage
+
+```bash
+# Queue all test email jobs
+bun run test-jobs
+
+# Queue specific job types
+bun run test-jobs password-reset
+bun run test-jobs member-invite
+bun run test-jobs auth-verification
+
+# Just show queue statistics
+bun run test-jobs stats
+```
+
+## Running Jobs with Development Server
+
+To run jobs automatically alongside your development server:
+
+```bash
+# Run everything including job processing
+bun dx
+```
+
+This will start:
+- Next.js development server
+- Database studio
+- Email development server
+- Job processor in watch mode
+
+## Job Types Available
+
+- `email.password-reset` - Password reset emails
+- `email.member-invite` - Member invitation emails
+- `email.auth-verify` - Account verification emails
+- `email.share-update` - Share update notifications
+- `email.share-data-room` - Data room sharing emails
+- `email.esign` - E-signature request emails
+- `email.esign-confirmation` - E-signature confirmation emails
+- `generate.esign-pdf` - PDF generation for e-signatures
\ No newline at end of file
diff --git a/apps/captable/scripts/dev/jobs.ts b/apps/captable/scripts/dev/jobs.ts
new file mode 100644
index 000000000..931b06839
--- /dev/null
+++ b/apps/captable/scripts/dev/jobs.ts
@@ -0,0 +1,177 @@
+#!/usr/bin/env bun
+
+import { logger } from "@captable/logger";
+import { cleanupJobs, getStats, processJobs } from "@captable/queue";
+
+// Import all jobs to register them
+import "@/jobs";
+
+const log = logger.child({ module: "dev-job-runner" });
+
+async function runJobs(_silent = false) {
+ try {
+ // Get current stats first
+ const initialStats = await getStats();
+
+ if (initialStats.pending === 0) {
+ // Only log occasionally when idle, not every time
+ return 0;
+ }
+
+ // Only log when we actually have jobs to process
+ log.info(initialStats, "Found jobs to process");
+
+ // Process jobs in batches
+ let totalProcessed = 0;
+ let batchCount = 0;
+ const maxBatches = 10;
+
+ while (batchCount < maxBatches) {
+ const processed = await processJobs(20);
+ totalProcessed += processed;
+ batchCount++;
+
+ if (processed === 0) {
+ break;
+ }
+
+ log.info({ processed, batch: batchCount }, "Batch completed");
+
+ // Small delay between batches
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ }
+
+ const finalStats = await getStats();
+ log.info(
+ {
+ totalProcessed,
+ batches: batchCount,
+ finalStats,
+ },
+ "Job processing completed",
+ );
+
+ return totalProcessed;
+ } catch (error) {
+ log.error({ error }, "Job processing failed");
+ throw error;
+ }
+}
+
+async function runJobsInWatchMode() {
+ log.info("π Starting job processor in watch mode...");
+ log.info("π€ Monitoring queue (quiet mode - only logs when jobs found)");
+ log.info("Press Ctrl+C to stop");
+
+ const POLL_INTERVAL = 5000; // Check every 5 seconds
+ const HEARTBEAT_INTERVAL = 60000; // Show heartbeat every minute
+
+ let isShuttingDown = false;
+ let lastHeartbeat = Date.now();
+ let totalChecks = 0;
+ let totalJobsProcessed = 0;
+ const startTime = Date.now();
+
+ // Handle graceful shutdown
+ process.on("SIGINT", () => {
+ log.info("Received SIGINT, shutting down gracefully...");
+ isShuttingDown = true;
+ });
+
+ process.on("SIGTERM", () => {
+ log.info("Received SIGTERM, shutting down gracefully...");
+ isShuttingDown = true;
+ });
+
+ while (!isShuttingDown) {
+ try {
+ totalChecks++;
+ const processed = await runJobs(true); // Silent mode for routine checks
+ totalJobsProcessed += processed;
+
+ // Show heartbeat periodically when idle
+ const now = Date.now();
+ if (now - lastHeartbeat >= HEARTBEAT_INTERVAL) {
+ const uptime = Math.round((now - startTime) / 1000 / 60);
+ log.info(
+ {
+ checks: totalChecks,
+ jobsProcessed: totalJobsProcessed,
+ uptime: `${uptime}m`,
+ },
+ "π Job processor active",
+ );
+ lastHeartbeat = now;
+ }
+
+ if (processed === 0) {
+ // No jobs processed, wait before checking again
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
+ } else {
+ // Jobs were processed, check again more quickly
+ await new Promise((resolve) => setTimeout(resolve, 1000));
+ }
+ } catch (error) {
+ log.error({ error }, "Error in watch mode, continuing...");
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
+ }
+ }
+
+ const finalUptime = Math.round((Date.now() - startTime) / 1000 / 60);
+ log.info(
+ {
+ totalChecks,
+ jobsProcessed: totalJobsProcessed,
+ uptime: `${finalUptime}m`,
+ },
+ "β
Job processor stopped",
+ );
+}
+
+async function cleanupOldJobs() {
+ try {
+ log.info("Cleaning up old jobs...");
+ const cleaned = await cleanupJobs(1); // Clean jobs older than 1 day in dev
+ log.info({ cleaned }, "Cleanup completed");
+ } catch (error) {
+ log.error({ error }, "Cleanup failed");
+ }
+}
+
+async function showStats() {
+ try {
+ const stats = await getStats();
+ console.log("\nπ Queue Statistics:");
+ console.table(stats);
+ } catch (error) {
+ log.error({ error }, "Failed to get stats");
+ }
+}
+
+// Parse command line arguments
+const args = process.argv.slice(2);
+const command = args[0] || "process";
+const isWatchMode = args.includes("--watch") || args.includes("-w");
+
+switch (command) {
+ case "process":
+ if (isWatchMode) {
+ runJobsInWatchMode();
+ } else {
+ runJobs().catch(() => process.exit(1));
+ }
+ break;
+ case "cleanup":
+ cleanupOldJobs();
+ break;
+ case "stats":
+ showStats();
+ break;
+ default:
+ console.log("Usage: bun run jobs [process|cleanup|stats] [--watch]");
+ console.log(" process - Process pending jobs (default)");
+ console.log(" cleanup - Clean up old completed jobs");
+ console.log(" stats - Show queue statistics");
+ console.log(" --watch - Run in watch mode (continuous processing)");
+ process.exit(1);
+}
diff --git a/apps/captable/scripts/dev/test-jobs.ts b/apps/captable/scripts/dev/test-jobs.ts
new file mode 100644
index 000000000..458596bd5
--- /dev/null
+++ b/apps/captable/scripts/dev/test-jobs.ts
@@ -0,0 +1,118 @@
+#!/usr/bin/env bun
+
+import { logger } from "@captable/logger";
+
+// Import all jobs to register them
+import {
+ authVerificationEmailJob,
+ esignConfirmationEmailJob,
+ esignEmailJob,
+ esignPdfJob,
+ getStats,
+ memberInviteEmailJob,
+ passwordResetEmailJob,
+ shareDataRoomEmailJob,
+ shareUpdateEmailJob,
+} from "@/jobs";
+
+const log = logger.child({ module: "test-jobs" });
+
+async function testPasswordResetEmail() {
+ try {
+ log.info("Testing password reset email job...");
+
+ const jobId = await passwordResetEmailJob.emit({
+ email: "test@example.com",
+ resetLink:
+ "https://cloud.captable.inc/auth/reset-password?token=test-token",
+ });
+
+ log.info({ jobId }, "Password reset email job queued");
+ } catch (error) {
+ log.error({ error }, "Failed to queue password reset email job");
+ }
+}
+
+async function testMemberInviteEmail() {
+ try {
+ log.info("Testing member invite email job...");
+
+ const jobId = await memberInviteEmailJob.emit({
+ email: "newmember@example.com",
+ invitedBy: "John Doe",
+ companyName: "Test Company",
+ inviteLink: "https://cloud.captable.inc/invite?token=test-invite-token",
+ });
+
+ log.info({ jobId }, "Member invite email job queued");
+ } catch (error) {
+ log.error({ error }, "Failed to queue member invite email job");
+ }
+}
+
+async function testAuthVerificationEmail() {
+ try {
+ log.info("Testing auth verification email job...");
+
+ const jobId = await authVerificationEmailJob.emit({
+ email: "user@example.com",
+ verifyLink:
+ "https://cloud.captable.inc/auth/verify?token=test-verification-token",
+ });
+
+ log.info({ jobId }, "Auth verification email job queued");
+ } catch (error) {
+ log.error({ error }, "Failed to queue auth verification email job");
+ }
+}
+
+async function showQueueStats() {
+ try {
+ const stats = await getStats();
+ console.log("\nπ Queue Statistics:");
+ console.table(stats);
+ } catch (error) {
+ log.error({ error }, "Failed to get queue stats");
+ }
+}
+
+async function testAllEmailJobs() {
+ log.info("π§ͺ Testing all email jobs...");
+
+ await testPasswordResetEmail();
+ await testMemberInviteEmail();
+ await testAuthVerificationEmail();
+
+ log.info("β
All test jobs queued!");
+ await showQueueStats();
+}
+
+// Parse command line arguments
+const command = process.argv[2] || "all";
+
+switch (command) {
+ case "password-reset":
+ testPasswordResetEmail().then(() => showQueueStats());
+ break;
+ case "member-invite":
+ testMemberInviteEmail().then(() => showQueueStats());
+ break;
+ case "auth-verification":
+ testAuthVerificationEmail().then(() => showQueueStats());
+ break;
+ case "stats":
+ showQueueStats();
+ break;
+ case "all":
+ testAllEmailJobs();
+ break;
+ default:
+ console.log("Usage: bun run test-jobs [job-type]");
+ console.log("Available job types:");
+ console.log(" password-reset - Test password reset email");
+ console.log(" member-invite - Test member invite email");
+ console.log(" auth-verification - Test auth verification email");
+ console.log(" stats - Show queue statistics");
+ console.log(" all - Test all email jobs (default)");
+ process.exit(1);
+}
diff --git a/apps/captable/trpc/routers/auth/procedure/forgot-password.ts b/apps/captable/trpc/routers/auth/procedure/forgot-password.ts
index a17b18a15..01d30b291 100644
--- a/apps/captable/trpc/routers/auth/procedure/forgot-password.ts
+++ b/apps/captable/trpc/routers/auth/procedure/forgot-password.ts
@@ -1,41 +1,35 @@
import { env } from "@/env";
-import { PasswordResetEmailJob } from "@/jobs/password-reset-email";
-import { generatePasswordResetToken } from "@/lib/token";
-import { getUserByEmail } from "@/server/user";
+import { passwordResetEmailJob } from "@/jobs";
import { withoutAuth } from "@/trpc/api/trpc";
+import { db, eq, users } from "@captable/db";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
+const forgotPasswordSchema = z.object({
+ email: z.string().email(),
+});
+
export const forgotPasswordProcedure = withoutAuth
- .input(z.string().email())
+ .input(forgotPasswordSchema)
.mutation(async ({ input }) => {
- const existingUser = await getUserByEmail(input);
-
- if (!existingUser) {
- throw new TRPCError({
- code: "BAD_REQUEST",
- message: "Email not found!",
- });
- }
+ const { email } = input;
- const passwordResetToken = await generatePasswordResetToken(input);
+ const existingUser = await db.query.users.findFirst({
+ where: eq(users.email, email),
+ });
- if (!passwordResetToken) {
+ if (!existingUser) {
throw new TRPCError({
- code: "INTERNAL_SERVER_ERROR",
- message: "Failed to generate password reset token",
+ code: "NOT_FOUND",
+ message: "User not found. Please check your email and try again.",
});
}
- const { email, token } = passwordResetToken;
-
- const resetLink = `${env.NEXT_PUBLIC_BASE_URL}/reset-password?token=${token}`;
+ const resetToken = crypto.randomUUID();
+ const resetLink = `${env.NEXT_PUBLIC_BASE_URL}/reset-password?token=${resetToken}&email=${encodeURIComponent(email)}`;
- await new PasswordResetEmailJob().emit({ email, resetLink });
+ // Emit password reset email job
+ await passwordResetEmailJob.emit({ email, resetLink });
- return {
- success: true,
- message:
- "To reset your password, please click the link sent to your email.",
- };
+ return { success: true };
});
diff --git a/apps/captable/trpc/routers/data-room-router/router.ts b/apps/captable/trpc/routers/data-room-router/router.ts
index f89ba75ac..4c40770f7 100644
--- a/apps/captable/trpc/routers/data-room-router/router.ts
+++ b/apps/captable/trpc/routers/data-room-router/router.ts
@@ -1,8 +1,5 @@
import { env } from "@/env";
-import {
- ShareDataRoomEmailJob,
- type ShareDataRoomEmailPayloadType,
-} from "@/jobs/share-data-room-email";
+import { shareDataRoomEmailJob } from "@/jobs";
import { generatePublicId } from "@/lib/common/id";
import { encode } from "@/lib/jwt";
import { ShareRecipientSchema } from "@/schema/contacts";
@@ -390,16 +387,17 @@ export const dataRoomRouter = createTRPCRouter({
const link = `${baseUrl}/data-rooms/${dataRoom.publicId}?token=${token}`;
- const payload: ShareDataRoomEmailPayloadType = {
- to: email,
- senderName: `${senderName}`,
- recipientName: recipient.name,
- companyName: company.name,
- dataRoom: dataRoom.name,
+ const payload = {
+ dataRoomId: dataRoomId,
+ dataRoomName: dataRoom.name,
+ recipientName: recipient.name || null,
link,
+ email,
+ companyName: company.name,
+ senderName: senderName || "Team",
};
- await new ShareDataRoomEmailJob().emit(payload);
+ await shareDataRoomEmailJob.emit(payload);
await db.transaction(async (tx) => {
await Audit.create(
diff --git a/apps/captable/trpc/routers/member-router/procedures/invite-member.ts b/apps/captable/trpc/routers/member-router/procedures/invite-member.ts
index efbd59e7d..368ee1a4d 100644
--- a/apps/captable/trpc/routers/member-router/procedures/invite-member.ts
+++ b/apps/captable/trpc/routers/member-router/procedures/invite-member.ts
@@ -1,4 +1,5 @@
import { env } from "@/env";
+import { memberInviteEmailJob } from "@/jobs";
import { MemberInviteEmailJob } from "@/jobs/member-inivite-email";
import { generatePasswordResetToken } from "@/lib/token";
import { Audit } from "@/server/audit";
@@ -227,13 +228,13 @@ export const inviteMemberProcedure = withAccessControl
const inviteLink = `${env.NEXT_PUBLIC_BASE_URL}/verify-member?token=${verificationToken}&passwordResetToken=${passwordResetTokenResult.token}`;
const payload = {
- invitedBy: user.name || "Someone",
- companyName: company.name,
- inviteLink,
email,
+ inviteLink,
+ companyName: company.name,
+ invitedBy: user.name || "Unknown",
};
- await new MemberInviteEmailJob().emit(payload);
+ await memberInviteEmailJob.emit(payload);
return { success: true };
});
diff --git a/apps/captable/trpc/routers/member-router/procedures/re-invite.ts b/apps/captable/trpc/routers/member-router/procedures/re-invite.ts
index 86d5620ec..94fdddbdc 100644
--- a/apps/captable/trpc/routers/member-router/procedures/re-invite.ts
+++ b/apps/captable/trpc/routers/member-router/procedures/re-invite.ts
@@ -1,5 +1,5 @@
import { env } from "@/env";
-import { MemberInviteEmailJob } from "@/jobs/member-inivite-email";
+import { memberInviteEmailJob } from "@/jobs";
import { generatePasswordResetToken } from "@/lib/token";
import { Audit } from "@/server/audit";
import { checkMembership } from "@/server/member";
@@ -148,13 +148,13 @@ export const reInviteProcedure = withAuth
const inviteLink = `${env.NEXT_PUBLIC_BASE_URL}/verify-member?token=${verificationToken}&passwordResetToken=${passwordResetToken}`;
const payload = {
- invitedBy: user.name || "Someone",
- companyName: company.name,
+ email,
inviteLink,
- email: email,
+ companyName: company.name,
+ invitedBy: user.name || "Unknown",
};
- await new MemberInviteEmailJob().emit(payload);
+ await memberInviteEmailJob.emit(payload);
return { success: true };
});
diff --git a/apps/captable/trpc/routers/template-field-router/procedures/add-fields.ts b/apps/captable/trpc/routers/template-field-router/procedures/add-fields.ts
index b03180071..c20002111 100644
--- a/apps/captable/trpc/routers/template-field-router/procedures/add-fields.ts
+++ b/apps/captable/trpc/routers/template-field-router/procedures/add-fields.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/prefer-for-of */
import { env } from "@/env";
-import { EsignEmailJob, type EsignEmailPayloadType } from "@/jobs/esign-email";
+import { esignEmailJob } from "@/jobs";
import { decode, encode } from "@/lib/jwt";
import { Audit } from "@/server/audit";
import { checkMembership } from "@/server/member";
@@ -55,7 +55,24 @@ export const addFieldProcedure = withAuth
try {
const user = ctx.session.user;
const { userAgent, requestIp } = ctx;
- const mails: EsignEmailPayloadType[] = [];
+ const mails: Array<{
+ signingLink: string;
+ recipient: {
+ id: string;
+ name: string | null | undefined;
+ email: string;
+ };
+ sender?: {
+ name: string | null | undefined;
+ email: string | null | undefined;
+ };
+ message?: string | null;
+ documentName?: string;
+ company?: {
+ name: string;
+ logo: string | null | undefined;
+ };
+ }> = [];
if (input.status === "COMPLETE" && (!user.email || !user.name)) {
return {
@@ -65,7 +82,7 @@ export const addFieldProcedure = withAuth
};
}
- const template = await db.transaction(async (tx) => {
+ const _template = await db.transaction(async (tx) => {
const { companyId } = await checkMembership({
tx,
session: ctx.session,
@@ -232,12 +249,7 @@ export const addFieldProcedure = withAuth
});
if (mails.length) {
- new EsignEmailJob().bulkEmit(
- mails.map((data) => ({
- data,
- singletonKey: `esign-notify-${template.id}-${data.recipient.id}`,
- })),
- );
+ await esignEmailJob.bulkEmit(mails);
}
return {
diff --git a/apps/captable/trpc/routers/update/procedures/share-update.ts b/apps/captable/trpc/routers/update/procedures/share-update.ts
index c665456fc..715d05f55 100644
--- a/apps/captable/trpc/routers/update/procedures/share-update.ts
+++ b/apps/captable/trpc/routers/update/procedures/share-update.ts
@@ -1,4 +1,5 @@
import { env } from "@/env";
+import { shareUpdateEmailJob } from "@/jobs";
import {
ShareUpdateEmailJob,
type ShareUpdateEmailPayloadType,
@@ -135,16 +136,16 @@ export const shareUpdateProcedure = withAuth
const link = `${baseUrl}/updates/${update.publicId}?token=${token}`;
- const payload: ShareUpdateEmailPayloadType = {
- to: email,
- senderName: `${senderName}`,
- recipientName: recipient.name ?? null,
+ const payload = {
+ to: recipient.email || recipient.value,
+ senderName: senderName || "Team",
+ recipientName: recipient.name || null,
companyName: update.companyName || "",
updateTitle: update.title,
- link,
+ link: link,
};
- await new ShareUpdateEmailJob().emit(payload);
+ await shareUpdateEmailJob.emit(payload);
}
};
diff --git a/apps/captable/vercel.json b/apps/captable/vercel.json
new file mode 100644
index 000000000..53db7b8ca
--- /dev/null
+++ b/apps/captable/vercel.json
@@ -0,0 +1,12 @@
+{
+ "crons": [
+ {
+ "path": "/api/cron/process-jobs",
+ "schedule": "* * * * *"
+ },
+ {
+ "path": "/api/cron/cleanup-jobs",
+ "schedule": "0 2 * * *"
+ }
+ ]
+}
diff --git a/bun.lock b/bun.lock
index d140aadb7..b497ddc65 100644
--- a/bun.lock
+++ b/bun.lock
@@ -26,6 +26,7 @@
"@captable/auth": "*",
"@captable/db": "*",
"@captable/email": "*",
+ "@captable/queue": "*",
"@captable/rbac": "*",
"@captable/utils": "*",
"@hono/zod-openapi": "^0.19.6",
@@ -80,7 +81,6 @@
"nodemailer": "^7.0.3",
"papaparse": "^5.5.3",
"pdf-lib": "^1.17.1",
- "pg-boss": "^10.2.0",
"pushmodal": "^1.0.5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@@ -192,6 +192,21 @@
"typescript": "^5.0.0",
},
},
+ "packages/queue": {
+ "name": "@captable/queue",
+ "dependencies": {
+ "@captable/db": "workspace:*",
+ "@captable/logger": "workspace:*",
+ "drizzle-orm": "^0.43.1",
+ },
+ "devDependencies": {
+ "@biomejs/biome": "1.9.4",
+ "@types/bun": "latest",
+ },
+ "peerDependencies": {
+ "typescript": "^5.0.0",
+ },
+ },
"packages/rbac": {
"name": "@captable/rbac",
"version": "1.0.0",
@@ -372,6 +387,8 @@
"@captable/logger": ["@captable/logger@workspace:packages/logger"],
+ "@captable/queue": ["@captable/queue@workspace:packages/queue"],
+
"@captable/rbac": ["@captable/rbac@workspace:packages/rbac"],
"@captable/utils": ["@captable/utils@workspace:packages/utils"],
@@ -1408,8 +1425,6 @@
"crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="],
- "cron-parser": ["cron-parser@4.9.0", "", { "dependencies": { "luxon": "^3.2.1" } }, "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q=="],
-
"cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
@@ -1842,8 +1857,6 @@
"lru-cache": ["lru-cache@11.1.0", "", {}, "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A=="],
- "luxon": ["luxon@3.6.1", "", {}, "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ=="],
-
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
"make-cancellable-promise": ["make-cancellable-promise@1.3.2", "", {}, "sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww=="],
@@ -2074,8 +2087,6 @@
"pg": ["pg@8.16.0", "", { "dependencies": { "pg-connection-string": "^2.9.0", "pg-pool": "^3.10.0", "pg-protocol": "^1.10.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.5" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-7SKfdvP8CTNXjMUzfcVTaI+TDzBEeaUnVwiVGZQD1Hh33Kpev7liQba9uLd4CfN8r9mCVsD0JIpq03+Unpz+kg=="],
- "pg-boss": ["pg-boss@10.2.0", "", { "dependencies": { "cron-parser": "^4.9.0", "pg": "^8.14.1", "serialize-error": "^8.1.0" } }, "sha512-5izR07hpNY6LktlidFmvgK9LGErdUeV+vfjMOTLP01FV9tcGpYu6nZitXU6bYl6nOGgoegzhahlSlAgi4PXpEA=="],
-
"pg-cloudflare": ["pg-cloudflare@1.2.5", "", {}, "sha512-OOX22Vt0vOSRrdoUPKJ8Wi2OpE/o/h9T8X1s4qSkCedbNah9ei2W2765be8iMVxQUsvgT7zIAT2eIa9fs5+vtg=="],
"pg-connection-string": ["pg-connection-string@2.9.0", "", {}, "sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ=="],
@@ -2316,8 +2327,6 @@
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
- "serialize-error": ["serialize-error@8.1.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ=="],
-
"serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="],
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
@@ -2732,8 +2741,6 @@
"restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
- "serialize-error/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="],
-
"socket.io/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
"socket.io-adapter/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
diff --git a/package.json b/package.json
index 44159d4d5..6e78223a0 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
"email:dev": "bun run --cwd packages/email dev --port 3001",
"// Parallel execution scripts": "",
- "dx": "dotenv -- turbo run dev db:studio email:dev --parallel",
+ "dx": "dotenv -- turbo run dev db:studio email:dev jobs:dev --parallel",
"lint:all": "dotenv -- turbo run lint check-types format --parallel",
"clean": "dotenv -- turbo run clean && rm -rf node_modules/.cache",
"fresh": "bun run clean && bun install && bun run db:generate"
diff --git a/packages/db/migrations/0003_small_emma_frost.sql b/packages/db/migrations/0003_small_emma_frost.sql
new file mode 100644
index 000000000..d350ccbc4
--- /dev/null
+++ b/packages/db/migrations/0003_small_emma_frost.sql
@@ -0,0 +1,16 @@
+CREATE TABLE "cap_job_queue" (
+ "id" varchar(128) PRIMARY KEY NOT NULL,
+ "type" varchar(100) NOT NULL,
+ "payload" json NOT NULL,
+ "status" varchar(20) DEFAULT 'pending' NOT NULL,
+ "attempts" integer DEFAULT 0 NOT NULL,
+ "max_attempts" integer DEFAULT 3 NOT NULL,
+ "priority" integer DEFAULT 0 NOT NULL,
+ "scheduled_for" timestamp DEFAULT now() NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ "processed_at" timestamp,
+ "failed_at" timestamp,
+ "error" varchar(1000),
+ "retry_delay" integer DEFAULT 1000 NOT NULL
+);
diff --git a/packages/db/migrations/0004_moaning_red_hulk.sql b/packages/db/migrations/0004_moaning_red_hulk.sql
new file mode 100644
index 000000000..edc62aa47
--- /dev/null
+++ b/packages/db/migrations/0004_moaning_red_hulk.sql
@@ -0,0 +1,6 @@
+CREATE INDEX "job_processing_idx" ON "cap_job_queue" USING btree ("status","scheduled_for","attempts");--> statement-breakpoint
+CREATE INDEX "priority_ordering_idx" ON "cap_job_queue" USING btree ("priority" DESC NULLS LAST,"created_at");--> statement-breakpoint
+CREATE INDEX "cleanup_idx" ON "cap_job_queue" USING btree ("status","created_at");--> statement-breakpoint
+CREATE INDEX "status_idx" ON "cap_job_queue" USING btree ("status");--> statement-breakpoint
+CREATE INDEX "type_idx" ON "cap_job_queue" USING btree ("type");--> statement-breakpoint
+CREATE INDEX "failed_jobs_idx" ON "cap_job_queue" USING btree ("status","failed_at" DESC NULLS LAST);
\ No newline at end of file
diff --git a/packages/db/migrations/meta/0003_snapshot.json b/packages/db/migrations/meta/0003_snapshot.json
new file mode 100644
index 000000000..9962bbc86
--- /dev/null
+++ b/packages/db/migrations/meta/0003_snapshot.json
@@ -0,0 +1,4918 @@
+{
+ "id": "7ed962da-2914-4589-a951-0df9c3bd1ec4",
+ "prevId": "5dc53db0-8120-4c40-a770-a68445ff1ae4",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.cap_better_auth_accounts": {
+ "name": "cap_better_auth_accounts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_id": {
+ "name": "provider_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token_expires_at": {
+ "name": "access_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token_expires_at": {
+ "name": "refresh_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cap_better_auth_accounts_user_id_cap_better_auth_users_id_fk": {
+ "name": "cap_better_auth_accounts_user_id_cap_better_auth_users_id_fk",
+ "tableFrom": "cap_better_auth_accounts",
+ "tableTo": "cap_better_auth_users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_better_auth_sessions": {
+ "name": "cap_better_auth_sessions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ip_address": {
+ "name": "ip_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cap_better_auth_sessions_user_id_cap_better_auth_users_id_fk": {
+ "name": "cap_better_auth_sessions_user_id_cap_better_auth_users_id_fk",
+ "tableFrom": "cap_better_auth_sessions",
+ "tableTo": "cap_better_auth_users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_better_auth_sessions_token_unique": {
+ "name": "cap_better_auth_sessions_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_better_auth_users": {
+ "name": "cap_better_auth_users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_better_auth_users_email_unique": {
+ "name": "cap_better_auth_users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": ["email"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_better_auth_verifications": {
+ "name": "cap_better_auth_verifications",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_accounts": {
+ "name": "cap_accounts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_account_id": {
+ "name": "provider_account_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "token_type": {
+ "name": "token_type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "session_state": {
+ "name": "session_state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "accounts_user_id_idx": {
+ "name": "accounts_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "accounts_provider_provider_account_id_idx": {
+ "name": "accounts_provider_provider_account_id_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "provider_account_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_sessions": {
+ "name": "cap_sessions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "session_token": {
+ "name": "session_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "sessions_session_token_idx": {
+ "name": "sessions_session_token_idx",
+ "columns": [
+ {
+ "expression": "session_token",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "sessions_user_id_idx": {
+ "name": "sessions_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_users": {
+ "name": "cap_users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "image": {
+ "name": "image",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_signed_in": {
+ "name": "last_signed_in",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "identity_provider": {
+ "name": "identity_provider",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "users_email_idx": {
+ "name": "users_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_passkeys": {
+ "name": "cap_passkeys",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "last_used_at": {
+ "name": "last_used_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "credential_id": {
+ "name": "credential_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "credential_public_key": {
+ "name": "credential_public_key",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "counter": {
+ "name": "counter",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "credential_device_type": {
+ "name": "credential_device_type",
+ "type": "CredentialDeviceTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "credential_backed_up": {
+ "name": "credential_backed_up",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "transports": {
+ "name": "transports",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "passkeys_user_id_idx": {
+ "name": "passkeys_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_passkey_verification_tokens": {
+ "name": "cap_passkey_verification_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_passkey_verification_tokens_token_unique": {
+ "name": "cap_passkey_verification_tokens_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_password_reset_tokens": {
+ "name": "cap_password_reset_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "password_reset_tokens_email_token_idx": {
+ "name": "password_reset_tokens_email_token_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "token",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_password_reset_tokens_token_unique": {
+ "name": "cap_password_reset_tokens_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_verification_tokens": {
+ "name": "cap_verification_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "secondary_id": {
+ "name": "secondary_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "verification_tokens_identifier_token_idx": {
+ "name": "verification_tokens_identifier_token_idx",
+ "columns": [
+ {
+ "expression": "identifier",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "token",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "verification_tokens_user_id_idx": {
+ "name": "verification_tokens_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_verification_tokens_secondary_id_unique": {
+ "name": "cap_verification_tokens_secondary_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["secondary_id"]
+ },
+ "cap_verification_tokens_token_unique": {
+ "name": "cap_verification_tokens_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_companies": {
+ "name": "cap_companies",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "logo": {
+ "name": "logo",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "website": {
+ "name": "website",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "incorporation_type": {
+ "name": "incorporation_type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "incorporation_date": {
+ "name": "incorporation_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "incorporation_country": {
+ "name": "incorporation_country",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "incorporation_state": {
+ "name": "incorporation_state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "street_address": {
+ "name": "street_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "city": {
+ "name": "city",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "state": {
+ "name": "state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "zipcode": {
+ "name": "zipcode",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "country": {
+ "name": "country",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "companies_public_id_unique": {
+ "name": "companies_public_id_unique",
+ "columns": [
+ {
+ "expression": "public_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_companies_public_id_unique": {
+ "name": "cap_companies_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_bank_accounts": {
+ "name": "cap_bank_accounts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "beneficiary_name": {
+ "name": "beneficiary_name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "beneficiary_address": {
+ "name": "beneficiary_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bank_name": {
+ "name": "bank_name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bank_address": {
+ "name": "bank_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "account_number": {
+ "name": "account_number",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "routing_number": {
+ "name": "routing_number",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "account_type": {
+ "name": "account_type",
+ "type": "BankAccountTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CHECKING'"
+ },
+ "swift_code": {
+ "name": "swift_code",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "primary": {
+ "name": "primary",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "bank_accounts_company_id_idx": {
+ "name": "bank_accounts_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_custom_roles": {
+ "name": "cap_custom_roles",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "permissions": {
+ "name": "permissions",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "custom_roles_company_id_idx": {
+ "name": "custom_roles_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_members": {
+ "name": "cap_members",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "MemberStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'PENDING'"
+ },
+ "is_onboarded": {
+ "name": "is_onboarded",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "role": {
+ "name": "role",
+ "type": "Roles",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "'ADMIN'"
+ },
+ "work_email": {
+ "name": "work_email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_accessed": {
+ "name": "last_accessed",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "custom_role_id": {
+ "name": "custom_role_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "members_company_id_idx": {
+ "name": "members_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_status_idx": {
+ "name": "members_status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_user_id_idx": {
+ "name": "members_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_custom_role_id_idx": {
+ "name": "members_custom_role_id_idx",
+ "columns": [
+ {
+ "expression": "custom_role_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_company_id_user_id_unique": {
+ "name": "members_company_id_user_id_unique",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_stakeholders": {
+ "name": "cap_stakeholders",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "institution_name": {
+ "name": "institution_name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_type": {
+ "name": "stakeholder_type",
+ "type": "StakeholderTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'INDIVIDUAL'"
+ },
+ "current_relationship": {
+ "name": "current_relationship",
+ "type": "StakeholderRelationshipEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'EMPLOYEE'"
+ },
+ "tax_id": {
+ "name": "tax_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "street_address": {
+ "name": "street_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "city": {
+ "name": "city",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "state": {
+ "name": "state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "zipcode": {
+ "name": "zipcode",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "country": {
+ "name": "country",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'US'"
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "stakeholders_company_id_idx": {
+ "name": "stakeholders_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_stakeholders_email_unique": {
+ "name": "cap_stakeholders_email_unique",
+ "nullsNotDistinct": false,
+ "columns": ["email"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_audits": {
+ "name": "cap_audits",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "summary": {
+ "name": "summary",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "action": {
+ "name": "action",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "occurred_at": {
+ "name": "occurred_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actor": {
+ "name": "actor",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "target": {
+ "name": "target",
+ "type": "jsonb[]",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "context": {
+ "name": "context",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "audits_company_id_idx": {
+ "name": "audits_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_share_classes": {
+ "name": "cap_share_classes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "idx": {
+ "name": "idx",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "class_type": {
+ "name": "class_type",
+ "type": "ShareTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'COMMON'"
+ },
+ "prefix": {
+ "name": "prefix",
+ "type": "SharePrefixEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CS'"
+ },
+ "initial_shares_authorized": {
+ "name": "initial_shares_authorized",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stockholder_approval_date": {
+ "name": "stockholder_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "votes_per_share": {
+ "name": "votes_per_share",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "par_value": {
+ "name": "par_value",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "price_per_share": {
+ "name": "price_per_share",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "seniority": {
+ "name": "seniority",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "conversion_rights": {
+ "name": "conversion_rights",
+ "type": "ConversionRightsEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CONVERTS_TO_FUTURE_ROUND'"
+ },
+ "converts_to_share_class_id": {
+ "name": "converts_to_share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "liquidation_preference_multiple": {
+ "name": "liquidation_preference_multiple",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participation_cap_multiple": {
+ "name": "participation_cap_multiple",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "share_classes_company_id_idx": {
+ "name": "share_classes_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "share_classes_company_id_idx_unique": {
+ "name": "share_classes_company_id_idx_unique",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "idx",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_equity_plans": {
+ "name": "cap_equity_plans",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plan_effective_date": {
+ "name": "plan_effective_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "initial_shares_reserved": {
+ "name": "initial_shares_reserved",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "default_cancellaton_behavior": {
+ "name": "default_cancellaton_behavior",
+ "type": "CancellationBehaviorEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "comments": {
+ "name": "comments",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_class_id": {
+ "name": "share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "equity_plans_share_class_id_idx": {
+ "name": "equity_plans_share_class_id_idx",
+ "columns": [
+ {
+ "expression": "share_class_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "equity_plans_company_id_idx": {
+ "name": "equity_plans_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_buckets": {
+ "name": "cap_buckets",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "key": {
+ "name": "key",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "mime_type": {
+ "name": "mime_type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "size": {
+ "name": "size",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tags": {
+ "name": "tags",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_document_shares": {
+ "name": "cap_document_shares",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "link": {
+ "name": "link",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "link_expires_at": {
+ "name": "link_expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "recipients": {
+ "name": "recipients",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'"
+ },
+ "email_protected": {
+ "name": "email_protected",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "document_id": {
+ "name": "document_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "document_shares_document_id_idx": {
+ "name": "document_shares_document_id_idx",
+ "columns": [
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_documents": {
+ "name": "cap_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bucket_id": {
+ "name": "bucket_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "uploader_id": {
+ "name": "uploader_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_id": {
+ "name": "share_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "option_id": {
+ "name": "option_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "safe_id": {
+ "name": "safe_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "convertible_note_id": {
+ "name": "convertible_note_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "documents_bucket_id_idx": {
+ "name": "documents_bucket_id_idx",
+ "columns": [
+ {
+ "expression": "bucket_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_uploader_id_idx": {
+ "name": "documents_uploader_id_idx",
+ "columns": [
+ {
+ "expression": "uploader_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_company_id_idx": {
+ "name": "documents_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_share_id_idx": {
+ "name": "documents_share_id_idx",
+ "columns": [
+ {
+ "expression": "share_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_option_id_idx": {
+ "name": "documents_option_id_idx",
+ "columns": [
+ {
+ "expression": "option_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_safe_id_idx": {
+ "name": "documents_safe_id_idx",
+ "columns": [
+ {
+ "expression": "safe_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_convertible_note_id_idx": {
+ "name": "documents_convertible_note_id_idx",
+ "columns": [
+ {
+ "expression": "convertible_note_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_documents_public_id_unique": {
+ "name": "cap_documents_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_data_room_documents": {
+ "name": "cap_data_room_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "data_room_id": {
+ "name": "data_room_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "document_id": {
+ "name": "document_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "data_room_documents_data_room_id_idx": {
+ "name": "data_room_documents_data_room_id_idx",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_documents_document_id_idx": {
+ "name": "data_room_documents_document_id_idx",
+ "columns": [
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_documents_data_room_id_document_id_unique": {
+ "name": "data_room_documents_data_room_id_document_id_unique",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_data_room_recipients": {
+ "name": "cap_data_room_recipients",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "data_room_id": {
+ "name": "data_room_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "member_id": {
+ "name": "member_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "data_room_recipients_id_data_room_id_idx": {
+ "name": "data_room_recipients_id_data_room_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_member_id_idx": {
+ "name": "data_room_recipients_member_id_idx",
+ "columns": [
+ {
+ "expression": "member_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_data_room_id_idx": {
+ "name": "data_room_recipients_data_room_id_idx",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_stakeholder_id_idx": {
+ "name": "data_room_recipients_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_data_room_id_email_unique": {
+ "name": "data_room_recipients_data_room_id_email_unique",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_data_rooms": {
+ "name": "cap_data_rooms",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public": {
+ "name": "public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "data_rooms_public_id_idx": {
+ "name": "data_rooms_public_id_idx",
+ "columns": [
+ {
+ "expression": "public_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_rooms_company_id_idx": {
+ "name": "data_rooms_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_rooms_company_id_name_unique": {
+ "name": "data_rooms_company_id_name_unique",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_data_rooms_public_id_unique": {
+ "name": "cap_data_rooms_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_update_recipients": {
+ "name": "cap_update_recipients",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "update_id": {
+ "name": "update_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "member_id": {
+ "name": "member_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "update_recipients_id_update_id_idx": {
+ "name": "update_recipients_id_update_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "update_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_member_id_idx": {
+ "name": "update_recipients_member_id_idx",
+ "columns": [
+ {
+ "expression": "member_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_update_id_idx": {
+ "name": "update_recipients_update_id_idx",
+ "columns": [
+ {
+ "expression": "update_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_stakeholder_id_idx": {
+ "name": "update_recipients_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_update_id_email_unique": {
+ "name": "update_recipients_update_id_email_unique",
+ "columns": [
+ {
+ "expression": "update_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_esign_recipients": {
+ "name": "cap_esign_recipients",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "EsignRecipientStatus",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'PENDING'"
+ },
+ "member_id": {
+ "name": "member_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "esign_recipients_member_id_idx": {
+ "name": "esign_recipients_member_id_idx",
+ "columns": [
+ {
+ "expression": "member_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "esign_recipients_template_id_idx": {
+ "name": "esign_recipients_template_id_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_template_fields": {
+ "name": "cap_template_fields",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "FieldTypes",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'TEXT'"
+ },
+ "default_value": {
+ "name": "default_value",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "read_only": {
+ "name": "read_only",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "required": {
+ "name": "required",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "prefilled_value": {
+ "name": "prefilled_value",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "top": {
+ "name": "top",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "left": {
+ "name": "left",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "width": {
+ "name": "width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "height": {
+ "name": "height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "recipient_id": {
+ "name": "recipient_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "viewport_height": {
+ "name": "viewport_height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "viewport_width": {
+ "name": "viewport_width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "page": {
+ "name": "page",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "meta": {
+ "name": "meta",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "template_fields_template_id_idx": {
+ "name": "template_fields_template_id_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "template_fields_recipient_id_idx": {
+ "name": "template_fields_recipient_id_idx",
+ "columns": [
+ {
+ "expression": "recipient_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_templates": {
+ "name": "cap_templates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "TemplateStatus",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "ordered_delivery": {
+ "name": "ordered_delivery",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "message": {
+ "name": "message",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "bucket_id": {
+ "name": "bucket_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "uploader_id": {
+ "name": "uploader_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "completed_on": {
+ "name": "completed_on",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "templates_bucket_id_idx": {
+ "name": "templates_bucket_id_idx",
+ "columns": [
+ {
+ "expression": "bucket_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "templates_uploader_id_idx": {
+ "name": "templates_uploader_id_idx",
+ "columns": [
+ {
+ "expression": "uploader_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "templates_company_id_idx": {
+ "name": "templates_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_shares": {
+ "name": "cap_shares",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "SecuritiesStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "certificate_id": {
+ "name": "certificate_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "price_per_share": {
+ "name": "price_per_share",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "capital_contribution": {
+ "name": "capital_contribution",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ip_contribution": {
+ "name": "ip_contribution",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "debt_cancelled": {
+ "name": "debt_cancelled",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "other_contributions": {
+ "name": "other_contributions",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cliff_years": {
+ "name": "cliff_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "vesting_years": {
+ "name": "vesting_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "company_legends": {
+ "name": "company_legends",
+ "type": "ShareLegendsEnum[]",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'"
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rule_144_date": {
+ "name": "rule_144_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "vesting_start_date": {
+ "name": "vesting_start_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_class_id": {
+ "name": "share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "shares_company_id_idx": {
+ "name": "shares_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "shares_stakeholder_id_idx": {
+ "name": "shares_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "shares_share_class_id_idx": {
+ "name": "shares_share_class_id_idx",
+ "columns": [
+ {
+ "expression": "share_class_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_options": {
+ "name": "cap_options",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "grant_id": {
+ "name": "grant_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "exercise_price": {
+ "name": "exercise_price",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "OptionTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "OptionStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "cliff_years": {
+ "name": "cliff_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "vesting_years": {
+ "name": "vesting_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expiration_date": {
+ "name": "expiration_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "vesting_start_date": {
+ "name": "vesting_start_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rule_144_date": {
+ "name": "rule_144_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "equity_plan_id": {
+ "name": "equity_plan_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "options_company_id_idx": {
+ "name": "options_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "options_equity_plan_id_idx": {
+ "name": "options_equity_plan_id_idx",
+ "columns": [
+ {
+ "expression": "equity_plan_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "options_stakeholder_id_idx": {
+ "name": "options_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_investments": {
+ "name": "cap_investments",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "amount": {
+ "name": "amount",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "shares": {
+ "name": "shares",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "date": {
+ "name": "date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "comments": {
+ "name": "comments",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "share_class_id": {
+ "name": "share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "investments_company_id_idx": {
+ "name": "investments_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "investments_share_class_id_idx": {
+ "name": "investments_share_class_id_idx",
+ "columns": [
+ {
+ "expression": "share_class_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "investments_stakeholder_id_idx": {
+ "name": "investments_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_safes": {
+ "name": "cap_safes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "SafeTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'POST_MONEY'"
+ },
+ "status": {
+ "name": "status",
+ "type": "SafeStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "capital": {
+ "name": "capital",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "safe_template": {
+ "name": "safe_template",
+ "type": "SafeTemplateEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "safe_id": {
+ "name": "safe_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valuation_cap": {
+ "name": "valuation_cap",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "discount_rate": {
+ "name": "discount_rate",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "mfn": {
+ "name": "mfn",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "pro_rata": {
+ "name": "pro_rata",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "additional_terms": {
+ "name": "additional_terms",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "safes_company_id_idx": {
+ "name": "safes_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "safes_stakeholder_id_idx": {
+ "name": "safes_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_convertible_notes": {
+ "name": "cap_convertible_notes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "ConvertibleStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "type": {
+ "name": "type",
+ "type": "ConvertibleTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'NOTE'"
+ },
+ "capital": {
+ "name": "capital",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "conversion_cap": {
+ "name": "conversion_cap",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "discount_rate": {
+ "name": "discount_rate",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "mfn": {
+ "name": "mfn",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "additional_terms": {
+ "name": "additional_terms",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_rate": {
+ "name": "interest_rate",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_method": {
+ "name": "interest_method",
+ "type": "ConvertibleInterestMethodEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_accrual": {
+ "name": "interest_accrual",
+ "type": "ConvertibleInterestAccrualEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_payment_schedule": {
+ "name": "interest_payment_schedule",
+ "type": "ConvertibleInterestPaymentScheduleEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "convertible_notes_company_id_idx": {
+ "name": "convertible_notes_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "convertible_notes_stakeholder_id_idx": {
+ "name": "convertible_notes_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_esign_audits": {
+ "name": "cap_esign_audits",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "recipient_id": {
+ "name": "recipient_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "action": {
+ "name": "action",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ip": {
+ "name": "ip",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "location": {
+ "name": "location",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "summary": {
+ "name": "summary",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "occurred_at": {
+ "name": "occurred_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "esign_audits_company_id_idx": {
+ "name": "esign_audits_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "esign_audits_template_id_idx": {
+ "name": "esign_audits_template_id_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "esign_audits_recipient_id_idx": {
+ "name": "esign_audits_recipient_id_idx",
+ "columns": [
+ {
+ "expression": "recipient_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_updates": {
+ "name": "cap_updates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content": {
+ "name": "content",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "html": {
+ "name": "html",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public": {
+ "name": "public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "status": {
+ "name": "status",
+ "type": "UpdateStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "author_id": {
+ "name": "author_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "updates_public_id_idx": {
+ "name": "updates_public_id_idx",
+ "columns": [
+ {
+ "expression": "public_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "updates_author_id_idx": {
+ "name": "updates_author_id_idx",
+ "columns": [
+ {
+ "expression": "author_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "updates_company_id_idx": {
+ "name": "updates_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_updates_public_id_unique": {
+ "name": "cap_updates_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_customers": {
+ "name": "cap_billing_customers",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "billing_customers_company_id_idx": {
+ "name": "billing_customers_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_prices": {
+ "name": "cap_billing_prices",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "product_id": {
+ "name": "product_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "unit_amount": {
+ "name": "unit_amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "currency": {
+ "name": "currency",
+ "type": "varchar(3)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "PricingType",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "interval": {
+ "name": "interval",
+ "type": "PricingPlanInterval",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interval_count": {
+ "name": "interval_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trial_period_days": {
+ "name": "trial_period_days",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "billing_prices_product_id_idx": {
+ "name": "billing_prices_product_id_idx",
+ "columns": [
+ {
+ "expression": "product_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_products": {
+ "name": "cap_billing_products",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_subscriptions": {
+ "name": "cap_billing_subscriptions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "price_id": {
+ "name": "price_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "SubscriptionStatus",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancel_at_period_end": {
+ "name": "cancel_at_period_end",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created": {
+ "name": "created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "current_period_start": {
+ "name": "current_period_start",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "current_period_end": {
+ "name": "current_period_end",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ended_at": {
+ "name": "ended_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cancel_at": {
+ "name": "cancel_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "canceled_at": {
+ "name": "canceled_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trial_start": {
+ "name": "trial_start",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trial_end": {
+ "name": "trial_end",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "billing_subscriptions_price_id_idx": {
+ "name": "billing_subscriptions_price_id_idx",
+ "columns": [
+ {
+ "expression": "price_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "billing_subscriptions_customer_id_idx": {
+ "name": "billing_subscriptions_customer_id_idx",
+ "columns": [
+ {
+ "expression": "customer_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_access_tokens": {
+ "name": "cap_access_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "client_secret": {
+ "name": "client_secret",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type_enum": {
+ "name": "type_enum",
+ "type": "AccessTokenType",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'api'"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_used": {
+ "name": "last_used",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "access_tokens_user_id_idx": {
+ "name": "access_tokens_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "access_tokens_type_enum_client_id_idx": {
+ "name": "access_tokens_type_enum_client_id_idx",
+ "columns": [
+ {
+ "expression": "type_enum",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_job_queue": {
+ "name": "cap_job_queue",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(128)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "payload": {
+ "name": "payload",
+ "type": "json",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "varchar(20)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "attempts": {
+ "name": "attempts",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "max_attempts": {
+ "name": "max_attempts",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 3
+ },
+ "priority": {
+ "name": "priority",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "scheduled_for": {
+ "name": "scheduled_for",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "processed_at": {
+ "name": "processed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "failed_at": {
+ "name": "failed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "varchar(1000)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retry_delay": {
+ "name": "retry_delay",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 1000
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.AccessTokenType": {
+ "name": "AccessTokenType",
+ "schema": "public",
+ "values": ["sig", "doc", "api", "upd"]
+ },
+ "public.AuditAction": {
+ "name": "AuditAction",
+ "schema": "public",
+ "values": ["CREATE", "UPDATE", "DELETE"]
+ },
+ "public.BankAccountTypeEnum": {
+ "name": "BankAccountTypeEnum",
+ "schema": "public",
+ "values": ["CHECKING", "SAVINGS"]
+ },
+ "public.CancellationBehaviorEnum": {
+ "name": "CancellationBehaviorEnum",
+ "schema": "public",
+ "values": [
+ "RETIRE",
+ "RETURN_TO_POOL",
+ "HOLD_AS_CAPITAL_STOCK",
+ "DEFINED_PER_PLAN_SECURITY"
+ ]
+ },
+ "public.ConversionRightsEnum": {
+ "name": "ConversionRightsEnum",
+ "schema": "public",
+ "values": ["CONVERTS_TO_FUTURE_ROUND", "CONVERTS_TO_SHARE_CLASS_ID"]
+ },
+ "public.ConvertibleInterestAccrualEnum": {
+ "name": "ConvertibleInterestAccrualEnum",
+ "schema": "public",
+ "values": [
+ "DAILY",
+ "MONTHLY",
+ "SEMI_ANNUALLY",
+ "ANNUALLY",
+ "YEARLY",
+ "CONTINUOUSLY"
+ ]
+ },
+ "public.ConvertibleInterestMethodEnum": {
+ "name": "ConvertibleInterestMethodEnum",
+ "schema": "public",
+ "values": ["SIMPLE", "COMPOUND"]
+ },
+ "public.ConvertibleInterestPaymentScheduleEnum": {
+ "name": "ConvertibleInterestPaymentScheduleEnum",
+ "schema": "public",
+ "values": ["DEFERRED", "PAY_AT_MATURITY"]
+ },
+ "public.ConvertibleStatusEnum": {
+ "name": "ConvertibleStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "ACTIVE", "PENDING", "EXPIRED", "CANCELLED"]
+ },
+ "public.ConvertibleTypeEnum": {
+ "name": "ConvertibleTypeEnum",
+ "schema": "public",
+ "values": ["CCD", "OCD", "NOTE"]
+ },
+ "public.CredentialDeviceTypeEnum": {
+ "name": "CredentialDeviceTypeEnum",
+ "schema": "public",
+ "values": ["SINGLE_DEVICE", "MULTI_DEVICE"]
+ },
+ "public.EsignRecipientStatus": {
+ "name": "EsignRecipientStatus",
+ "schema": "public",
+ "values": ["SENT", "SIGNED", "PENDING"]
+ },
+ "public.FieldTypes": {
+ "name": "FieldTypes",
+ "schema": "public",
+ "values": [
+ "TEXT",
+ "RADIO",
+ "EMAIL",
+ "DATE",
+ "DATETIME",
+ "TEXTAREA",
+ "CHECKBOX",
+ "SIGNATURE",
+ "SELECT"
+ ]
+ },
+ "public.MemberStatusEnum": {
+ "name": "MemberStatusEnum",
+ "schema": "public",
+ "values": ["ACTIVE", "INACTIVE", "PENDING"]
+ },
+ "public.OptionStatusEnum": {
+ "name": "OptionStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "ACTIVE", "EXERCISED", "EXPIRED", "CANCELLED"]
+ },
+ "public.OptionTypeEnum": {
+ "name": "OptionTypeEnum",
+ "schema": "public",
+ "values": ["ISO", "NSO", "RSU"]
+ },
+ "public.PricingPlanInterval": {
+ "name": "PricingPlanInterval",
+ "schema": "public",
+ "values": ["day", "week", "month", "year"]
+ },
+ "public.PricingType": {
+ "name": "PricingType",
+ "schema": "public",
+ "values": ["one_time", "recurring"]
+ },
+ "public.Roles": {
+ "name": "Roles",
+ "schema": "public",
+ "values": ["ADMIN", "CUSTOM"]
+ },
+ "public.SafeStatusEnum": {
+ "name": "SafeStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "ACTIVE", "PENDING", "EXPIRED", "CANCELLED"]
+ },
+ "public.SafeTemplateEnum": {
+ "name": "SafeTemplateEnum",
+ "schema": "public",
+ "values": [
+ "POST_MONEY_CAP",
+ "POST_MONEY_DISCOUNT",
+ "POST_MONEY_MFN",
+ "POST_MONEY_CAP_WITH_PRO_RATA",
+ "POST_MONEY_DISCOUNT_WITH_PRO_RATA",
+ "POST_MONEY_MFN_WITH_PRO_RATA",
+ "CUSTOM"
+ ]
+ },
+ "public.SafeTypeEnum": {
+ "name": "SafeTypeEnum",
+ "schema": "public",
+ "values": ["PRE_MONEY", "POST_MONEY"]
+ },
+ "public.SecuritiesStatusEnum": {
+ "name": "SecuritiesStatusEnum",
+ "schema": "public",
+ "values": ["ACTIVE", "DRAFT", "SIGNED", "PENDING"]
+ },
+ "public.ShareLegendsEnum": {
+ "name": "ShareLegendsEnum",
+ "schema": "public",
+ "values": ["US_SECURITIES_ACT", "SALE_AND_ROFR", "TRANSFER_RESTRICTIONS"]
+ },
+ "public.SharePrefixEnum": {
+ "name": "SharePrefixEnum",
+ "schema": "public",
+ "values": ["CS", "PS"]
+ },
+ "public.ShareTypeEnum": {
+ "name": "ShareTypeEnum",
+ "schema": "public",
+ "values": ["COMMON", "PREFERRED"]
+ },
+ "public.StakeholderRelationshipEnum": {
+ "name": "StakeholderRelationshipEnum",
+ "schema": "public",
+ "values": [
+ "ADVISOR",
+ "BOARD_MEMBER",
+ "CONSULTANT",
+ "EMPLOYEE",
+ "EX_ADVISOR",
+ "EX_CONSULTANT",
+ "EX_EMPLOYEE",
+ "EXECUTIVE",
+ "FOUNDER",
+ "INVESTOR",
+ "NON_US_EMPLOYEE",
+ "OFFICER",
+ "OTHER"
+ ]
+ },
+ "public.StakeholderTypeEnum": {
+ "name": "StakeholderTypeEnum",
+ "schema": "public",
+ "values": ["INDIVIDUAL", "INSTITUTION"]
+ },
+ "public.SubscriptionStatus": {
+ "name": "SubscriptionStatus",
+ "schema": "public",
+ "values": [
+ "trialing",
+ "active",
+ "canceled",
+ "incomplete",
+ "incomplete_expired",
+ "past_due",
+ "unpaid",
+ "paused"
+ ]
+ },
+ "public.TemplateStatus": {
+ "name": "TemplateStatus",
+ "schema": "public",
+ "values": ["DRAFT", "COMPLETE", "SENT", "WAITING", "CANCELLED"]
+ },
+ "public.UpdateStatusEnum": {
+ "name": "UpdateStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "PUBLIC", "PRIVATE"]
+ }
+ },
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/packages/db/migrations/meta/0004_snapshot.json b/packages/db/migrations/meta/0004_snapshot.json
new file mode 100644
index 000000000..a65e21149
--- /dev/null
+++ b/packages/db/migrations/meta/0004_snapshot.json
@@ -0,0 +1,5039 @@
+{
+ "id": "3ac57fb9-e8fa-4294-8e32-0cd048b6ed49",
+ "prevId": "7ed962da-2914-4589-a951-0df9c3bd1ec4",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.cap_better_auth_accounts": {
+ "name": "cap_better_auth_accounts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "account_id": {
+ "name": "account_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_id": {
+ "name": "provider_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token_expires_at": {
+ "name": "access_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "refresh_token_expires_at": {
+ "name": "refresh_token_expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cap_better_auth_accounts_user_id_cap_better_auth_users_id_fk": {
+ "name": "cap_better_auth_accounts_user_id_cap_better_auth_users_id_fk",
+ "tableFrom": "cap_better_auth_accounts",
+ "tableTo": "cap_better_auth_users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_better_auth_sessions": {
+ "name": "cap_better_auth_sessions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ip_address": {
+ "name": "ip_address",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cap_better_auth_sessions_user_id_cap_better_auth_users_id_fk": {
+ "name": "cap_better_auth_sessions_user_id_cap_better_auth_users_id_fk",
+ "tableFrom": "cap_better_auth_sessions",
+ "tableTo": "cap_better_auth_users",
+ "columnsFrom": ["user_id"],
+ "columnsTo": ["id"],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_better_auth_sessions_token_unique": {
+ "name": "cap_better_auth_sessions_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_better_auth_users": {
+ "name": "cap_better_auth_users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "image": {
+ "name": "image",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_better_auth_users_email_unique": {
+ "name": "cap_better_auth_users_email_unique",
+ "nullsNotDistinct": false,
+ "columns": ["email"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_better_auth_verifications": {
+ "name": "cap_better_auth_verifications",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "value": {
+ "name": "value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_accounts": {
+ "name": "cap_accounts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider": {
+ "name": "provider",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provider_account_id": {
+ "name": "provider_account_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "refresh_token": {
+ "name": "refresh_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "access_token": {
+ "name": "access_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "token_type": {
+ "name": "token_type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "scope": {
+ "name": "scope",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "id_token": {
+ "name": "id_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "session_state": {
+ "name": "session_state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "accounts_user_id_idx": {
+ "name": "accounts_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "accounts_provider_provider_account_id_idx": {
+ "name": "accounts_provider_provider_account_id_idx",
+ "columns": [
+ {
+ "expression": "provider",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "provider_account_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_sessions": {
+ "name": "cap_sessions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "session_token": {
+ "name": "session_token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "sessions_session_token_idx": {
+ "name": "sessions_session_token_idx",
+ "columns": [
+ {
+ "expression": "session_token",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "sessions_user_id_idx": {
+ "name": "sessions_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_users": {
+ "name": "cap_users",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "password": {
+ "name": "password",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email_verified": {
+ "name": "email_verified",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "image": {
+ "name": "image",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_signed_in": {
+ "name": "last_signed_in",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "identity_provider": {
+ "name": "identity_provider",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "users_email_idx": {
+ "name": "users_email_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_passkeys": {
+ "name": "cap_passkeys",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "last_used_at": {
+ "name": "last_used_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "credential_id": {
+ "name": "credential_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "credential_public_key": {
+ "name": "credential_public_key",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "counter": {
+ "name": "counter",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "credential_device_type": {
+ "name": "credential_device_type",
+ "type": "CredentialDeviceTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "credential_backed_up": {
+ "name": "credential_backed_up",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "transports": {
+ "name": "transports",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "passkeys_user_id_idx": {
+ "name": "passkeys_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_passkey_verification_tokens": {
+ "name": "cap_passkey_verification_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_passkey_verification_tokens_token_unique": {
+ "name": "cap_passkey_verification_tokens_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_password_reset_tokens": {
+ "name": "cap_password_reset_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "password_reset_tokens_email_token_idx": {
+ "name": "password_reset_tokens_email_token_idx",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "token",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_password_reset_tokens_token_unique": {
+ "name": "cap_password_reset_tokens_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_verification_tokens": {
+ "name": "cap_verification_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "secondary_id": {
+ "name": "secondary_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "identifier": {
+ "name": "identifier",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "token": {
+ "name": "token",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires": {
+ "name": "expires",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "verification_tokens_identifier_token_idx": {
+ "name": "verification_tokens_identifier_token_idx",
+ "columns": [
+ {
+ "expression": "identifier",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "token",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "verification_tokens_user_id_idx": {
+ "name": "verification_tokens_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_verification_tokens_secondary_id_unique": {
+ "name": "cap_verification_tokens_secondary_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["secondary_id"]
+ },
+ "cap_verification_tokens_token_unique": {
+ "name": "cap_verification_tokens_token_unique",
+ "nullsNotDistinct": false,
+ "columns": ["token"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_companies": {
+ "name": "cap_companies",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "logo": {
+ "name": "logo",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "website": {
+ "name": "website",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "incorporation_type": {
+ "name": "incorporation_type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "incorporation_date": {
+ "name": "incorporation_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "incorporation_country": {
+ "name": "incorporation_country",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "incorporation_state": {
+ "name": "incorporation_state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "street_address": {
+ "name": "street_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "city": {
+ "name": "city",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "state": {
+ "name": "state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "zipcode": {
+ "name": "zipcode",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "country": {
+ "name": "country",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "companies_public_id_unique": {
+ "name": "companies_public_id_unique",
+ "columns": [
+ {
+ "expression": "public_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_companies_public_id_unique": {
+ "name": "cap_companies_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_bank_accounts": {
+ "name": "cap_bank_accounts",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "beneficiary_name": {
+ "name": "beneficiary_name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "beneficiary_address": {
+ "name": "beneficiary_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bank_name": {
+ "name": "bank_name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bank_address": {
+ "name": "bank_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "account_number": {
+ "name": "account_number",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "routing_number": {
+ "name": "routing_number",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "account_type": {
+ "name": "account_type",
+ "type": "BankAccountTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CHECKING'"
+ },
+ "swift_code": {
+ "name": "swift_code",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "primary": {
+ "name": "primary",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "bank_accounts_company_id_idx": {
+ "name": "bank_accounts_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_custom_roles": {
+ "name": "cap_custom_roles",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "permissions": {
+ "name": "permissions",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "custom_roles_company_id_idx": {
+ "name": "custom_roles_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_members": {
+ "name": "cap_members",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "MemberStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'PENDING'"
+ },
+ "is_onboarded": {
+ "name": "is_onboarded",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "role": {
+ "name": "role",
+ "type": "Roles",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false,
+ "default": "'ADMIN'"
+ },
+ "work_email": {
+ "name": "work_email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_accessed": {
+ "name": "last_accessed",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "custom_role_id": {
+ "name": "custom_role_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "members_company_id_idx": {
+ "name": "members_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_status_idx": {
+ "name": "members_status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_user_id_idx": {
+ "name": "members_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_custom_role_id_idx": {
+ "name": "members_custom_role_id_idx",
+ "columns": [
+ {
+ "expression": "custom_role_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "members_company_id_user_id_unique": {
+ "name": "members_company_id_user_id_unique",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_stakeholders": {
+ "name": "cap_stakeholders",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "institution_name": {
+ "name": "institution_name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_type": {
+ "name": "stakeholder_type",
+ "type": "StakeholderTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'INDIVIDUAL'"
+ },
+ "current_relationship": {
+ "name": "current_relationship",
+ "type": "StakeholderRelationshipEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'EMPLOYEE'"
+ },
+ "tax_id": {
+ "name": "tax_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "street_address": {
+ "name": "street_address",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "city": {
+ "name": "city",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "state": {
+ "name": "state",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "zipcode": {
+ "name": "zipcode",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "country": {
+ "name": "country",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'US'"
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "stakeholders_company_id_idx": {
+ "name": "stakeholders_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_stakeholders_email_unique": {
+ "name": "cap_stakeholders_email_unique",
+ "nullsNotDistinct": false,
+ "columns": ["email"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_audits": {
+ "name": "cap_audits",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "summary": {
+ "name": "summary",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "action": {
+ "name": "action",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "occurred_at": {
+ "name": "occurred_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actor": {
+ "name": "actor",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "target": {
+ "name": "target",
+ "type": "jsonb[]",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "context": {
+ "name": "context",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "audits_company_id_idx": {
+ "name": "audits_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_share_classes": {
+ "name": "cap_share_classes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "idx": {
+ "name": "idx",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "class_type": {
+ "name": "class_type",
+ "type": "ShareTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'COMMON'"
+ },
+ "prefix": {
+ "name": "prefix",
+ "type": "SharePrefixEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CS'"
+ },
+ "initial_shares_authorized": {
+ "name": "initial_shares_authorized",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stockholder_approval_date": {
+ "name": "stockholder_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "votes_per_share": {
+ "name": "votes_per_share",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "par_value": {
+ "name": "par_value",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "price_per_share": {
+ "name": "price_per_share",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "seniority": {
+ "name": "seniority",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "conversion_rights": {
+ "name": "conversion_rights",
+ "type": "ConversionRightsEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CONVERTS_TO_FUTURE_ROUND'"
+ },
+ "converts_to_share_class_id": {
+ "name": "converts_to_share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "liquidation_preference_multiple": {
+ "name": "liquidation_preference_multiple",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "participation_cap_multiple": {
+ "name": "participation_cap_multiple",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "share_classes_company_id_idx": {
+ "name": "share_classes_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "share_classes_company_id_idx_unique": {
+ "name": "share_classes_company_id_idx_unique",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "idx",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_equity_plans": {
+ "name": "cap_equity_plans",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plan_effective_date": {
+ "name": "plan_effective_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "initial_shares_reserved": {
+ "name": "initial_shares_reserved",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "default_cancellaton_behavior": {
+ "name": "default_cancellaton_behavior",
+ "type": "CancellationBehaviorEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "comments": {
+ "name": "comments",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_class_id": {
+ "name": "share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "equity_plans_share_class_id_idx": {
+ "name": "equity_plans_share_class_id_idx",
+ "columns": [
+ {
+ "expression": "share_class_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "equity_plans_company_id_idx": {
+ "name": "equity_plans_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_buckets": {
+ "name": "cap_buckets",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "key": {
+ "name": "key",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "mime_type": {
+ "name": "mime_type",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "size": {
+ "name": "size",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tags": {
+ "name": "tags",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_document_shares": {
+ "name": "cap_document_shares",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "link": {
+ "name": "link",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "link_expires_at": {
+ "name": "link_expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "recipients": {
+ "name": "recipients",
+ "type": "varchar(191)[]",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'"
+ },
+ "email_protected": {
+ "name": "email_protected",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "document_id": {
+ "name": "document_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "document_shares_document_id_idx": {
+ "name": "document_shares_document_id_idx",
+ "columns": [
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_documents": {
+ "name": "cap_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bucket_id": {
+ "name": "bucket_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "uploader_id": {
+ "name": "uploader_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_id": {
+ "name": "share_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "option_id": {
+ "name": "option_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "safe_id": {
+ "name": "safe_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "convertible_note_id": {
+ "name": "convertible_note_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "documents_bucket_id_idx": {
+ "name": "documents_bucket_id_idx",
+ "columns": [
+ {
+ "expression": "bucket_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_uploader_id_idx": {
+ "name": "documents_uploader_id_idx",
+ "columns": [
+ {
+ "expression": "uploader_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_company_id_idx": {
+ "name": "documents_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_share_id_idx": {
+ "name": "documents_share_id_idx",
+ "columns": [
+ {
+ "expression": "share_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_option_id_idx": {
+ "name": "documents_option_id_idx",
+ "columns": [
+ {
+ "expression": "option_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_safe_id_idx": {
+ "name": "documents_safe_id_idx",
+ "columns": [
+ {
+ "expression": "safe_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "documents_convertible_note_id_idx": {
+ "name": "documents_convertible_note_id_idx",
+ "columns": [
+ {
+ "expression": "convertible_note_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_documents_public_id_unique": {
+ "name": "cap_documents_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_data_room_documents": {
+ "name": "cap_data_room_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "data_room_id": {
+ "name": "data_room_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "document_id": {
+ "name": "document_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "data_room_documents_data_room_id_idx": {
+ "name": "data_room_documents_data_room_id_idx",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_documents_document_id_idx": {
+ "name": "data_room_documents_document_id_idx",
+ "columns": [
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_documents_data_room_id_document_id_unique": {
+ "name": "data_room_documents_data_room_id_document_id_unique",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_data_room_recipients": {
+ "name": "cap_data_room_recipients",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "data_room_id": {
+ "name": "data_room_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "member_id": {
+ "name": "member_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "data_room_recipients_id_data_room_id_idx": {
+ "name": "data_room_recipients_id_data_room_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_member_id_idx": {
+ "name": "data_room_recipients_member_id_idx",
+ "columns": [
+ {
+ "expression": "member_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_data_room_id_idx": {
+ "name": "data_room_recipients_data_room_id_idx",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_stakeholder_id_idx": {
+ "name": "data_room_recipients_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_room_recipients_data_room_id_email_unique": {
+ "name": "data_room_recipients_data_room_id_email_unique",
+ "columns": [
+ {
+ "expression": "data_room_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_data_rooms": {
+ "name": "cap_data_rooms",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public": {
+ "name": "public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "data_rooms_public_id_idx": {
+ "name": "data_rooms_public_id_idx",
+ "columns": [
+ {
+ "expression": "public_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_rooms_company_id_idx": {
+ "name": "data_rooms_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "data_rooms_company_id_name_unique": {
+ "name": "data_rooms_company_id_name_unique",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_data_rooms_public_id_unique": {
+ "name": "cap_data_rooms_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_update_recipients": {
+ "name": "cap_update_recipients",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "update_id": {
+ "name": "update_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "member_id": {
+ "name": "member_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "update_recipients_id_update_id_idx": {
+ "name": "update_recipients_id_update_id_idx",
+ "columns": [
+ {
+ "expression": "id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "update_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_member_id_idx": {
+ "name": "update_recipients_member_id_idx",
+ "columns": [
+ {
+ "expression": "member_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_update_id_idx": {
+ "name": "update_recipients_update_id_idx",
+ "columns": [
+ {
+ "expression": "update_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_stakeholder_id_idx": {
+ "name": "update_recipients_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "update_recipients_update_id_email_unique": {
+ "name": "update_recipients_update_id_email_unique",
+ "columns": [
+ {
+ "expression": "update_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_esign_recipients": {
+ "name": "cap_esign_recipients",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "EsignRecipientStatus",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'PENDING'"
+ },
+ "member_id": {
+ "name": "member_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "esign_recipients_member_id_idx": {
+ "name": "esign_recipients_member_id_idx",
+ "columns": [
+ {
+ "expression": "member_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "esign_recipients_template_id_idx": {
+ "name": "esign_recipients_template_id_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_template_fields": {
+ "name": "cap_template_fields",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "FieldTypes",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'TEXT'"
+ },
+ "default_value": {
+ "name": "default_value",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "read_only": {
+ "name": "read_only",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "required": {
+ "name": "required",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "prefilled_value": {
+ "name": "prefilled_value",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "top": {
+ "name": "top",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "left": {
+ "name": "left",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "width": {
+ "name": "width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "height": {
+ "name": "height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "recipient_id": {
+ "name": "recipient_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "viewport_height": {
+ "name": "viewport_height",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "viewport_width": {
+ "name": "viewport_width",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "page": {
+ "name": "page",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "meta": {
+ "name": "meta",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "template_fields_template_id_idx": {
+ "name": "template_fields_template_id_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "template_fields_recipient_id_idx": {
+ "name": "template_fields_recipient_id_idx",
+ "columns": [
+ {
+ "expression": "recipient_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_templates": {
+ "name": "cap_templates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "TemplateStatus",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "ordered_delivery": {
+ "name": "ordered_delivery",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "message": {
+ "name": "message",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "bucket_id": {
+ "name": "bucket_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "uploader_id": {
+ "name": "uploader_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "completed_on": {
+ "name": "completed_on",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "templates_bucket_id_idx": {
+ "name": "templates_bucket_id_idx",
+ "columns": [
+ {
+ "expression": "bucket_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "templates_uploader_id_idx": {
+ "name": "templates_uploader_id_idx",
+ "columns": [
+ {
+ "expression": "uploader_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "templates_company_id_idx": {
+ "name": "templates_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_shares": {
+ "name": "cap_shares",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "SecuritiesStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "certificate_id": {
+ "name": "certificate_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "price_per_share": {
+ "name": "price_per_share",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "capital_contribution": {
+ "name": "capital_contribution",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ip_contribution": {
+ "name": "ip_contribution",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "debt_cancelled": {
+ "name": "debt_cancelled",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "other_contributions": {
+ "name": "other_contributions",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cliff_years": {
+ "name": "cliff_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "vesting_years": {
+ "name": "vesting_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "company_legends": {
+ "name": "company_legends",
+ "type": "ShareLegendsEnum[]",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'{}'"
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rule_144_date": {
+ "name": "rule_144_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "vesting_start_date": {
+ "name": "vesting_start_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "share_class_id": {
+ "name": "share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "shares_company_id_idx": {
+ "name": "shares_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "shares_stakeholder_id_idx": {
+ "name": "shares_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "shares_share_class_id_idx": {
+ "name": "shares_share_class_id_idx",
+ "columns": [
+ {
+ "expression": "share_class_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_options": {
+ "name": "cap_options",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "grant_id": {
+ "name": "grant_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "exercise_price": {
+ "name": "exercise_price",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "OptionTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "OptionStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "cliff_years": {
+ "name": "cliff_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "vesting_years": {
+ "name": "vesting_years",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expiration_date": {
+ "name": "expiration_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "vesting_start_date": {
+ "name": "vesting_start_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rule_144_date": {
+ "name": "rule_144_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "equity_plan_id": {
+ "name": "equity_plan_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "options_company_id_idx": {
+ "name": "options_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "options_equity_plan_id_idx": {
+ "name": "options_equity_plan_id_idx",
+ "columns": [
+ {
+ "expression": "equity_plan_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "options_stakeholder_id_idx": {
+ "name": "options_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_investments": {
+ "name": "cap_investments",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "amount": {
+ "name": "amount",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "shares": {
+ "name": "shares",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "date": {
+ "name": "date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "comments": {
+ "name": "comments",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "share_class_id": {
+ "name": "share_class_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "investments_company_id_idx": {
+ "name": "investments_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "investments_share_class_id_idx": {
+ "name": "investments_share_class_id_idx",
+ "columns": [
+ {
+ "expression": "share_class_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "investments_stakeholder_id_idx": {
+ "name": "investments_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_safes": {
+ "name": "cap_safes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "SafeTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'POST_MONEY'"
+ },
+ "status": {
+ "name": "status",
+ "type": "SafeStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "capital": {
+ "name": "capital",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "safe_template": {
+ "name": "safe_template",
+ "type": "SafeTemplateEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "safe_id": {
+ "name": "safe_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valuation_cap": {
+ "name": "valuation_cap",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "discount_rate": {
+ "name": "discount_rate",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "mfn": {
+ "name": "mfn",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "pro_rata": {
+ "name": "pro_rata",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "additional_terms": {
+ "name": "additional_terms",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "safes_company_id_idx": {
+ "name": "safes_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "safes_stakeholder_id_idx": {
+ "name": "safes_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_convertible_notes": {
+ "name": "cap_convertible_notes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "ConvertibleStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "type": {
+ "name": "type",
+ "type": "ConvertibleTypeEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'NOTE'"
+ },
+ "capital": {
+ "name": "capital",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "conversion_cap": {
+ "name": "conversion_cap",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "discount_rate": {
+ "name": "discount_rate",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "mfn": {
+ "name": "mfn",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "additional_terms": {
+ "name": "additional_terms",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_rate": {
+ "name": "interest_rate",
+ "type": "real",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_method": {
+ "name": "interest_method",
+ "type": "ConvertibleInterestMethodEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_accrual": {
+ "name": "interest_accrual",
+ "type": "ConvertibleInterestAccrualEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interest_payment_schedule": {
+ "name": "interest_payment_schedule",
+ "type": "ConvertibleInterestPaymentScheduleEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "stakeholder_id": {
+ "name": "stakeholder_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "issue_date": {
+ "name": "issue_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "board_approval_date": {
+ "name": "board_approval_date",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "convertible_notes_company_id_idx": {
+ "name": "convertible_notes_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "convertible_notes_stakeholder_id_idx": {
+ "name": "convertible_notes_stakeholder_id_idx",
+ "columns": [
+ {
+ "expression": "stakeholder_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_esign_audits": {
+ "name": "cap_esign_audits",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "template_id": {
+ "name": "template_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "recipient_id": {
+ "name": "recipient_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "action": {
+ "name": "action",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ip": {
+ "name": "ip",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "user_agent": {
+ "name": "user_agent",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "location": {
+ "name": "location",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "summary": {
+ "name": "summary",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "occurred_at": {
+ "name": "occurred_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "esign_audits_company_id_idx": {
+ "name": "esign_audits_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "esign_audits_template_id_idx": {
+ "name": "esign_audits_template_id_idx",
+ "columns": [
+ {
+ "expression": "template_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "esign_audits_recipient_id_idx": {
+ "name": "esign_audits_recipient_id_idx",
+ "columns": [
+ {
+ "expression": "recipient_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_updates": {
+ "name": "cap_updates",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "public_id": {
+ "name": "public_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "content": {
+ "name": "content",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "html": {
+ "name": "html",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "public": {
+ "name": "public",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "status": {
+ "name": "status",
+ "type": "UpdateStatusEnum",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'DRAFT'"
+ },
+ "author_id": {
+ "name": "author_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "updates_public_id_idx": {
+ "name": "updates_public_id_idx",
+ "columns": [
+ {
+ "expression": "public_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "updates_author_id_idx": {
+ "name": "updates_author_id_idx",
+ "columns": [
+ {
+ "expression": "author_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "updates_company_id_idx": {
+ "name": "updates_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cap_updates_public_id_unique": {
+ "name": "cap_updates_public_id_unique",
+ "nullsNotDistinct": false,
+ "columns": ["public_id"]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_customers": {
+ "name": "cap_billing_customers",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "company_id": {
+ "name": "company_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "billing_customers_company_id_idx": {
+ "name": "billing_customers_company_id_idx",
+ "columns": [
+ {
+ "expression": "company_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_prices": {
+ "name": "cap_billing_prices",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "product_id": {
+ "name": "product_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "unit_amount": {
+ "name": "unit_amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "currency": {
+ "name": "currency",
+ "type": "varchar(3)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "PricingType",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "interval": {
+ "name": "interval",
+ "type": "PricingPlanInterval",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "interval_count": {
+ "name": "interval_count",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trial_period_days": {
+ "name": "trial_period_days",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "billing_prices_product_id_idx": {
+ "name": "billing_prices_product_id_idx",
+ "columns": [
+ {
+ "expression": "product_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_products": {
+ "name": "cap_billing_products",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "description": {
+ "name": "description",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_billing_subscriptions": {
+ "name": "cap_billing_subscriptions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "price_id": {
+ "name": "price_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "quantity": {
+ "name": "quantity",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "SubscriptionStatus",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancel_at_period_end": {
+ "name": "cancel_at_period_end",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "created": {
+ "name": "created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "current_period_start": {
+ "name": "current_period_start",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "current_period_end": {
+ "name": "current_period_end",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ended_at": {
+ "name": "ended_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cancel_at": {
+ "name": "cancel_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "canceled_at": {
+ "name": "canceled_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trial_start": {
+ "name": "trial_start",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "trial_end": {
+ "name": "trial_end",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metadata": {
+ "name": "metadata",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "billing_subscriptions_price_id_idx": {
+ "name": "billing_subscriptions_price_id_idx",
+ "columns": [
+ {
+ "expression": "price_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "billing_subscriptions_customer_id_idx": {
+ "name": "billing_subscriptions_customer_id_idx",
+ "columns": [
+ {
+ "expression": "customer_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_access_tokens": {
+ "name": "cap_access_tokens",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(191)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "active": {
+ "name": "active",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "client_id": {
+ "name": "client_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "client_secret": {
+ "name": "client_secret",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "type_enum": {
+ "name": "type_enum",
+ "type": "AccessTokenType",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'api'"
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "varchar(191)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expires_at": {
+ "name": "expires_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "last_used": {
+ "name": "last_used",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "access_tokens_user_id_idx": {
+ "name": "access_tokens_user_id_idx",
+ "columns": [
+ {
+ "expression": "user_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "access_tokens_type_enum_client_id_idx": {
+ "name": "access_tokens_type_enum_client_id_idx",
+ "columns": [
+ {
+ "expression": "type_enum",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "client_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cap_job_queue": {
+ "name": "cap_job_queue",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(128)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "type": {
+ "name": "type",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "payload": {
+ "name": "payload",
+ "type": "json",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "varchar(20)",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pending'"
+ },
+ "attempts": {
+ "name": "attempts",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "max_attempts": {
+ "name": "max_attempts",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 3
+ },
+ "priority": {
+ "name": "priority",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "scheduled_for": {
+ "name": "scheduled_for",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "processed_at": {
+ "name": "processed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "failed_at": {
+ "name": "failed_at",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "error": {
+ "name": "error",
+ "type": "varchar(1000)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retry_delay": {
+ "name": "retry_delay",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 1000
+ }
+ },
+ "indexes": {
+ "job_processing_idx": {
+ "name": "job_processing_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "scheduled_for",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "attempts",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "priority_ordering_idx": {
+ "name": "priority_ordering_idx",
+ "columns": [
+ {
+ "expression": "priority",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ },
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cleanup_idx": {
+ "name": "cleanup_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "created_at",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "status_idx": {
+ "name": "status_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "type_idx": {
+ "name": "type_idx",
+ "columns": [
+ {
+ "expression": "type",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "failed_jobs_idx": {
+ "name": "failed_jobs_idx",
+ "columns": [
+ {
+ "expression": "status",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "failed_at",
+ "isExpression": false,
+ "asc": false,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.AccessTokenType": {
+ "name": "AccessTokenType",
+ "schema": "public",
+ "values": ["sig", "doc", "api", "upd"]
+ },
+ "public.AuditAction": {
+ "name": "AuditAction",
+ "schema": "public",
+ "values": ["CREATE", "UPDATE", "DELETE"]
+ },
+ "public.BankAccountTypeEnum": {
+ "name": "BankAccountTypeEnum",
+ "schema": "public",
+ "values": ["CHECKING", "SAVINGS"]
+ },
+ "public.CancellationBehaviorEnum": {
+ "name": "CancellationBehaviorEnum",
+ "schema": "public",
+ "values": [
+ "RETIRE",
+ "RETURN_TO_POOL",
+ "HOLD_AS_CAPITAL_STOCK",
+ "DEFINED_PER_PLAN_SECURITY"
+ ]
+ },
+ "public.ConversionRightsEnum": {
+ "name": "ConversionRightsEnum",
+ "schema": "public",
+ "values": ["CONVERTS_TO_FUTURE_ROUND", "CONVERTS_TO_SHARE_CLASS_ID"]
+ },
+ "public.ConvertibleInterestAccrualEnum": {
+ "name": "ConvertibleInterestAccrualEnum",
+ "schema": "public",
+ "values": [
+ "DAILY",
+ "MONTHLY",
+ "SEMI_ANNUALLY",
+ "ANNUALLY",
+ "YEARLY",
+ "CONTINUOUSLY"
+ ]
+ },
+ "public.ConvertibleInterestMethodEnum": {
+ "name": "ConvertibleInterestMethodEnum",
+ "schema": "public",
+ "values": ["SIMPLE", "COMPOUND"]
+ },
+ "public.ConvertibleInterestPaymentScheduleEnum": {
+ "name": "ConvertibleInterestPaymentScheduleEnum",
+ "schema": "public",
+ "values": ["DEFERRED", "PAY_AT_MATURITY"]
+ },
+ "public.ConvertibleStatusEnum": {
+ "name": "ConvertibleStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "ACTIVE", "PENDING", "EXPIRED", "CANCELLED"]
+ },
+ "public.ConvertibleTypeEnum": {
+ "name": "ConvertibleTypeEnum",
+ "schema": "public",
+ "values": ["CCD", "OCD", "NOTE"]
+ },
+ "public.CredentialDeviceTypeEnum": {
+ "name": "CredentialDeviceTypeEnum",
+ "schema": "public",
+ "values": ["SINGLE_DEVICE", "MULTI_DEVICE"]
+ },
+ "public.EsignRecipientStatus": {
+ "name": "EsignRecipientStatus",
+ "schema": "public",
+ "values": ["SENT", "SIGNED", "PENDING"]
+ },
+ "public.FieldTypes": {
+ "name": "FieldTypes",
+ "schema": "public",
+ "values": [
+ "TEXT",
+ "RADIO",
+ "EMAIL",
+ "DATE",
+ "DATETIME",
+ "TEXTAREA",
+ "CHECKBOX",
+ "SIGNATURE",
+ "SELECT"
+ ]
+ },
+ "public.MemberStatusEnum": {
+ "name": "MemberStatusEnum",
+ "schema": "public",
+ "values": ["ACTIVE", "INACTIVE", "PENDING"]
+ },
+ "public.OptionStatusEnum": {
+ "name": "OptionStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "ACTIVE", "EXERCISED", "EXPIRED", "CANCELLED"]
+ },
+ "public.OptionTypeEnum": {
+ "name": "OptionTypeEnum",
+ "schema": "public",
+ "values": ["ISO", "NSO", "RSU"]
+ },
+ "public.PricingPlanInterval": {
+ "name": "PricingPlanInterval",
+ "schema": "public",
+ "values": ["day", "week", "month", "year"]
+ },
+ "public.PricingType": {
+ "name": "PricingType",
+ "schema": "public",
+ "values": ["one_time", "recurring"]
+ },
+ "public.Roles": {
+ "name": "Roles",
+ "schema": "public",
+ "values": ["ADMIN", "CUSTOM"]
+ },
+ "public.SafeStatusEnum": {
+ "name": "SafeStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "ACTIVE", "PENDING", "EXPIRED", "CANCELLED"]
+ },
+ "public.SafeTemplateEnum": {
+ "name": "SafeTemplateEnum",
+ "schema": "public",
+ "values": [
+ "POST_MONEY_CAP",
+ "POST_MONEY_DISCOUNT",
+ "POST_MONEY_MFN",
+ "POST_MONEY_CAP_WITH_PRO_RATA",
+ "POST_MONEY_DISCOUNT_WITH_PRO_RATA",
+ "POST_MONEY_MFN_WITH_PRO_RATA",
+ "CUSTOM"
+ ]
+ },
+ "public.SafeTypeEnum": {
+ "name": "SafeTypeEnum",
+ "schema": "public",
+ "values": ["PRE_MONEY", "POST_MONEY"]
+ },
+ "public.SecuritiesStatusEnum": {
+ "name": "SecuritiesStatusEnum",
+ "schema": "public",
+ "values": ["ACTIVE", "DRAFT", "SIGNED", "PENDING"]
+ },
+ "public.ShareLegendsEnum": {
+ "name": "ShareLegendsEnum",
+ "schema": "public",
+ "values": ["US_SECURITIES_ACT", "SALE_AND_ROFR", "TRANSFER_RESTRICTIONS"]
+ },
+ "public.SharePrefixEnum": {
+ "name": "SharePrefixEnum",
+ "schema": "public",
+ "values": ["CS", "PS"]
+ },
+ "public.ShareTypeEnum": {
+ "name": "ShareTypeEnum",
+ "schema": "public",
+ "values": ["COMMON", "PREFERRED"]
+ },
+ "public.StakeholderRelationshipEnum": {
+ "name": "StakeholderRelationshipEnum",
+ "schema": "public",
+ "values": [
+ "ADVISOR",
+ "BOARD_MEMBER",
+ "CONSULTANT",
+ "EMPLOYEE",
+ "EX_ADVISOR",
+ "EX_CONSULTANT",
+ "EX_EMPLOYEE",
+ "EXECUTIVE",
+ "FOUNDER",
+ "INVESTOR",
+ "NON_US_EMPLOYEE",
+ "OFFICER",
+ "OTHER"
+ ]
+ },
+ "public.StakeholderTypeEnum": {
+ "name": "StakeholderTypeEnum",
+ "schema": "public",
+ "values": ["INDIVIDUAL", "INSTITUTION"]
+ },
+ "public.SubscriptionStatus": {
+ "name": "SubscriptionStatus",
+ "schema": "public",
+ "values": [
+ "trialing",
+ "active",
+ "canceled",
+ "incomplete",
+ "incomplete_expired",
+ "past_due",
+ "unpaid",
+ "paused"
+ ]
+ },
+ "public.TemplateStatus": {
+ "name": "TemplateStatus",
+ "schema": "public",
+ "values": ["DRAFT", "COMPLETE", "SENT", "WAITING", "CANCELLED"]
+ },
+ "public.UpdateStatusEnum": {
+ "name": "UpdateStatusEnum",
+ "schema": "public",
+ "values": ["DRAFT", "PUBLIC", "PRIVATE"]
+ }
+ },
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/packages/db/migrations/meta/_journal.json b/packages/db/migrations/meta/_journal.json
index d2517b9b4..bea8d80f3 100644
--- a/packages/db/migrations/meta/_journal.json
+++ b/packages/db/migrations/meta/_journal.json
@@ -22,6 +22,20 @@
"when": 1748503844931,
"tag": "0002_nostalgic_donald_blake",
"breakpoints": true
+ },
+ {
+ "idx": 3,
+ "version": "7",
+ "when": 1748838315996,
+ "tag": "0003_small_emma_frost",
+ "breakpoints": true
+ },
+ {
+ "idx": 4,
+ "version": "7",
+ "when": 1748840687375,
+ "tag": "0004_moaning_red_hulk",
+ "breakpoints": true
}
]
}
diff --git a/packages/db/schema/index.ts b/packages/db/schema/index.ts
index 57494e0a1..5f3ad5889 100644
--- a/packages/db/schema/index.ts
+++ b/packages/db/schema/index.ts
@@ -26,4 +26,5 @@ export * from "./convertible-notes";
export * from "./updates";
export * from "./billing";
export * from "./access-tokens";
+export * from "./job-queue";
export * from "./relations";
diff --git a/packages/db/schema/job-queue.ts b/packages/db/schema/job-queue.ts
new file mode 100644
index 000000000..758281f6e
--- /dev/null
+++ b/packages/db/schema/job-queue.ts
@@ -0,0 +1,68 @@
+import { createId } from "@paralleldrive/cuid2";
+import {
+ index,
+ integer,
+ json,
+ pgTable,
+ timestamp,
+ varchar,
+} from "drizzle-orm/pg-core";
+import { createTable } from "./table";
+
+export const jobQueue = createTable(
+ "job_queue",
+ {
+ id: varchar("id", { length: 128 })
+ .primaryKey()
+ .$defaultFn(() => createId()),
+ type: varchar("type", { length: 100 }).notNull(),
+ payload: json("payload").notNull(),
+ status: varchar("status", { length: 20 }).default("pending").notNull(),
+ attempts: integer("attempts").default(0).notNull(),
+ maxAttempts: integer("max_attempts").default(3).notNull(),
+ priority: integer("priority").default(0).notNull(),
+ scheduledFor: timestamp("scheduled_for").defaultNow().notNull(),
+ createdAt: timestamp("created_at").defaultNow().notNull(),
+ updatedAt: timestamp("updated_at").defaultNow().notNull(),
+ processedAt: timestamp("processed_at"),
+ failedAt: timestamp("failed_at"),
+ error: varchar("error", { length: 1000 }),
+ retryDelay: integer("retry_delay").default(1000).notNull(),
+ },
+ (table) => ({
+ // Primary index for job processing - covers the main WHERE clause
+ // Used in: WHERE status = 'pending' AND scheduled_for <= NOW() AND attempts < max_attempts
+ jobProcessingIdx: index("job_processing_idx").on(
+ table.status,
+ table.scheduledFor,
+ table.attempts,
+ ),
+
+ // Index for priority ordering - optimizes ORDER BY priority DESC, created_at ASC
+ priorityOrderingIdx: index("priority_ordering_idx").on(
+ table.priority.desc(),
+ table.createdAt.asc(),
+ ),
+
+ // Index for cleanup operations - covers cleanup WHERE clause
+ // Used in: WHERE created_at <= cutoff AND status = 'completed'
+ cleanupIdx: index("cleanup_idx").on(table.status, table.createdAt),
+
+ // Index for status filtering and stats queries
+ // Used in: GROUP BY status and general status filtering
+ statusIdx: index("status_idx").on(table.status),
+
+ // Index for job type filtering - useful for monitoring specific job types
+ typeIdx: index("type_idx").on(table.type),
+
+ // Composite index for failed job analysis
+ // Used for: WHERE status = 'failed' ORDER BY failed_at DESC
+ failedJobsIdx: index("failed_jobs_idx").on(
+ table.status,
+ table.failedAt.desc(),
+ ),
+ }),
+);
+
+export type JobQueue = typeof jobQueue.$inferSelect;
+export type NewJobQueue = typeof jobQueue.$inferInsert;
diff --git a/packages/queue/README.md b/packages/queue/README.md
new file mode 100644
index 000000000..1345fdd0a
--- /dev/null
+++ b/packages/queue/README.md
@@ -0,0 +1,494 @@
+# @captable/queue
+
+A serverless-friendly job queue implementation for the Captable monorepo, designed to replace pg-boss and work seamlessly with Vercel, Netlify, and other serverless platforms.
+
+## Features
+
+- π **Serverless-native** - No persistent connections required
+- β‘ **High performance** - Uses database-backed queue with efficient queries
+- π **Automatic retries** - Exponential backoff with configurable limits
+- π **Priority queues** - Process high-priority jobs first
+- π§Ή **Auto cleanup** - Automatic removal of old completed jobs
+- π **Job statistics** - Monitor queue health and performance
+- π **Type-safe** - Full TypeScript support with proper typing
+- πͺ΅ **Comprehensive logging** - Structured logging with @captable/logger
+
+## Installation
+
+```bash
+# The package is already installed as part of the monorepo
+```
+
+## Quick Start
+
+### 1. Create a Job
+
+```typescript
+import { BaseJob } from "@captable/queue";
+import { sendMail } from "@/server/mailer";
+
+export type WelcomeEmailPayload = {
+ email: string;
+ name: string;
+ companyName: string;
+};
+
+export class WelcomeEmailJob extends BaseJob {
+ readonly type = "email.welcome";
+ protected readonly options = {
+ maxAttempts: 3,
+ retryDelay: 1000,
+ priority: 1,
+ };
+
+ async work(payload: WelcomeEmailPayload): Promise {
+ // Your job logic here
+ await sendMail({
+ to: [payload.email],
+ subject: `Welcome to ${payload.companyName}!`,
+ html: `Welcome ${payload.name}!
`,
+ });
+ }
+}
+
+// Create and register the job
+const welcomeEmailJob = new WelcomeEmailJob();
+welcomeEmailJob.register();
+
+export { welcomeEmailJob };
+```
+
+### 2. Queue Jobs
+
+```typescript
+import { welcomeEmailJob } from "@/jobs/welcome-email";
+
+// Emit a single job
+await welcomeEmailJob.emit({
+ email: "user@example.com",
+ name: "John Doe",
+ companyName: "Acme Corp",
+});
+
+// Emit with custom options
+await welcomeEmailJob.emit(
+ {
+ email: "user@example.com",
+ name: "John Doe",
+ companyName: "Acme Corp",
+ },
+ {
+ delay: 60, // Wait 60 seconds before processing
+ priority: 5, // High priority
+ maxAttempts: 5,
+ }
+);
+
+// Bulk emit
+await welcomeEmailJob.bulkEmit([
+ { email: "user1@example.com", name: "User 1", companyName: "Acme" },
+ { email: "user2@example.com", name: "User 2", companyName: "Acme" },
+]);
+```
+
+### 3. Process Jobs (Cron)
+
+Jobs are automatically processed via Cron:
+
+```typescript
+// app/api/cron/process-jobs/route.ts
+import { processJobs } from "@captable/queue";
+import "@/jobs"; // Import to register all jobs
+
+export async function GET() {
+ const processed = await processJobs(20);
+ return Response.json({ processed });
+}
+```
+
+## API Reference
+
+### BaseJob
+
+Abstract base class for creating jobs.
+
+```typescript
+abstract class BaseJob> {
+ abstract readonly type: string;
+ protected readonly options: JobOptions;
+
+ abstract work(payload: T): Promise;
+
+ emit(payload: T, options?: JobOptions): Promise;
+ bulkEmit(payloads: T[], options?: JobOptions): Promise;
+ emitDelayed(payload: T, delayInSeconds: number, options?: JobOptions): Promise;
+ emitPriority(payload: T, priority: number, options?: JobOptions): Promise;
+ register(): void;
+}
+```
+
+### Queue Functions
+
+Utility functions for queue management.
+
+```typescript
+// Register a job processor
+function register(processor: JobProcessor): void;
+
+// Add jobs to queue
+function addJob(type: string, payload: T, options?: JobOptions): Promise;
+function addJobs(jobs: Array>): Promise;
+
+// Process and manage jobs
+function processJobs(limit?: number): Promise;
+function getStats(): Promise;
+function cleanupJobs(olderThanDays?: number): Promise;
+
+// Utility functions
+function getRegisteredProcessors(): string[];
+function clearProcessors(): void;
+```
+
+### JobOptions
+
+Configuration options for jobs.
+
+```typescript
+interface JobOptions {
+ delay?: number; // seconds to delay execution
+ maxAttempts?: number; // maximum retry attempts
+ priority?: number; // higher = more priority
+ retryDelay?: number; // milliseconds between retries
+}
+```
+
+### JobStats
+
+Queue statistics.
+
+```typescript
+interface JobStats {
+ pending: number;
+ processing: number;
+ completed: number;
+ failed: number;
+}
+```
+
+## Configuration
+
+### Cron
+
+```json
+// vercel.json
+{
+ "crons": [
+ {
+ "path": "/api/cron/process-jobs",
+ "schedule": "* * * * *" // Every minute
+ },
+ {
+ "path": "/api/cron/cleanup-jobs",
+ "schedule": "0 2 * * *" // Daily at 2 AM
+ }
+ ]
+}
+```
+
+### Environment Variables
+
+```bash
+CRON_SECRET=your-super-secret-cron-key
+DATABASE_URL=your-database-url
+```
+
+## Database Schema
+
+The queue uses a single table `cap_job_queue`:
+
+```sql
+CREATE TABLE cap_job_queue (
+ id VARCHAR(128) PRIMARY KEY,
+ type VARCHAR(100) NOT NULL,
+ payload JSON NOT NULL,
+ status VARCHAR(20) DEFAULT 'pending',
+ attempts INTEGER DEFAULT 0,
+ max_attempts INTEGER DEFAULT 3,
+ priority INTEGER DEFAULT 0,
+ scheduled_for TIMESTAMP DEFAULT NOW(),
+ created_at TIMESTAMP DEFAULT NOW(),
+ updated_at TIMESTAMP DEFAULT NOW(),
+ processed_at TIMESTAMP,
+ failed_at TIMESTAMP,
+ error VARCHAR(1000),
+ retry_delay INTEGER DEFAULT 1000
+);
+```
+
+## Job Organization
+
+### Job Registry
+
+Create a central registry to import all jobs:
+
+```typescript
+// jobs/index.ts
+import "./welcome-email";
+import "./password-reset";
+import "./notifications";
+
+export { welcomeEmailJob } from "./welcome-email";
+export { passwordResetJob } from "./password-reset";
+export * from "@captable/queue";
+```
+
+### Job Types
+
+Follow consistent naming conventions:
+
+- Email jobs: `email.welcome`, `email.password-reset`
+- PDF generation: `generate.invoice`, `generate.report`
+- Data processing: `process.analytics`, `process.cleanup`
+
+## Best Practices
+
+### 1. Job Design
+
+- Keep jobs idempotent
+- Handle errors gracefully
+- Use appropriate retry limits
+- Set meaningful priorities
+
+### 2. Payload Design
+
+```typescript
+// β
Good: Specific, typed payload
+type EmailPayload = {
+ to: string;
+ template: string;
+ data: Record;
+};
+
+// β Bad: Generic, untyped payload
+type GenericPayload = {
+ action: string;
+ params: any;
+};
+```
+
+### 3. Error Handling
+
+```typescript
+async work(payload: EmailPayload): Promise {
+ try {
+ await sendEmail(payload);
+ } catch (error) {
+ if (error instanceof RateLimitError) {
+ // Will retry with exponential backoff
+ throw error;
+ }
+
+ if (error instanceof PermanentError) {
+ // Log and don't retry
+ log.error({ error, payload }, "Permanent error");
+ return; // Don't throw to avoid retries
+ }
+
+ throw error; // Retry for unknown errors
+ }
+}
+```
+
+### 4. Monitoring
+
+```typescript
+import { getStats, getRegisteredProcessors } from "@captable/queue";
+
+// Get queue statistics
+const stats = await getStats();
+console.log(`Pending: ${stats.pending}, Failed: ${stats.failed}`);
+
+// List registered processors
+const processors = getRegisteredProcessors();
+console.log(`Registered jobs: ${processors.join(", ")}`);
+```
+
+## Migration from pg-boss
+
+### Before (pg-boss)
+
+```typescript
+import { BaseJob } from "@/jobs/base";
+import type { Job } from "pg-boss";
+
+export class EmailJob extends BaseJob {
+ readonly type = "email.send";
+
+ async work(job: Job): Promise {
+ await sendEmail(job.data);
+ }
+}
+
+// Usage
+await boss.send("email.send", { to: "user@example.com" });
+```
+
+### After (@captable/queue)
+
+```typescript
+import { BaseJob } from "@captable/queue";
+
+export class EmailJob extends BaseJob {
+ readonly type = "email.send";
+
+ async work(payload: EmailPayload): Promise {
+ await sendEmail(payload);
+ }
+}
+
+const emailJob = new EmailJob();
+emailJob.register();
+
+// Usage
+await emailJob.emit({ to: "user@example.com" });
+```
+
+## Troubleshooting
+
+### Jobs Not Processing
+
+1. Check cron routes are deployed
+2. Verify `CRON_SECRET` is set
+3. Ensure jobs are imported in registry
+4. Check database connectivity
+
+### High Failure Rate
+
+1. Review error logs
+2. Adjust retry limits
+3. Check external service availability
+4. Validate job payloads
+
+### Performance Issues
+
+1. Monitor queue depth
+2. Adjust processing batch size
+3. Consider job priorities
+4. Review database indexes
+
+## License
+
+MIT
+
+## Development
+
+### Quick Development Setup
+
+
+Start everything including job processing:
+
+```bash
+# From monorepo root
+bun run dx
+```
+
+This starts:
+- Next.js development server (port 3000)
+- Database studio
+- Email development server (port 3001)
+- **Job processor in watch mode** (with quiet logging)
+
+### Manual Job Management
+
+From the `apps/captable` directory:
+
+```bash
+# Process all pending jobs once
+bun run jobs
+
+# Process jobs continuously (watch mode)
+bun run jobs:dev
+
+# Queue sample jobs for testing
+bun run test-jobs
+
+# Show queue statistics
+bun run jobs stats
+
+# Clean up old completed jobs
+bun run jobs cleanup
+```
+
+### Development Scripts
+
+Job management scripts are located in `apps/captable/scripts/dev/`:
+
+- **`jobs.ts`** - Main job processor with watch mode
+- **`test-jobs.ts`** - Queue sample jobs for testing
+- **`README.md`** - Detailed documentation
+
+### Watch Mode Features
+
+The watch mode (`bun run jobs:dev`) includes:
+
+- π **Quiet operation** - Only logs when jobs are found
+- π **Heartbeat logging** - Status every 60 seconds when idle
+- π **Graceful shutdown** - Ctrl+C stops cleanly
+- β‘ **Fast processing** - 1s intervals when jobs found, 5s when idle
+
+### Development Workflow
+
+1. **Start full development environment:**
+ ```bash
+ bun run dx
+ ```
+
+2. **Queue test jobs (in another terminal):**
+ ```bash
+ cd apps/captable
+ bun run test-jobs
+ ```
+
+3. **Monitor queue status:**
+ ```bash
+ bun run jobs stats
+ ```
+
+4. **Manual processing (if needed):**
+ ```bash
+ bun run jobs
+ ```
+
+### Testing Individual Job Types
+
+```bash
+# Test specific email jobs
+bun run test-jobs password-reset
+bun run test-jobs member-invite
+bun run test-jobs auth-verification
+
+# Test all jobs at once
+bun run test-jobs all
+```
+
+### Production vs Development
+
+| Environment | Trigger | Frequency | Logging |
+|-------------|---------|-----------|----------|
+| **Development** | Watch mode | Every 5s | Quiet + heartbeat |
+| **Production** |Cron | Every minute | Event-driven |
+
+### Available Job Types
+
+Current job implementations:
+
+- `email.password-reset` - Password reset emails
+- `email.member-invite` - Member invitation emails
+- `email.auth-verify` - Account verification emails
+- `email.share-update` - Share update notifications
+- `email.share-data-room` - Data room sharing emails
+- `email.esign` - E-signature request emails
+- `email.esign-confirmation` - E-signature confirmation emails
+- `generate.esign-pdf` - PDF generation for e-signatures
+
+See `apps/captable/jobs/` for complete implementations.
diff --git a/packages/queue/base-job.ts b/packages/queue/base-job.ts
new file mode 100644
index 000000000..427cc4167
--- /dev/null
+++ b/packages/queue/base-job.ts
@@ -0,0 +1,83 @@
+import { logger } from "@captable/logger";
+import { addJob, addJobs, register } from "./queue";
+import type { JobOptions } from "./types";
+
+const log = logger.child({ module: "base-job" });
+
+export abstract class BaseJob> {
+ abstract readonly type: string;
+ protected readonly options: JobOptions = {
+ maxAttempts: 3,
+ retryDelay: 1000,
+ priority: 0,
+ };
+
+ /**
+ * Register this job with the queue
+ * Call this method after instantiating the job
+ */
+ register(): void {
+ register({
+ type: this.type,
+ process: this.work.bind(this),
+ });
+
+ log.info(`Registered job: ${this.type}`);
+ }
+
+ /**
+ * Process the job payload
+ */
+ abstract work(payload: T): Promise;
+
+ /**
+ * Emit a single job
+ */
+ emit(payload: T, options?: JobOptions): Promise {
+ return addJob(this.type, payload, {
+ ...this.options,
+ ...options,
+ });
+ }
+
+ /**
+ * Emit multiple jobs in bulk
+ */
+ bulkEmit(payloads: T[], options?: JobOptions): Promise {
+ const jobs = payloads.map((payload) => ({
+ type: this.type,
+ payload,
+ options: { ...this.options, ...options },
+ }));
+
+ return addJobs(jobs);
+ }
+
+ /**
+ * Emit a job with delay
+ */
+ emitDelayed(
+ payload: T,
+ delayInSeconds: number,
+ options?: JobOptions,
+ ): Promise {
+ return this.emit(payload, {
+ ...options,
+ delay: delayInSeconds,
+ });
+ }
+
+ /**
+ * Emit a high priority job
+ */
+ emitPriority(
+ payload: T,
+ priority: number,
+ options?: JobOptions,
+ ): Promise {
+ return this.emit(payload, {
+ ...options,
+ priority,
+ });
+ }
+}
diff --git a/packages/queue/index.ts b/packages/queue/index.ts
new file mode 100644
index 000000000..fc33d0ab8
--- /dev/null
+++ b/packages/queue/index.ts
@@ -0,0 +1,20 @@
+export {
+ register,
+ addJob,
+ addJobs,
+ processJobs,
+ getStats,
+ cleanupJobs,
+ getRegisteredProcessors,
+ clearProcessors,
+} from "./queue";
+export { BaseJob } from "./base-job";
+export type {
+ JobOptions,
+ JobProcessor,
+ JobStats,
+ BulkJobInput,
+} from "./types";
+
+// Re-export database types for convenience
+export type { JobQueue, NewJobQueue } from "@captable/db/schema";
diff --git a/packages/queue/package.json b/packages/queue/package.json
new file mode 100644
index 000000000..693f341bc
--- /dev/null
+++ b/packages/queue/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "@captable/queue",
+ "module": "index.ts",
+ "type": "module",
+ "exports": {
+ ".": {
+ "import": "./index.ts",
+ "require": "./index.ts",
+ "types": "./index.ts"
+ },
+ "./base-job": {
+ "import": "./base-job.ts",
+ "types": "./base-job.ts"
+ },
+ "./types": {
+ "import": "./types.ts",
+ "types": "./types.ts"
+ }
+ },
+ "sideEffects": false,
+ "scripts": {
+ "lint": "biome check",
+ "format": "biome format --write",
+ "type-check": "tsc --noEmit"
+ },
+ "devDependencies": {
+ "@biomejs/biome": "1.9.4",
+ "@types/bun": "latest"
+ },
+ "peerDependencies": {
+ "typescript": "^5.0.0"
+ },
+ "dependencies": {
+ "@captable/db": "workspace:*",
+ "@captable/logger": "workspace:*",
+ "drizzle-orm": "^0.43.1"
+ }
+}
diff --git a/packages/queue/queue.ts b/packages/queue/queue.ts
new file mode 100644
index 000000000..c85b3a3ac
--- /dev/null
+++ b/packages/queue/queue.ts
@@ -0,0 +1,310 @@
+import { db } from "@captable/db";
+import { jobQueue } from "@captable/db/schema";
+import type { JobQueue } from "@captable/db/schema";
+import { logger } from "@captable/logger";
+import { and, asc, desc, eq, lt, lte, sql } from "drizzle-orm";
+import type { BulkJobInput, JobOptions, JobProcessor, JobStats } from "./types";
+
+const log = logger.child({ module: "queue" });
+
+// Module-level processors map
+const processors = new Map>>();
+
+/**
+ * Register a job processor
+ */
+export function register>(
+ processor: JobProcessor,
+) {
+ processors.set(
+ processor.type,
+ processor as JobProcessor>,
+ );
+ log.info(`Registered job processor: ${processor.type}`);
+}
+
+/**
+ * Add a single job to the queue
+ */
+export async function addJob>(
+ type: string,
+ payload: T,
+ options: JobOptions = {},
+): Promise {
+ const {
+ delay = 0,
+ maxAttempts = 3,
+ priority = 0,
+ retryDelay = 1000,
+ } = options;
+
+ const scheduledFor = new Date(Date.now() + delay * 1000);
+
+ const [job] = await db
+ .insert(jobQueue)
+ .values({
+ type,
+ payload,
+ maxAttempts,
+ priority,
+ scheduledFor,
+ retryDelay,
+ })
+ .returning();
+
+ if (!job) {
+ throw new Error("Failed to create job");
+ }
+
+ log.info(
+ {
+ jobId: job.id,
+ type,
+ scheduledFor,
+ priority,
+ },
+ `Job queued: ${type}`,
+ );
+
+ return job.id;
+}
+
+/**
+ * Add multiple jobs to the queue in bulk
+ */
+export async function addJobs>(
+ jobs: Array>,
+): Promise {
+ const jobsToInsert = jobs.map(({ type, payload, options = {} }) => {
+ const {
+ delay = 0,
+ maxAttempts = 3,
+ priority = 0,
+ retryDelay = 1000,
+ } = options;
+
+ return {
+ type,
+ payload,
+ maxAttempts,
+ priority,
+ scheduledFor: new Date(Date.now() + delay * 1000),
+ retryDelay,
+ };
+ });
+
+ const insertedJobs = await db
+ .insert(jobQueue)
+ .values(jobsToInsert)
+ .returning();
+
+ log.info(`Bulk queued ${insertedJobs.length} jobs`);
+ return insertedJobs.map((job) => job.id);
+}
+
+/**
+ * Process pending jobs
+ */
+export async function processJobs(limit = 10): Promise {
+ const startTime = Date.now();
+
+ // Get jobs ordered by priority (desc) then created date (asc)
+ const jobs = await db
+ .select()
+ .from(jobQueue)
+ .where(
+ and(
+ eq(jobQueue.status, "pending"),
+ lte(jobQueue.scheduledFor, new Date()),
+ lt(jobQueue.attempts, jobQueue.maxAttempts),
+ ),
+ )
+ .orderBy(desc(jobQueue.priority), asc(jobQueue.createdAt))
+ .limit(limit);
+
+ if (jobs.length === 0) {
+ return 0;
+ }
+
+ log.info(`Processing ${jobs.length} jobs`);
+
+ let processedCount = 0;
+
+ for (const job of jobs) {
+ try {
+ await executeJob(job);
+ processedCount++;
+ } catch (error) {
+ log.error(
+ {
+ jobId: job.id,
+ type: job.type,
+ error: error instanceof Error ? error.message : String(error),
+ },
+ `Job execution failed: ${job.type}`,
+ );
+ }
+ }
+
+ const duration = Date.now() - startTime;
+ log.info(
+ {
+ processed: processedCount,
+ total: jobs.length,
+ duration,
+ },
+ `Job processing completed in ${duration}ms`,
+ );
+
+ return processedCount;
+}
+
+/**
+ * Execute a single job
+ */
+async function executeJob(job: JobQueue): Promise {
+ const jobStartTime = Date.now();
+
+ // Update job status to processing
+ await db
+ .update(jobQueue)
+ .set({
+ status: "processing",
+ updatedAt: new Date(),
+ })
+ .where(eq(jobQueue.id, job.id));
+
+ const processor = processors.get(job.type);
+ if (!processor) {
+ throw new Error(`No processor registered for job type: ${job.type}`);
+ }
+
+ try {
+ await processor.process(job.payload as Record);
+
+ // Mark as completed
+ await db
+ .update(jobQueue)
+ .set({
+ status: "completed",
+ processedAt: new Date(),
+ updatedAt: new Date(),
+ })
+ .where(eq(jobQueue.id, job.id));
+
+ const duration = Date.now() - jobStartTime;
+ log.info(
+ {
+ jobId: job.id,
+ type: job.type,
+ duration,
+ },
+ `Job completed: ${job.type}`,
+ );
+ } catch (error) {
+ const newAttempts = job.attempts + 1;
+ const isLastAttempt = newAttempts >= job.maxAttempts;
+ const errorMessage = error instanceof Error ? error.message : String(error);
+
+ // Calculate next retry time with exponential backoff
+ const nextRetryDelay = job.retryDelay * 2 ** job.attempts;
+ const nextScheduledFor = new Date(Date.now() + nextRetryDelay);
+
+ await db
+ .update(jobQueue)
+ .set({
+ attempts: newAttempts,
+ status: isLastAttempt ? "failed" : "pending",
+ error: errorMessage,
+ failedAt: isLastAttempt ? new Date() : undefined,
+ scheduledFor: isLastAttempt ? job.scheduledFor : nextScheduledFor,
+ updatedAt: new Date(),
+ })
+ .where(eq(jobQueue.id, job.id));
+
+ if (isLastAttempt) {
+ log.error(
+ {
+ jobId: job.id,
+ type: job.type,
+ attempts: newAttempts,
+ error: errorMessage,
+ },
+ `Job failed permanently: ${job.type}`,
+ );
+ } else {
+ log.warn(
+ {
+ jobId: job.id,
+ type: job.type,
+ attempts: newAttempts,
+ nextRetry: nextScheduledFor,
+ error: errorMessage,
+ },
+ `Job failed, will retry: ${job.type}`,
+ );
+ }
+
+ throw error;
+ }
+}
+
+/**
+ * Get job statistics
+ */
+export async function getStats(): Promise {
+ const stats = await db
+ .select({
+ status: jobQueue.status,
+ count: sql`count(*)`,
+ })
+ .from(jobQueue)
+ .groupBy(jobQueue.status);
+
+ return stats.reduce(
+ (acc, stat) => {
+ acc[stat.status as keyof JobStats] = stat.count;
+ return acc;
+ },
+ {
+ pending: 0,
+ processing: 0,
+ completed: 0,
+ failed: 0,
+ } as JobStats,
+ );
+}
+
+/**
+ * Clean up old completed jobs
+ */
+export async function cleanupJobs(olderThanDays = 7): Promise {
+ const cutoffDate = new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000);
+
+ const result = await db
+ .delete(jobQueue)
+ .where(
+ and(
+ lte(jobQueue.createdAt, cutoffDate),
+ eq(jobQueue.status, "completed"),
+ ),
+ );
+
+ const deletedCount = result.length || 0;
+ log.info(`Cleaned up ${deletedCount} old completed jobs`);
+ return deletedCount;
+}
+
+/**
+ * Get all processors types
+ */
+export function getRegisteredProcessors(): string[] {
+ return Array.from(processors.keys());
+}
+
+/**
+ * Clear all processors (useful for testing)
+ */
+export function clearProcessors(): void {
+ processors.clear();
+}
diff --git a/packages/queue/types.ts b/packages/queue/types.ts
new file mode 100644
index 000000000..5ce349cba
--- /dev/null
+++ b/packages/queue/types.ts
@@ -0,0 +1,24 @@
+export interface JobOptions {
+ delay?: number; // seconds
+ maxAttempts?: number;
+ priority?: number;
+ retryDelay?: number; // milliseconds
+}
+
+export interface JobProcessor> {
+ type: string;
+ process: (payload: T) => Promise;
+}
+
+export interface JobStats {
+ pending: number;
+ processing: number;
+ completed: number;
+ failed: number;
+}
+
+export interface BulkJobInput> {
+ type: string;
+ payload: T;
+ options?: JobOptions;
+}
diff --git a/turbo.jsonc b/turbo.jsonc
index 98369b88b..fa9e495f5 100644
--- a/turbo.jsonc
+++ b/turbo.jsonc
@@ -61,6 +61,14 @@
"inputs": []
},
+ // Jobs development - continuous job processing
+ "jobs:dev": {
+ "cache": false,
+ "persistent": true,
+ "dependsOn": [],
+ "inputs": []
+ },
+
// Formatting is independent
"format": {
"inputs": ["**/*.{ts,tsx,js,jsx,json,md}", "biome.json", ".biomejs.json"],