summaryrefslogtreecommitdiffhomepage
path: root/cloud/core
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-08-08 13:22:54 -0400
committerFrank <[email protected]>2025-08-08 13:24:32 -0400
commit183e0911b76025a1f2a82e979d9834fec2131d0e (patch)
tree9987c1753bd64d1ce1d174ab397f1a8c681f642c /cloud/core
parentc7bb19ad0712469063eab35589aa5d3602b0c5b1 (diff)
downloadopencode-183e0911b76025a1f2a82e979d9834fec2131d0e.tar.gz
opencode-183e0911b76025a1f2a82e979d9834fec2131d0e.zip
wip: gateway
Diffstat (limited to 'cloud/core')
-rw-r--r--cloud/core/drizzle.config.ts20
-rw-r--r--cloud/core/migrations/0000_amused_mojo.sql66
-rw-r--r--cloud/core/migrations/0001_thankful_chat.sql8
-rw-r--r--cloud/core/migrations/0002_stale_jackal.sql14
-rw-r--r--cloud/core/migrations/0003_tranquil_spencer_smythe.sql1
-rw-r--r--cloud/core/migrations/meta/0000_snapshot.json461
-rw-r--r--cloud/core/migrations/meta/0001_snapshot.json515
-rw-r--r--cloud/core/migrations/meta/0002_snapshot.json615
-rw-r--r--cloud/core/migrations/meta/0003_snapshot.json609
-rw-r--r--cloud/core/migrations/meta/_journal.json34
-rw-r--r--cloud/core/package.json22
-rw-r--r--cloud/core/src/account.ts67
-rw-r--r--cloud/core/src/actor.ts75
-rw-r--r--cloud/core/src/billing.ts71
-rw-r--r--cloud/core/src/context.ts21
-rw-r--r--cloud/core/src/drizzle/index.ts94
-rw-r--r--cloud/core/src/drizzle/types.ts29
-rw-r--r--cloud/core/src/identifier.ts26
-rw-r--r--cloud/core/src/schema/account.sql.ts12
-rw-r--r--cloud/core/src/schema/billing.sql.ts45
-rw-r--r--cloud/core/src/schema/key.sql.ts16
-rw-r--r--cloud/core/src/schema/user.sql.ts16
-rw-r--r--cloud/core/src/schema/workspace.sql.ts25
-rw-r--r--cloud/core/src/util/fn.ts14
-rw-r--r--cloud/core/src/util/log.ts55
-rw-r--r--cloud/core/src/util/price.ts3
-rw-r--r--cloud/core/src/workspace.ts48
-rw-r--r--cloud/core/sst-env.d.ts9
-rw-r--r--cloud/core/tsconfig.json9
29 files changed, 3000 insertions, 0 deletions
diff --git a/cloud/core/drizzle.config.ts b/cloud/core/drizzle.config.ts
new file mode 100644
index 000000000..c65363cb8
--- /dev/null
+++ b/cloud/core/drizzle.config.ts
@@ -0,0 +1,20 @@
+import { defineConfig } from "drizzle-kit"
+import { Resource } from "sst"
+
+export default defineConfig({
+ out: "./migrations/",
+ strict: true,
+ schema: ["./src/**/*.sql.ts"],
+ verbose: true,
+ dialect: "postgresql",
+ dbCredentials: {
+ database: Resource.Database.database,
+ host: Resource.Database.host,
+ user: Resource.Database.username,
+ password: Resource.Database.password,
+ port: Resource.Database.port,
+ ssl: {
+ rejectUnauthorized: false,
+ },
+ },
+})
diff --git a/cloud/core/migrations/0000_amused_mojo.sql b/cloud/core/migrations/0000_amused_mojo.sql
new file mode 100644
index 000000000..75441ad24
--- /dev/null
+++ b/cloud/core/migrations/0000_amused_mojo.sql
@@ -0,0 +1,66 @@
+CREATE TABLE "billing" (
+ "id" varchar(30) NOT NULL,
+ "workspace_id" varchar(30) NOT NULL,
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone,
+ "customer_id" varchar(255),
+ "payment_method_id" varchar(255),
+ "payment_method_last4" varchar(4),
+ "balance" bigint NOT NULL,
+ "reload" boolean,
+ CONSTRAINT "billing_workspace_id_id_pk" PRIMARY KEY("workspace_id","id")
+);
+--> statement-breakpoint
+CREATE TABLE "payment" (
+ "id" varchar(30) NOT NULL,
+ "workspace_id" varchar(30) NOT NULL,
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone,
+ "customer_id" varchar(255),
+ "payment_id" varchar(255),
+ "amount" bigint NOT NULL,
+ CONSTRAINT "payment_workspace_id_id_pk" PRIMARY KEY("workspace_id","id")
+);
+--> statement-breakpoint
+CREATE TABLE "usage" (
+ "id" varchar(30) NOT NULL,
+ "workspace_id" varchar(30) NOT NULL,
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone,
+ "request_id" varchar(255),
+ "model" varchar(255) NOT NULL,
+ "input_tokens" integer NOT NULL,
+ "output_tokens" integer NOT NULL,
+ "reasoning_tokens" integer,
+ "cache_read_tokens" integer,
+ "cache_write_tokens" integer,
+ "cost" bigint NOT NULL,
+ CONSTRAINT "usage_workspace_id_id_pk" PRIMARY KEY("workspace_id","id")
+);
+--> statement-breakpoint
+CREATE TABLE "user" (
+ "id" varchar(30) NOT NULL,
+ "workspace_id" varchar(30) NOT NULL,
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone,
+ "email" text NOT NULL,
+ "name" varchar(255) NOT NULL,
+ "time_seen" timestamp with time zone,
+ "color" integer,
+ CONSTRAINT "user_workspace_id_id_pk" PRIMARY KEY("workspace_id","id")
+);
+--> statement-breakpoint
+CREATE TABLE "workspace" (
+ "id" varchar(30) PRIMARY KEY NOT NULL,
+ "slug" varchar(255),
+ "name" varchar(255),
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone
+);
+--> statement-breakpoint
+ALTER TABLE "billing" ADD CONSTRAINT "billing_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "payment" ADD CONSTRAINT "payment_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "usage" ADD CONSTRAINT "usage_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "user" ADD CONSTRAINT "user_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+CREATE UNIQUE INDEX "user_email" ON "user" USING btree ("workspace_id","email");--> statement-breakpoint
+CREATE UNIQUE INDEX "slug" ON "workspace" USING btree ("slug"); \ No newline at end of file
diff --git a/cloud/core/migrations/0001_thankful_chat.sql b/cloud/core/migrations/0001_thankful_chat.sql
new file mode 100644
index 000000000..9c66a6ac4
--- /dev/null
+++ b/cloud/core/migrations/0001_thankful_chat.sql
@@ -0,0 +1,8 @@
+CREATE TABLE "account" (
+ "id" varchar(30) NOT NULL,
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone,
+ "email" varchar(255) NOT NULL
+);
+--> statement-breakpoint
+CREATE UNIQUE INDEX "email" ON "account" USING btree ("email"); \ No newline at end of file
diff --git a/cloud/core/migrations/0002_stale_jackal.sql b/cloud/core/migrations/0002_stale_jackal.sql
new file mode 100644
index 000000000..267dff273
--- /dev/null
+++ b/cloud/core/migrations/0002_stale_jackal.sql
@@ -0,0 +1,14 @@
+CREATE TABLE "key" (
+ "id" varchar(30) NOT NULL,
+ "workspace_id" varchar(30) NOT NULL,
+ "time_created" timestamp with time zone DEFAULT now() NOT NULL,
+ "time_deleted" timestamp with time zone,
+ "user_id" text NOT NULL,
+ "name" varchar(255) NOT NULL,
+ "key" varchar(255) NOT NULL,
+ "time_used" timestamp with time zone,
+ CONSTRAINT "key_workspace_id_id_pk" PRIMARY KEY("workspace_id","id")
+);
+--> statement-breakpoint
+ALTER TABLE "key" ADD CONSTRAINT "key_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+CREATE UNIQUE INDEX "global_key" ON "key" USING btree ("key"); \ No newline at end of file
diff --git a/cloud/core/migrations/0003_tranquil_spencer_smythe.sql b/cloud/core/migrations/0003_tranquil_spencer_smythe.sql
new file mode 100644
index 000000000..4f57f779f
--- /dev/null
+++ b/cloud/core/migrations/0003_tranquil_spencer_smythe.sql
@@ -0,0 +1 @@
+ALTER TABLE "usage" DROP COLUMN "request_id"; \ No newline at end of file
diff --git a/cloud/core/migrations/meta/0000_snapshot.json b/cloud/core/migrations/meta/0000_snapshot.json
new file mode 100644
index 000000000..3b86bed25
--- /dev/null
+++ b/cloud/core/migrations/meta/0000_snapshot.json
@@ -0,0 +1,461 @@
+{
+ "id": "9b5cec8c-8b59-4d7a-bb5c-76ade1c83d6f",
+ "prevId": "00000000-0000-0000-0000-000000000000",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.billing": {
+ "name": "billing",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_id": {
+ "name": "payment_method_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_last4": {
+ "name": "payment_method_last4",
+ "type": "varchar(4)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "balance": {
+ "name": "balance",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reload": {
+ "name": "reload",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "billing_workspace_id_workspace_id_fk": {
+ "name": "billing_workspace_id_workspace_id_fk",
+ "tableFrom": "billing",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "billing_workspace_id_id_pk": {
+ "name": "billing_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.payment": {
+ "name": "payment",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_id": {
+ "name": "payment_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "amount": {
+ "name": "amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "payment_workspace_id_workspace_id_fk": {
+ "name": "payment_workspace_id_workspace_id_fk",
+ "tableFrom": "payment",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "payment_workspace_id_id_pk": {
+ "name": "payment_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.usage": {
+ "name": "usage",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "request_id": {
+ "name": "request_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "input_tokens": {
+ "name": "input_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "output_tokens": {
+ "name": "output_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reasoning_tokens": {
+ "name": "reasoning_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_read_tokens": {
+ "name": "cache_read_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_write_tokens": {
+ "name": "cache_write_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cost": {
+ "name": "cost",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "usage_workspace_id_workspace_id_fk": {
+ "name": "usage_workspace_id_workspace_id_fk",
+ "tableFrom": "usage",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "usage_workspace_id_id_pk": {
+ "name": "usage_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.user": {
+ "name": "user",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_seen": {
+ "name": "time_seen",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "color": {
+ "name": "color",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "user_email": {
+ "name": "user_email",
+ "columns": [
+ {
+ "expression": "workspace_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "user_workspace_id_workspace_id_fk": {
+ "name": "user_workspace_id_workspace_id_fk",
+ "tableFrom": "user",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "user_workspace_id_id_pk": {
+ "name": "user_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.workspace": {
+ "name": "workspace",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "slug": {
+ "name": "slug",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+} \ No newline at end of file
diff --git a/cloud/core/migrations/meta/0001_snapshot.json b/cloud/core/migrations/meta/0001_snapshot.json
new file mode 100644
index 000000000..69d66ebc6
--- /dev/null
+++ b/cloud/core/migrations/meta/0001_snapshot.json
@@ -0,0 +1,515 @@
+{
+ "id": "bf9e9084-4073-4ecb-8e56-5610816c9589",
+ "prevId": "9b5cec8c-8b59-4d7a-bb5c-76ade1c83d6f",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.account": {
+ "name": "account",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "email": {
+ "name": "email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.billing": {
+ "name": "billing",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_id": {
+ "name": "payment_method_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_last4": {
+ "name": "payment_method_last4",
+ "type": "varchar(4)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "balance": {
+ "name": "balance",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reload": {
+ "name": "reload",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "billing_workspace_id_workspace_id_fk": {
+ "name": "billing_workspace_id_workspace_id_fk",
+ "tableFrom": "billing",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "billing_workspace_id_id_pk": {
+ "name": "billing_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.payment": {
+ "name": "payment",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_id": {
+ "name": "payment_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "amount": {
+ "name": "amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "payment_workspace_id_workspace_id_fk": {
+ "name": "payment_workspace_id_workspace_id_fk",
+ "tableFrom": "payment",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "payment_workspace_id_id_pk": {
+ "name": "payment_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.usage": {
+ "name": "usage",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "request_id": {
+ "name": "request_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "input_tokens": {
+ "name": "input_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "output_tokens": {
+ "name": "output_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reasoning_tokens": {
+ "name": "reasoning_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_read_tokens": {
+ "name": "cache_read_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_write_tokens": {
+ "name": "cache_write_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cost": {
+ "name": "cost",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "usage_workspace_id_workspace_id_fk": {
+ "name": "usage_workspace_id_workspace_id_fk",
+ "tableFrom": "usage",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "usage_workspace_id_id_pk": {
+ "name": "usage_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.user": {
+ "name": "user",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_seen": {
+ "name": "time_seen",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "color": {
+ "name": "color",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "user_email": {
+ "name": "user_email",
+ "columns": [
+ {
+ "expression": "workspace_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "user_workspace_id_workspace_id_fk": {
+ "name": "user_workspace_id_workspace_id_fk",
+ "tableFrom": "user",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "user_workspace_id_id_pk": {
+ "name": "user_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.workspace": {
+ "name": "workspace",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "slug": {
+ "name": "slug",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+} \ No newline at end of file
diff --git a/cloud/core/migrations/meta/0002_snapshot.json b/cloud/core/migrations/meta/0002_snapshot.json
new file mode 100644
index 000000000..7d970ab02
--- /dev/null
+++ b/cloud/core/migrations/meta/0002_snapshot.json
@@ -0,0 +1,615 @@
+{
+ "id": "351e4956-74e0-4282-a23b-02f1a73fa38c",
+ "prevId": "bf9e9084-4073-4ecb-8e56-5610816c9589",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.account": {
+ "name": "account",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "email": {
+ "name": "email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.billing": {
+ "name": "billing",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_id": {
+ "name": "payment_method_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_last4": {
+ "name": "payment_method_last4",
+ "type": "varchar(4)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "balance": {
+ "name": "balance",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reload": {
+ "name": "reload",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "billing_workspace_id_workspace_id_fk": {
+ "name": "billing_workspace_id_workspace_id_fk",
+ "tableFrom": "billing",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "billing_workspace_id_id_pk": {
+ "name": "billing_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.payment": {
+ "name": "payment",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_id": {
+ "name": "payment_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "amount": {
+ "name": "amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "payment_workspace_id_workspace_id_fk": {
+ "name": "payment_workspace_id_workspace_id_fk",
+ "tableFrom": "payment",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "payment_workspace_id_id_pk": {
+ "name": "payment_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.usage": {
+ "name": "usage",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "request_id": {
+ "name": "request_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "input_tokens": {
+ "name": "input_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "output_tokens": {
+ "name": "output_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reasoning_tokens": {
+ "name": "reasoning_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_read_tokens": {
+ "name": "cache_read_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_write_tokens": {
+ "name": "cache_write_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cost": {
+ "name": "cost",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "usage_workspace_id_workspace_id_fk": {
+ "name": "usage_workspace_id_workspace_id_fk",
+ "tableFrom": "usage",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "usage_workspace_id_id_pk": {
+ "name": "usage_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.key": {
+ "name": "key",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "key": {
+ "name": "key",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_used": {
+ "name": "time_used",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "global_key": {
+ "name": "global_key",
+ "columns": [
+ {
+ "expression": "key",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "key_workspace_id_workspace_id_fk": {
+ "name": "key_workspace_id_workspace_id_fk",
+ "tableFrom": "key",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "key_workspace_id_id_pk": {
+ "name": "key_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.user": {
+ "name": "user",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_seen": {
+ "name": "time_seen",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "color": {
+ "name": "color",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "user_email": {
+ "name": "user_email",
+ "columns": [
+ {
+ "expression": "workspace_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "user_workspace_id_workspace_id_fk": {
+ "name": "user_workspace_id_workspace_id_fk",
+ "tableFrom": "user",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "user_workspace_id_id_pk": {
+ "name": "user_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.workspace": {
+ "name": "workspace",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "slug": {
+ "name": "slug",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+} \ No newline at end of file
diff --git a/cloud/core/migrations/meta/0003_snapshot.json b/cloud/core/migrations/meta/0003_snapshot.json
new file mode 100644
index 000000000..e1202ddbf
--- /dev/null
+++ b/cloud/core/migrations/meta/0003_snapshot.json
@@ -0,0 +1,609 @@
+{
+ "id": "fa935883-9e51-4811-90c7-8967eefe458c",
+ "prevId": "351e4956-74e0-4282-a23b-02f1a73fa38c",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.account": {
+ "name": "account",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "email": {
+ "name": "email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.billing": {
+ "name": "billing",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_id": {
+ "name": "payment_method_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_method_last4": {
+ "name": "payment_method_last4",
+ "type": "varchar(4)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "balance": {
+ "name": "balance",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reload": {
+ "name": "reload",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "billing_workspace_id_workspace_id_fk": {
+ "name": "billing_workspace_id_workspace_id_fk",
+ "tableFrom": "billing",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "billing_workspace_id_id_pk": {
+ "name": "billing_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.payment": {
+ "name": "payment",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "customer_id": {
+ "name": "customer_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "payment_id": {
+ "name": "payment_id",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "amount": {
+ "name": "amount",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "payment_workspace_id_workspace_id_fk": {
+ "name": "payment_workspace_id_workspace_id_fk",
+ "tableFrom": "payment",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "payment_workspace_id_id_pk": {
+ "name": "payment_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.usage": {
+ "name": "usage",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "model": {
+ "name": "model",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "input_tokens": {
+ "name": "input_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "output_tokens": {
+ "name": "output_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "reasoning_tokens": {
+ "name": "reasoning_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_read_tokens": {
+ "name": "cache_read_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cache_write_tokens": {
+ "name": "cache_write_tokens",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cost": {
+ "name": "cost",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "usage_workspace_id_workspace_id_fk": {
+ "name": "usage_workspace_id_workspace_id_fk",
+ "tableFrom": "usage",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "usage_workspace_id_id_pk": {
+ "name": "usage_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.key": {
+ "name": "key",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "user_id": {
+ "name": "user_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "key": {
+ "name": "key",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_used": {
+ "name": "time_used",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "global_key": {
+ "name": "global_key",
+ "columns": [
+ {
+ "expression": "key",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "key_workspace_id_workspace_id_fk": {
+ "name": "key_workspace_id_workspace_id_fk",
+ "tableFrom": "key",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "key_workspace_id_id_pk": {
+ "name": "key_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.user": {
+ "name": "user",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "workspace_id": {
+ "name": "workspace_id",
+ "type": "varchar(30)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "time_seen": {
+ "name": "time_seen",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "color": {
+ "name": "color",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "user_email": {
+ "name": "user_email",
+ "columns": [
+ {
+ "expression": "workspace_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "user_workspace_id_workspace_id_fk": {
+ "name": "user_workspace_id_workspace_id_fk",
+ "tableFrom": "user",
+ "tableTo": "workspace",
+ "columnsFrom": [
+ "workspace_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "user_workspace_id_id_pk": {
+ "name": "user_workspace_id_id_pk",
+ "columns": [
+ "workspace_id",
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.workspace": {
+ "name": "workspace",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "varchar(30)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "name": {
+ "name": "name",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "time_created": {
+ "name": "time_created",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "time_deleted": {
+ "name": "time_deleted",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "slug": {
+ "name": "slug",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+} \ No newline at end of file
diff --git a/cloud/core/migrations/meta/_journal.json b/cloud/core/migrations/meta/_journal.json
new file mode 100644
index 000000000..ceba11e26
--- /dev/null
+++ b/cloud/core/migrations/meta/_journal.json
@@ -0,0 +1,34 @@
+{
+ "version": "7",
+ "dialect": "postgresql",
+ "entries": [
+ {
+ "idx": 0,
+ "version": "7",
+ "when": 1754518198186,
+ "tag": "0000_amused_mojo",
+ "breakpoints": true
+ },
+ {
+ "idx": 1,
+ "version": "7",
+ "when": 1754609655262,
+ "tag": "0001_thankful_chat",
+ "breakpoints": true
+ },
+ {
+ "idx": 2,
+ "version": "7",
+ "when": 1754627626945,
+ "tag": "0002_stale_jackal",
+ "breakpoints": true
+ },
+ {
+ "idx": 3,
+ "version": "7",
+ "when": 1754672464106,
+ "tag": "0003_tranquil_spencer_smythe",
+ "breakpoints": true
+ }
+ ]
+} \ No newline at end of file
diff --git a/cloud/core/package.json b/cloud/core/package.json
new file mode 100644
index 000000000..eeebf4392
--- /dev/null
+++ b/cloud/core/package.json
@@ -0,0 +1,22 @@
+{
+ "$schema": "https://json.schemastore.org/package.json",
+ "name": "@opencode/cloud-core",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "dependencies": {
+ "@aws-sdk/client-sts": "3.782.0",
+ "drizzle-orm": "0.41.0",
+ "stripe": "18.0.0",
+ "ulid": "3.0.0"
+ },
+ "exports": {
+ "./*": "./src/*"
+ },
+ "scripts": {
+ "db": "sst shell drizzle-kit"
+ },
+ "devDependencies": {
+ "drizzle-kit": "0.30.5"
+ }
+}
diff --git a/cloud/core/src/account.ts b/cloud/core/src/account.ts
new file mode 100644
index 000000000..cb123e048
--- /dev/null
+++ b/cloud/core/src/account.ts
@@ -0,0 +1,67 @@
+import { z } from "zod"
+import { and, eq, getTableColumns, isNull } from "drizzle-orm"
+import { fn } from "./util/fn"
+import { Database } from "./drizzle"
+import { Identifier } from "./identifier"
+import { AccountTable } from "./schema/account.sql"
+import { Actor } from "./actor"
+import { WorkspaceTable } from "./schema/workspace.sql"
+import { UserTable } from "./schema/user.sql"
+
+export namespace Account {
+ export const create = fn(
+ z.object({
+ email: z.string().email(),
+ id: z.string().optional(),
+ }),
+ async (input) =>
+ Database.transaction(async (tx) => {
+ const id = input.id ?? Identifier.create("account")
+ await tx.insert(AccountTable).values({
+ id,
+ email: input.email,
+ })
+ return id
+ }),
+ )
+
+ export const fromID = fn(z.string(), async (id) =>
+ Database.transaction(async (tx) => {
+ return tx
+ .select()
+ .from(AccountTable)
+ .where(eq(AccountTable.id, id))
+ .execute()
+ .then((rows) => rows[0])
+ }),
+ )
+
+ export const fromEmail = fn(z.string().email(), async (email) =>
+ Database.transaction(async (tx) => {
+ return tx
+ .select()
+ .from(AccountTable)
+ .where(eq(AccountTable.email, email))
+ .execute()
+ .then((rows) => rows[0])
+ }),
+ )
+
+ export const workspaces = async () => {
+ const actor = Actor.assert("account")
+ return Database.transaction(async (tx) =>
+ tx
+ .select(getTableColumns(WorkspaceTable))
+ .from(WorkspaceTable)
+ .innerJoin(UserTable, eq(UserTable.workspaceID, WorkspaceTable.id))
+ .where(
+ and(
+ eq(UserTable.email, actor.properties.email),
+ isNull(UserTable.timeDeleted),
+ isNull(WorkspaceTable.timeDeleted),
+ ),
+ )
+ .execute(),
+ )
+ }
+}
diff --git a/cloud/core/src/actor.ts b/cloud/core/src/actor.ts
new file mode 100644
index 000000000..beb292bb8
--- /dev/null
+++ b/cloud/core/src/actor.ts
@@ -0,0 +1,75 @@
+import { Context } from "./context"
+import { Log } from "./util/log"
+
+export namespace Actor {
+ interface Account {
+ type: "account"
+ properties: {
+ accountID: string
+ email: string
+ }
+ }
+
+ interface Public {
+ type: "public"
+ properties: {}
+ }
+
+ interface User {
+ type: "user"
+ properties: {
+ userID: string
+ workspaceID: string
+ email: string
+ }
+ }
+
+ interface System {
+ type: "system"
+ properties: {
+ workspaceID: string
+ }
+ }
+
+ export type Info = Account | Public | User | System
+
+ const ctx = Context.create<Info>()
+ export const use = ctx.use
+
+ const log = Log.create().tag("namespace", "actor")
+
+ export function provide<R, T extends Info["type"]>(
+ type: T,
+ properties: Extract<Info, { type: T }>["properties"],
+ cb: () => R,
+ ) {
+ return ctx.provide(
+ {
+ type,
+ properties,
+ } as any,
+ () => {
+ return Log.provide({ ...properties }, () => {
+ log.info("provided")
+ return cb()
+ })
+ },
+ )
+ }
+
+ export function assert<T extends Info["type"]>(type: T) {
+ const actor = use()
+ if (actor.type !== type) {
+ throw new Error(`Expected actor type ${type}, got ${actor.type}`)
+ }
+ return actor as Extract<Info, { type: T }>
+ }
+
+ export function workspace() {
+ const actor = use()
+ if ("workspaceID" in actor.properties) {
+ return actor.properties.workspaceID
+ }
+ throw new Error(`actor of type "${actor.type}" is not associated with a workspace`)
+ }
+}
diff --git a/cloud/core/src/billing.ts b/cloud/core/src/billing.ts
new file mode 100644
index 000000000..1a7bb2946
--- /dev/null
+++ b/cloud/core/src/billing.ts
@@ -0,0 +1,71 @@
+import { Resource } from "sst"
+import { Stripe } from "stripe"
+import { Database, eq, sql } from "./drizzle"
+import { BillingTable, UsageTable } from "./schema/billing.sql"
+import { Actor } from "./actor"
+import { fn } from "./util/fn"
+import { z } from "zod"
+import { Identifier } from "./identifier"
+import { centsToMicroCents } from "./util/price"
+
+export namespace Billing {
+ export const stripe = () =>
+ new Stripe(Resource.STRIPE_SECRET_KEY.value, {
+ apiVersion: "2025-03-31.basil",
+ })
+
+ export const get = async () => {
+ return Database.use(async (tx) =>
+ tx
+ .select({
+ customerID: BillingTable.customerID,
+ paymentMethodID: BillingTable.paymentMethodID,
+ balance: BillingTable.balance,
+ reload: BillingTable.reload,
+ })
+ .from(BillingTable)
+ .where(eq(BillingTable.workspaceID, Actor.workspace()))
+ .then((r) => r[0]),
+ )
+ }
+
+ export const consume = fn(
+ z.object({
+ requestID: z.string().optional(),
+ model: z.string(),
+ inputTokens: z.number(),
+ outputTokens: z.number(),
+ reasoningTokens: z.number().optional(),
+ cacheReadTokens: z.number().optional(),
+ cacheWriteTokens: z.number().optional(),
+ costInCents: z.number(),
+ }),
+ async (input) => {
+ const workspaceID = Actor.workspace()
+ const cost = centsToMicroCents(input.costInCents)
+
+ return await Database.transaction(async (tx) => {
+ await tx.insert(UsageTable).values({
+ workspaceID,
+ id: Identifier.create("usage"),
+ requestID: input.requestID,
+ model: input.model,
+ inputTokens: input.inputTokens,
+ outputTokens: input.outputTokens,
+ reasoningTokens: input.reasoningTokens,
+ cacheReadTokens: input.cacheReadTokens,
+ cacheWriteTokens: input.cacheWriteTokens,
+ cost,
+ })
+ const [updated] = await tx
+ .update(BillingTable)
+ .set({
+ balance: sql`${BillingTable.balance} - ${cost}`,
+ })
+ .where(eq(BillingTable.workspaceID, workspaceID))
+ .returning()
+ return updated.balance
+ })
+ },
+ )
+}
diff --git a/cloud/core/src/context.ts b/cloud/core/src/context.ts
new file mode 100644
index 000000000..c2ca6a313
--- /dev/null
+++ b/cloud/core/src/context.ts
@@ -0,0 +1,21 @@
+import { AsyncLocalStorage } from "node:async_hooks"
+
+export namespace Context {
+ export class NotFound extends Error {}
+
+ export function create<T>() {
+ const storage = new AsyncLocalStorage<T>()
+ return {
+ use() {
+ const result = storage.getStore()
+ if (!result) {
+ throw new NotFound()
+ }
+ return result
+ },
+ provide<R>(value: T, fn: () => R) {
+ return storage.run<R>(value, fn)
+ },
+ }
+ }
+}
diff --git a/cloud/core/src/drizzle/index.ts b/cloud/core/src/drizzle/index.ts
new file mode 100644
index 000000000..76220f2a2
--- /dev/null
+++ b/cloud/core/src/drizzle/index.ts
@@ -0,0 +1,94 @@
+import { drizzle } from "drizzle-orm/postgres-js"
+import { Resource } from "sst"
+export * from "drizzle-orm"
+import postgres from "postgres"
+
+function createClient() {
+ const client = postgres({
+ idle_timeout: 30000,
+ connect_timeout: 30000,
+ host: Resource.Database.host,
+ database: Resource.Database.database,
+ user: Resource.Database.username,
+ password: Resource.Database.password,
+ port: Resource.Database.port,
+ ssl: {
+ rejectUnauthorized: false,
+ },
+ max: 1,
+ })
+
+ return drizzle(client, {})
+}
+
+import { PgTransaction, type PgTransactionConfig } from "drizzle-orm/pg-core"
+import type { ExtractTablesWithRelations } from "drizzle-orm"
+import type { PostgresJsQueryResultHKT } from "drizzle-orm/postgres-js"
+import { Context } from "../context"
+
+export namespace Database {
+ export type Transaction = PgTransaction<
+ PostgresJsQueryResultHKT,
+ Record<string, unknown>,
+ ExtractTablesWithRelations<Record<string, unknown>>
+ >
+
+ export type TxOrDb = Transaction | ReturnType<typeof createClient>
+
+ const TransactionContext = Context.create<{
+ tx: TxOrDb
+ effects: (() => void | Promise<void>)[]
+ }>()
+
+ export async function use<T>(callback: (trx: TxOrDb) => Promise<T>) {
+ try {
+ const { tx } = TransactionContext.use()
+ return tx.transaction(callback)
+ } catch (err) {
+ if (err instanceof Context.NotFound) {
+ const client = createClient()
+ const effects: (() => void | Promise<void>)[] = []
+ const result = await TransactionContext.provide(
+ {
+ effects,
+ tx: client,
+ },
+ () => callback(client),
+ )
+ await Promise.all(effects.map((x) => x()))
+ return result
+ }
+ throw err
+ }
+ }
+ export async function fn<Input, T>(callback: (input: Input, trx: TxOrDb) => Promise<T>) {
+ return (input: Input) => use(async (tx) => callback(input, tx))
+ }
+
+ export async function effect(effect: () => any | Promise<any>) {
+ try {
+ const { effects } = TransactionContext.use()
+ effects.push(effect)
+ } catch {
+ await effect()
+ }
+ }
+
+ export async function transaction<T>(callback: (tx: TxOrDb) => Promise<T>, config?: PgTransactionConfig) {
+ try {
+ const { tx } = TransactionContext.use()
+ return callback(tx)
+ } catch (err) {
+ if (err instanceof Context.NotFound) {
+ const client = createClient()
+ const effects: (() => void | Promise<void>)[] = []
+ const result = await client.transaction(async (tx) => {
+ return TransactionContext.provide({ tx, effects }, () => callback(tx))
+ }, config)
+ await Promise.all(effects.map((x) => x()))
+ return result
+ }
+ throw err
+ }
+ }
+}
diff --git a/cloud/core/src/drizzle/types.ts b/cloud/core/src/drizzle/types.ts
new file mode 100644
index 000000000..5ae95d011
--- /dev/null
+++ b/cloud/core/src/drizzle/types.ts
@@ -0,0 +1,29 @@
+import { bigint, timestamp, varchar } from "drizzle-orm/pg-core"
+
+export const ulid = (name: string) => varchar(name, { length: 30 })
+
+export const workspaceColumns = {
+ get id() {
+ return ulid("id").notNull()
+ },
+ get workspaceID() {
+ return ulid("workspace_id").notNull()
+ },
+}
+
+export const id = () => ulid("id").notNull()
+
+export const utc = (name: string) =>
+ timestamp(name, {
+ withTimezone: true,
+ })
+
+export const currency = (name: string) =>
+ bigint(name, {
+ mode: "number",
+ })
+
+export const timestamps = {
+ timeCreated: utc("time_created").notNull().defaultNow(),
+ timeDeleted: utc("time_deleted"),
+}
diff --git a/cloud/core/src/identifier.ts b/cloud/core/src/identifier.ts
new file mode 100644
index 000000000..f8e73852e
--- /dev/null
+++ b/cloud/core/src/identifier.ts
@@ -0,0 +1,26 @@
+import { ulid } from "ulid"
+import { z } from "zod"
+
+export namespace Identifier {
+ const prefixes = {
+ account: "acc",
+ billing: "bil",
+ key: "key",
+ payment: "pay",
+ usage: "usg",
+ user: "usr",
+ workspace: "wrk",
+ } as const
+
+ export function create(prefix: keyof typeof prefixes, given?: string): string {
+ if (given) {
+ if (given.startsWith(prefixes[prefix])) return given
+ throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`)
+ }
+ return [prefixes[prefix], ulid()].join("_")
+ }
+
+ export function schema(prefix: keyof typeof prefixes) {
+ return z.string().startsWith(prefixes[prefix])
+ }
+}
diff --git a/cloud/core/src/schema/account.sql.ts b/cloud/core/src/schema/account.sql.ts
new file mode 100644
index 000000000..1733f0a15
--- /dev/null
+++ b/cloud/core/src/schema/account.sql.ts
@@ -0,0 +1,12 @@
+import { pgTable, uniqueIndex, varchar } from "drizzle-orm/pg-core"
+import { id, timestamps } from "../drizzle/types"
+
+export const AccountTable = pgTable(
+ "account",
+ {
+ id: id(),
+ ...timestamps,
+ email: varchar("email", { length: 255 }).notNull(),
+ },
+ (table) => [uniqueIndex("email").on(table.email)],
+)
diff --git a/cloud/core/src/schema/billing.sql.ts b/cloud/core/src/schema/billing.sql.ts
new file mode 100644
index 000000000..96b29f5de
--- /dev/null
+++ b/cloud/core/src/schema/billing.sql.ts
@@ -0,0 +1,45 @@
+import { bigint, boolean, integer, pgTable, varchar } from "drizzle-orm/pg-core"
+import { timestamps, workspaceColumns } from "../drizzle/types"
+import { workspaceIndexes } from "./workspace.sql"
+
+export const BillingTable = pgTable(
+ "billing",
+ {
+ ...workspaceColumns,
+ ...timestamps,
+ customerID: varchar("customer_id", { length: 255 }),
+ paymentMethodID: varchar("payment_method_id", { length: 255 }),
+ paymentMethodLast4: varchar("payment_method_last4", { length: 4 }),
+ balance: bigint("balance", { mode: "number" }).notNull(),
+ reload: boolean("reload"),
+ },
+ (table) => [...workspaceIndexes(table)],
+)
+
+export const PaymentTable = pgTable(
+ "payment",
+ {
+ ...workspaceColumns,
+ ...timestamps,
+ customerID: varchar("customer_id", { length: 255 }),
+ paymentID: varchar("payment_id", { length: 255 }),
+ amount: bigint("amount", { mode: "number" }).notNull(),
+ },
+ (table) => [...workspaceIndexes(table)],
+)
+
+export const UsageTable = pgTable(
+ "usage",
+ {
+ ...workspaceColumns,
+ ...timestamps,
+ model: varchar("model", { length: 255 }).notNull(),
+ inputTokens: integer("input_tokens").notNull(),
+ outputTokens: integer("output_tokens").notNull(),
+ reasoningTokens: integer("reasoning_tokens"),
+ cacheReadTokens: integer("cache_read_tokens"),
+ cacheWriteTokens: integer("cache_write_tokens"),
+ cost: bigint("cost", { mode: "number" }).notNull(),
+ },
+ (table) => [...workspaceIndexes(table)],
+)
diff --git a/cloud/core/src/schema/key.sql.ts b/cloud/core/src/schema/key.sql.ts
new file mode 100644
index 000000000..240736b86
--- /dev/null
+++ b/cloud/core/src/schema/key.sql.ts
@@ -0,0 +1,16 @@
+import { text, pgTable, varchar, uniqueIndex } from "drizzle-orm/pg-core"
+import { timestamps, utc, workspaceColumns } from "../drizzle/types"
+import { workspaceIndexes } from "./workspace.sql"
+
+export const KeyTable = pgTable(
+ "key",
+ {
+ ...workspaceColumns,
+ ...timestamps,
+ userID: text("user_id").notNull(),
+ name: varchar("name", { length: 255 }).notNull(),
+ key: varchar("key", { length: 255 }).notNull(),
+ timeUsed: utc("time_used"),
+ },
+ (table) => [...workspaceIndexes(table), uniqueIndex("global_key").on(table.key)],
+)
diff --git a/cloud/core/src/schema/user.sql.ts b/cloud/core/src/schema/user.sql.ts
new file mode 100644
index 000000000..34cbd6beb
--- /dev/null
+++ b/cloud/core/src/schema/user.sql.ts
@@ -0,0 +1,16 @@
+import { text, pgTable, uniqueIndex, varchar, integer } from "drizzle-orm/pg-core"
+import { timestamps, utc, workspaceColumns } from "../drizzle/types"
+import { workspaceIndexes } from "./workspace.sql"
+
+export const UserTable = pgTable(
+ "user",
+ {
+ ...workspaceColumns,
+ ...timestamps,
+ email: text("email").notNull(),
+ name: varchar("name", { length: 255 }).notNull(),
+ timeSeen: utc("time_seen"),
+ color: integer("color"),
+ },
+ (table) => [...workspaceIndexes(table), uniqueIndex("user_email").on(table.workspaceID, table.email)],
+)
diff --git a/cloud/core/src/schema/workspace.sql.ts b/cloud/core/src/schema/workspace.sql.ts
new file mode 100644
index 000000000..3e9379e1f
--- /dev/null
+++ b/cloud/core/src/schema/workspace.sql.ts
@@ -0,0 +1,25 @@
+import { primaryKey, foreignKey, pgTable, uniqueIndex, varchar } from "drizzle-orm/pg-core"
+import { timestamps, ulid } from "../drizzle/types"
+
+export const WorkspaceTable = pgTable(
+ "workspace",
+ {
+ id: ulid("id").notNull().primaryKey(),
+ slug: varchar("slug", { length: 255 }),
+ name: varchar("name", { length: 255 }),
+ ...timestamps,
+ },
+ (table) => [uniqueIndex("slug").on(table.slug)],
+)
+
+export function workspaceIndexes(table: any) {
+ return [
+ primaryKey({
+ columns: [table.workspaceID, table.id],
+ }),
+ foreignKey({
+ foreignColumns: [WorkspaceTable.id],
+ columns: [table.workspaceID],
+ }),
+ ]
+}
diff --git a/cloud/core/src/util/fn.ts b/cloud/core/src/util/fn.ts
new file mode 100644
index 000000000..038a50719
--- /dev/null
+++ b/cloud/core/src/util/fn.ts
@@ -0,0 +1,14 @@
+import { z } from "zod"
+
+export function fn<T extends z.ZodType, Result>(
+ schema: T,
+ cb: (input: z.output<T>) => Result,
+) {
+ const result = (input: z.input<T>) => {
+ const parsed = schema.parse(input)
+ return cb(parsed)
+ }
+ result.force = (input: z.input<T>) => cb(input)
+ result.schema = schema
+ return result
+}
diff --git a/cloud/core/src/util/log.ts b/cloud/core/src/util/log.ts
new file mode 100644
index 000000000..4f2d25c13
--- /dev/null
+++ b/cloud/core/src/util/log.ts
@@ -0,0 +1,55 @@
+import { Context } from "../context"
+
+export namespace Log {
+ const ctx = Context.create<{
+ tags: Record<string, any>
+ }>()
+
+ export function create(tags?: Record<string, any>) {
+ tags = tags || {}
+
+ const result = {
+ info(message?: any, extra?: Record<string, any>) {
+ const prefix = Object.entries({
+ ...use().tags,
+ ...tags,
+ ...extra,
+ })
+ .map(([key, value]) => `${key}=${value}`)
+ .join(" ")
+ console.log(prefix, message)
+ return result
+ },
+ tag(key: string, value: string) {
+ if (tags) tags[key] = value
+ return result
+ },
+ clone() {
+ return Log.create({ ...tags })
+ },
+ }
+
+ return result
+ }
+
+ export function provide<R>(tags: Record<string, any>, cb: () => R) {
+ const existing = use()
+ return ctx.provide(
+ {
+ tags: {
+ ...existing.tags,
+ ...tags,
+ },
+ },
+ cb,
+ )
+ }
+
+ function use() {
+ try {
+ return ctx.use()
+ } catch (e) {
+ return { tags: {} }
+ }
+ }
+}
diff --git a/cloud/core/src/util/price.ts b/cloud/core/src/util/price.ts
new file mode 100644
index 000000000..abdbca032
--- /dev/null
+++ b/cloud/core/src/util/price.ts
@@ -0,0 +1,3 @@
+export function centsToMicroCents(amount: number) {
+ return Math.round(amount * 1000000)
+}
diff --git a/cloud/core/src/workspace.ts b/cloud/core/src/workspace.ts
new file mode 100644
index 000000000..532b22963
--- /dev/null
+++ b/cloud/core/src/workspace.ts
@@ -0,0 +1,48 @@
+import { z } from "zod"
+import { fn } from "./util/fn"
+import { centsToMicroCents } from "./util/price"
+import { Actor } from "./actor"
+import { Database, eq } from "./drizzle"
+import { Identifier } from "./identifier"
+import { UserTable } from "./schema/user.sql"
+import { BillingTable } from "./schema/billing.sql"
+import { WorkspaceTable } from "./schema/workspace.sql"
+
+export namespace Workspace {
+ export const create = fn(z.void(), async () => {
+ const account = Actor.assert("account")
+ const workspaceID = Identifier.create("workspace")
+ await Database.transaction(async (tx) => {
+ await tx.insert(WorkspaceTable).values({
+ id: workspaceID,
+ })
+ await tx.insert(UserTable).values({
+ workspaceID,
+ id: Identifier.create("user"),
+ email: account.properties.email,
+ name: "",
+ })
+ await tx.insert(BillingTable).values({
+ workspaceID,
+ id: Identifier.create("billing"),
+ balance: centsToMicroCents(100),
+ })
+ })
+ return workspaceID
+ })
+
+ export async function list() {
+ const account = Actor.assert("account")
+ return Database.use(async (tx) => {
+ return tx
+ .select({
+ id: WorkspaceTable.id,
+ slug: WorkspaceTable.slug,
+ name: WorkspaceTable.name,
+ })
+ .from(UserTable)
+ .innerJoin(WorkspaceTable, eq(UserTable.workspaceID, WorkspaceTable.id))
+ .where(eq(UserTable.email, account.properties.email))
+ })
+ }
+}
diff --git a/cloud/core/sst-env.d.ts b/cloud/core/sst-env.d.ts
new file mode 100644
index 000000000..b6a7e9066
--- /dev/null
+++ b/cloud/core/sst-env.d.ts
@@ -0,0 +1,9 @@
+/* This file is auto-generated by SST. Do not edit. */
+/* tslint:disable */
+/* eslint-disable */
+/* deno-fmt-ignore-file */
+
+/// <reference path="../../sst-env.d.ts" />
+
+import "sst"
+export {} \ No newline at end of file
diff --git a/cloud/core/tsconfig.json b/cloud/core/tsconfig.json
new file mode 100644
index 000000000..0faf16aab
--- /dev/null
+++ b/cloud/core/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "@tsconfig/node22/tsconfig.json",
+ "compilerOptions": {
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "types": ["@cloudflare/workers-types", "node"]
+ }
+}