| 1 | import type { |
| 2 | RelayAgentActivityAggregateState, |
| 3 | RelayAgentActivityState, |
| 4 | RelayAgentAwarenessPreferences, |
| 5 | RelayManagedEndpointOrigin, |
| 6 | } from "@t3tools/contracts/relay"; |
| 7 | import { |
| 8 | boolean, |
| 9 | index, |
| 10 | integer, |
| 11 | jsonb, |
| 12 | pgTable, |
| 13 | primaryKey, |
| 14 | text, |
| 15 | uniqueIndex, |
| 16 | varchar, |
| 17 | } from "drizzle-orm/pg-core"; |
| 18 | |
| 19 | export const relayMobileDevices = pgTable( |
| 20 | "relay_mobile_devices", |
| 21 | { |
| 22 | userId: varchar("user_id", { length: 255 }).notNull(), |
| 23 | deviceId: varchar("device_id", { length: 255 }).notNull(), |
| 24 | label: text("label").notNull().default("iOS device"), |
| 25 | platform: varchar("platform", { length: 16 }).notNull().$type<"ios" | "android">(), |
| 26 | iosMajorVersion: integer("ios_major_version"), |
| 27 | androidApiLevel: integer("android_api_level"), |
| 28 | appVersion: varchar("app_version", { length: 64 }), |
| 29 | bundleId: varchar("bundle_id", { length: 255 }), |
| 30 | apsEnvironment: varchar("aps_environment", { length: 16 }).$type<"sandbox" | "production">(), |
| 31 | pushToken: text("push_token"), |
| 32 | pushToStartToken: text("push_to_start_token"), |
| 33 | preferencesJson: jsonb("preferences_json").notNull().$type<RelayAgentAwarenessPreferences>(), |
| 34 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 35 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 36 | }, |
| 37 | (table) => [ |
| 38 | primaryKey({ columns: [table.userId, table.deviceId] }), |
| 39 | uniqueIndex("idx_relay_mobile_devices_push_token").on(table.pushToken), |
| 40 | uniqueIndex("idx_relay_mobile_devices_push_to_start_token").on(table.pushToStartToken), |
| 41 | ], |
| 42 | ); |
| 43 | |
| 44 | export const relayLiveActivities = pgTable( |
| 45 | "relay_live_activities", |
| 46 | { |
| 47 | userId: varchar("user_id", { length: 255 }).notNull(), |
| 48 | deviceId: varchar("device_id", { length: 255 }).notNull(), |
| 49 | activityPushToken: text("activity_push_token"), |
| 50 | remoteStartQueuedAt: varchar("remote_start_queued_at", { length: 64 }), |
| 51 | remoteStartedAt: varchar("remote_started_at", { length: 64 }), |
| 52 | endedAt: varchar("ended_at", { length: 64 }), |
| 53 | lastAggregateJson: jsonb("last_aggregate_json").$type<RelayAgentActivityAggregateState>(), |
| 54 | lastLiveActivityDeliveryAt: varchar("last_live_activity_delivery_at", { length: 64 }), |
| 55 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 56 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 57 | }, |
| 58 | (table) => [ |
| 59 | primaryKey({ columns: [table.userId, table.deviceId] }), |
| 60 | uniqueIndex("idx_relay_live_activities_activity_push_token").on(table.activityPushToken), |
| 61 | ], |
| 62 | ); |
| 63 | |
| 64 | export const relayEnvironmentLinks = pgTable( |
| 65 | "relay_environment_links", |
| 66 | { |
| 67 | userId: varchar("user_id", { length: 191 }).notNull(), |
| 68 | environmentId: varchar("environment_id", { length: 191 }).notNull(), |
| 69 | environmentLabel: text("environment_label").notNull().default("T3 Environment"), |
| 70 | environmentPublicKey: text("environment_public_key").notNull(), |
| 71 | endpointHttpBaseUrl: text("endpoint_http_base_url").notNull(), |
| 72 | endpointWsBaseUrl: text("endpoint_ws_base_url").notNull(), |
| 73 | endpointProviderKind: varchar("endpoint_provider_kind", { length: 32 }).notNull(), |
| 74 | notificationsEnabled: boolean("notifications_enabled").notNull().default(true), |
| 75 | liveActivitiesEnabled: boolean("live_activities_enabled").notNull().default(true), |
| 76 | managedTunnelsEnabled: boolean("managed_tunnels_enabled").notNull().default(false), |
| 77 | // Opt-in: hold webhook requests while the environment is offline. |
| 78 | holdWebhooksWhileOffline: boolean("hold_webhooks_while_offline").notNull().default(false), |
| 79 | createdByDeviceId: varchar("created_by_device_id", { length: 191 }), |
| 80 | revokedAt: varchar("revoked_at", { length: 64 }), |
| 81 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 82 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 83 | }, |
| 84 | (table) => [ |
| 85 | primaryKey({ columns: [table.userId, table.environmentId] }), |
| 86 | index("idx_relay_environment_links_environment").on(table.environmentId, table.revokedAt), |
| 87 | ], |
| 88 | ); |
| 89 | |
| 90 | export const relayManagedEndpointAllocations = pgTable( |
| 91 | "relay_managed_endpoint_allocations", |
| 92 | { |
| 93 | userId: varchar("user_id", { length: 191 }).notNull(), |
| 94 | environmentId: varchar("environment_id", { length: 191 }).notNull(), |
| 95 | hostname: text("hostname").notNull(), |
| 96 | tunnelId: varchar("tunnel_id", { length: 191 }), |
| 97 | tunnelName: text("tunnel_name").notNull(), |
| 98 | dnsRecordId: varchar("dns_record_id", { length: 191 }), |
| 99 | readyAt: varchar("ready_at", { length: 64 }), |
| 100 | recoveryEnabledAt: varchar("recovery_enabled_at", { length: 64 }), |
| 101 | recoveryEnvironmentPublicKey: text("recovery_environment_public_key"), |
| 102 | // Set when cleanup deletes the recorded tunnel; cleared when a tunnel is recorded again. |
| 103 | tunnelReleasedAt: varchar("tunnel_released_at", { length: 64 }), |
| 104 | origin: jsonb("origin").$type<RelayManagedEndpointOrigin>(), |
| 105 | generation: integer("generation").notNull().default(0), |
| 106 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 107 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 108 | }, |
| 109 | (table) => [ |
| 110 | primaryKey({ columns: [table.userId, table.environmentId] }), |
| 111 | uniqueIndex("idx_relay_managed_endpoint_allocations_hostname").on(table.hostname), |
| 112 | uniqueIndex("idx_relay_managed_endpoint_allocations_tunnel_name").on(table.tunnelName), |
| 113 | ], |
| 114 | ); |
| 115 | |
| 116 | export const relayManagedTunnelLimits = pgTable("relay_managed_tunnel_limits", { |
| 117 | userId: varchar("user_id", { length: 191 }).primaryKey(), |
| 118 | maxTunnels: integer("max_tunnels").notNull(), |
| 119 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 120 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 121 | }); |
| 122 | |
| 123 | export const relayEnvironmentCredentials = pgTable( |
| 124 | "relay_environment_credentials", |
| 125 | { |
| 126 | credentialId: varchar("credential_id", { length: 64 }).primaryKey(), |
| 127 | environmentId: varchar("environment_id", { length: 191 }).notNull(), |
| 128 | environmentPublicKey: text("environment_public_key").notNull(), |
| 129 | credentialHash: varchar("credential_hash", { length: 191 }).notNull(), |
| 130 | revokedAt: varchar("revoked_at", { length: 64 }), |
| 131 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 132 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 133 | }, |
| 134 | (table) => [ |
| 135 | uniqueIndex("idx_relay_environment_credentials_hash").on(table.credentialHash), |
| 136 | index("idx_relay_environment_credentials_environment").on(table.environmentId, table.revokedAt), |
| 137 | index("idx_relay_environment_credentials_environment_key").on( |
| 138 | table.environmentId, |
| 139 | table.environmentPublicKey, |
| 140 | table.revokedAt, |
| 141 | ), |
| 142 | ], |
| 143 | ); |
| 144 | |
| 145 | export const relayAgentActivityRows = pgTable( |
| 146 | "relay_agent_activity_rows", |
| 147 | { |
| 148 | environmentId: varchar("environment_id", { length: 191 }).notNull(), |
| 149 | environmentPublicKey: text("environment_public_key").notNull(), |
| 150 | threadId: varchar("thread_id", { length: 512 }).notNull(), |
| 151 | stateJson: jsonb("state_json").notNull().$type<RelayAgentActivityState>(), |
| 152 | updatedAt: varchar("updated_at", { length: 64 }).notNull(), |
| 153 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 154 | }, |
| 155 | (table) => [ |
| 156 | primaryKey({ columns: [table.environmentId, table.environmentPublicKey, table.threadId] }), |
| 157 | index("idx_relay_agent_activity_rows_updated").on(table.updatedAt), |
| 158 | ], |
| 159 | ); |
| 160 | |
| 161 | export const relayDeliveryAttempts = pgTable( |
| 162 | "relay_delivery_attempts", |
| 163 | { |
| 164 | id: varchar("id", { length: 36 }).primaryKey(), |
| 165 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 166 | userId: varchar("user_id", { length: 255 }), |
| 167 | environmentId: varchar("environment_id", { length: 191 }), |
| 168 | threadId: varchar("thread_id", { length: 512 }), |
| 169 | deviceId: varchar("device_id", { length: 255 }), |
| 170 | kind: varchar("kind", { length: 64 }).notNull(), |
| 171 | sourceJobId: varchar("source_job_id", { length: 64 }), |
| 172 | tokenSuffix: varchar("token_suffix", { length: 16 }), |
| 173 | apnsStatus: integer("apns_status"), |
| 174 | apnsReason: text("apns_reason"), |
| 175 | apnsId: varchar("apns_id", { length: 128 }), |
| 176 | transportError: text("transport_error"), |
| 177 | }, |
| 178 | (table) => [ |
| 179 | index("idx_relay_delivery_attempts_environment").on( |
| 180 | table.environmentId, |
| 181 | table.threadId, |
| 182 | table.createdAt, |
| 183 | ), |
| 184 | uniqueIndex("idx_relay_delivery_attempts_source_job").on(table.sourceJobId), |
| 185 | ], |
| 186 | ); |
| 187 | |
| 188 | export const relayDpopProofs = pgTable( |
| 189 | "relay_dpop_proofs", |
| 190 | { |
| 191 | thumbprint: varchar("thumbprint", { length: 128 }).notNull(), |
| 192 | jti: varchar("jti", { length: 255 }).notNull(), |
| 193 | iat: integer("iat").notNull(), |
| 194 | expiresAt: varchar("expires_at", { length: 64 }).notNull(), |
| 195 | createdAt: varchar("created_at", { length: 64 }).notNull(), |
| 196 | }, |
| 197 | (table) => [ |
| 198 | primaryKey({ columns: [table.thumbprint, table.jti] }), |
| 199 | index("idx_relay_dpop_proofs_expires_at").on(table.expiresAt), |
| 200 | ], |
| 201 | ); |