diff --git a/docs/widget-sso.md b/docs/widget-sso.md index 0a37a2cba..5026c30d3 100644 --- a/docs/widget-sso.md +++ b/docs/widget-sso.md @@ -22,22 +22,34 @@ Secrets are **never auto-created** — merely probing an org id cannot materiali | Claim | Value | Why | | --- | --- | --- | | `aud` | **Your workspace id** (from the widget config) | Pins the token to exactly one workspace. A token minted for workspace A is rejected at workspace B even if both secrets leaked. | -| `userId` | Your stable id for this user | Used as the contact's `externalId` and to dedupe the SSO user. | +| `sub` | Your stable id for this user | Used as the contact's `externalId` and to dedupe the SSO user. | | `email` | User's email | Required; the SSO session and contact are keyed on it. | | `name` | Display name | Required. | +| `exp` | UNIX timestamp; keep it short (≤ 5 minutes is plenty) | **Required and enforced.** Tokens without `exp` are rejected. | `aud` must be a **single string** — an array or a missing/`iss`-only token is rejected. +`sub` replaced the legacy `userId` claim. `userId` is still **accepted as a fallback** while customers migrate, but a token carrying **both** `sub` and `userId` with different values is rejected as a conflict. The `userId` fallback is scheduled for removal **after 2026-12-31** — mint `sub` in new integrations today. + +### Enforced at verification time + +Beyond the signature and the required claims, `verifyJwt` enforces (all failures map to `INVALID_JWT`): + +- **`exp` required** — a token without it is rejected after the signature verifies. +- **Total lifetime capped**: `exp - iat` (or `exp - now` when `iat` is absent) may not exceed the workspace cap — **24 hours by default**, overridable per workspace via `organization.jwt_max_token_lifetime_minutes` (contact support to tighten it; shortening the cap is the only supported direction). A token claiming `exp = now + 30 days` is rejected even though the signature is valid. Keep minting short-lived tokens (≤ 5 minutes); the cap only bounds the worst case for a leaked token. +- **`iat` not in the future** — more than 30s ahead of Feeblo's clock is rejected. +- **30s clock-skew leeway** for `exp`/`nbf`/`iat` checks, so a slightly-skewed issuer clock does not break sign-ins. + ### Recommended claims | Claim | Value | Why | | --- | --- | --- | -| `exp` | UNIX timestamp; keep it short (≤ 5 minutes is plenty) | Not required, but **strongly recommended**: if present it is validated (an expired token is rejected), it bounds the 24h rotation grace window, and it limits how long a leaked token stays valid. | +| `iss` | Your app URL (e.g. `https://app.example.com`) | Not verified yet — the issuer is stored unverified. Setting it now means the workspace can be migrated to issuer verification (planned to be promoted to required) without a second token change. Until then it is informational only. | ### Optional claims - `avatar` — profile image URL. -- Custom attribute values and nested `companies` (see `packages/domain/src/contact/utils.ts` `parsePersonAttributes` for the exact shape; attribute definitions are configured per workspace). +- Custom attribute values and nested `companies` (see `packages/domain/src/contact/utils.ts` `parsePersonAttributes` for the exact shape; attribute definitions are configured per workspace). Attribute values must be **JSON scalars** (string, number, boolean, null); arrays and nested objects are **ignored** — they are never persisted or rendered. ## Example (Node.js, `jose`) @@ -48,21 +60,23 @@ const workspaceId = process.env.FEEBLO_WORKSPACE_ID; // from the widget config const secret = process.env.FEEBLO_SSO_SECRET; // from Settings → Security (64-char hex) const token = await new SignJWT({ - userId: user.id, + sub: user.id, email: user.email, name: user.name, // custom attributes: { email: { value: user.plan } } … }) .setProtectedHeader({ alg: "HS256" }) .setAudience(workspaceId) // REQUIRED — binds to the workspace - .setExpirationTime("5m") // strongly recommended, optional + .setIssuer("https://app.example.com") // recommended — issuer verification coming + .setIssuedAt() // recommended — required for the lifetime cap to use real mint time + .setExpirationTime("5m") // REQUIRED .sign(new Uint8Array(Buffer.from(secret, "hex"))); ``` ## Rotation & revocation - **Rotate** (Settings → Security): the current secret is revoked and a new one becomes active. Tokens signed with the previous secret keep verifying for a **24-hour grace period**, so rotate at a low-traffic moment and mint tokens with short `exp` values. -- **Revoke immediately**: the secret is dropped right away; tokens signed with it stop working immediately. +- **Revoke immediately**: the secret is dropped right away (its tokens stop verifying immediately), and a new secret is generated. The grace period still applies to the immediately-revoked secret. - Only the active secret plus the most recent grace-period secret are ever accepted. Expired revoked secrets are pruned. ## Error codes @@ -72,8 +86,8 @@ The SSO endpoint maps failures to better-auth errors via the `jwt-auto-login` pl | Code | Meaning | | --- | --- | | `ORGANIZATION_HAS_NO_JWT_SECRET` | No secret generated yet; generate one in Settings → Security. | -| `INVALID_JWT` | Signature invalid, wrong `aud`, an expired `exp` (when present), or wrong/leaked secret. | -| `SSO_TOKEN_MISSING_EMAIL_OR_NAME` | Required `email`/`name` (or `userId`) missing. | +| `INVALID_JWT` | Signature invalid, wrong/missing `aud`, missing `exp`, expired `exp` (beyond leeway), `iat` too far in the future, token lifetime beyond the workspace cap, conflicting `sub`/`userId`, or wrong/leaked secret. | +| `SSO_TOKEN_MISSING_EMAIL_OR_NAME` | Required `email`/`name` (or `sub`) missing. | | `FAILED_TO_CREATE_SSO_USER` / `FAILED_TO_CREATE_SSO_CONTACT` | Persistence failure while upserting the user/contact. | | `SSO_RATE_LIMITED` | Too many SSO attempts within the rate-limit window (429): unauthenticated attempts are limited by trusted client IP, and verified sign-ins are limited by workspace. | | `SSO_RATE_LIMIT_UNAVAILABLE` | The SSO rate limiter is unavailable (503). | @@ -81,13 +95,15 @@ The SSO endpoint maps failures to better-auth errors via the `jwt-auto-login` pl ## Security notes - **`aud` binding is required, not optional.** The per-workspace secret already prevents cross-workspace forgery; `aud` is defense-in-depth that keeps the tenant binding intact even if a verification path ever runs against a pool of secrets or a stateless edge verifier derives the workspace from the token. -- Mint tokens **on-demand, per request**, with a short `exp` — never long-lived API keys. (Enforced `exp` is not part of the contract, so treat it as your own mitigation for leaked tokens.) +- Mint tokens **on-demand, per request**, with a short `exp` — never long-lived API keys. `exp` and the lifetime cap are enforced server-side, so a leaked token now ages out on a fixed schedule no matter what the minting side does. - The signing secret is a tenant credential: keep it in server-side config only, never ship it to the browser. - SSO sessions are restricted to the workspace (`restrictedToOrganizationId`) and cannot be used to access the dashboard. +- Prefer passing the SSO token in a fragment (`data-feeblo-link` widget flow) over a query string: query strings leak into logs, history and the `Referer` header, and a token in a URL is replayable until it expires. ## Tests The contract is locked by tests: -- `packages/domain/src/jwt-secret/verification.test.ts` — claim-level rules (wrong/missing `aud`, `exp` optional but expired tokens rejected when `exp` is present, wrong secret). -- `packages/domain/src/widget/sso.test.ts` — end-to-end `createSsoSession` against a real database (valid token creates a restricted user; mismatched `aud`, missing `aud`, expired token, foreign secret, and no-secret cases all behave as documented). +- `packages/domain/src/jwt-secret/verification.test.ts` — claim-level rules (wrong/missing `aud`, missing `exp`, expired `exp`, future `iat`, clock-skew leeway, 24h lifetime cap, per-workspace cap override, wrong secret). +- `packages/domain/src/widget/sso.test.ts` — end-to-end `createSsoSession` against a real database (valid token creates a restricted user; mismatched `aud`, missing `aud`, missing `exp`, expired token, overlifetime token, per-org cap, foreign secret, and no-secret cases all behave as documented). +- `packages/domain/src/contact/utils.test.ts` / `jwt-parsing.test.ts` — `sub`/`userId` resolution and conflict rejection, scalar-only custom attribute values. diff --git a/packages/db/src/migrations/20260823045922_jwt_max_token_lifetime/migration.sql b/packages/db/src/migrations/20260823045922_jwt_max_token_lifetime/migration.sql new file mode 100644 index 000000000..c3bace656 --- /dev/null +++ b/packages/db/src/migrations/20260823045922_jwt_max_token_lifetime/migration.sql @@ -0,0 +1 @@ +ALTER TABLE "organization" ADD COLUMN "jwt_max_token_lifetime_minutes" integer; \ No newline at end of file diff --git a/packages/db/src/migrations/20260823045922_jwt_max_token_lifetime/snapshot.json b/packages/db/src/migrations/20260823045922_jwt_max_token_lifetime/snapshot.json new file mode 100644 index 000000000..406025cfa --- /dev/null +++ b/packages/db/src/migrations/20260823045922_jwt_max_token_lifetime/snapshot.json @@ -0,0 +1,13697 @@ +{ + "version": "8", + "dialect": "postgres", + "id": "b01d69bb-2ebf-4c92-b4e3-8cde961322ff", + "prevIds": [ + "e78cde4e-42a1-4efd-9f7c-f356f317c8e5", + "f8103ab7-1b09-4430-a263-04559a2ef4fd" + ], + "ddl": [ + { + "values": [ + "PUBLIC", + "PRIVATE" + ], + "name": "board_visibility", + "entityType": "enums", + "schema": "public" + }, + { + "values": [ + "draft", + "scheduled", + "published" + ], + "name": "changelog_status", + "entityType": "enums", + "schema": "public" + }, + { + "values": [ + "PUBLIC", + "HIDDEN" + ], + "name": "changelog_visibility", + "entityType": "enums", + "schema": "public" + }, + { + "values": [ + "PUBLIC", + "INTERNAL" + ], + "name": "post_comment_visibility", + "entityType": "enums", + "schema": "public" + }, + { + "values": [ + "PUBLIC", + "HIDDEN" + ], + "name": "roadmap_visibility", + "entityType": "enums", + "schema": "public" + }, + { + "values": [ + "public", + "private" + ], + "name": "saved_roadmap_visibility", + "entityType": "enums", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "account", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "invitation", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "jwt_secret", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "member", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "organization", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "product", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "session", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "subscription", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "two_factor", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "user", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "verification", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "board", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "changelog_category_link", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "changelog_category", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "changelog_post", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "changelog", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "comment_reaction", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "comment", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "company_attribute_definition", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "company_attribute_value", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "company", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "contact_attribute_definition", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "contact_attribute_value", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "contact", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "email_contact", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "email_delivery", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "email_outbox", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "email_provider_event", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "email_subscription", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "email_suppression", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "notification", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_activity", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_reaction", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_status", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_subscription", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_tag", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "roadmap_column", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "roadmap", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "site", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "tag", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "upvote", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "external_resource_create_request", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "github_installation", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "github_sync_rule", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "github_webhook_delivery", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "integration_connection", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "integration_delivery_attempt", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "integration_delivery", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "integration_event", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "integration_external_resource", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "integration_route", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_external_resource_link", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "asset", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "changelog_asset", + "entityType": "tables", + "schema": "public" + }, + { + "isRlsEnabled": false, + "name": "post_asset", + "entityType": "tables", + "schema": "public" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "issuer", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "account_id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider_id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "access_token", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refresh_token", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id_token", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "access_token_expires_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "refresh_token_expires_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scope", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "password", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "account" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "role", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'pending'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "inviter_id", + "entityType": "columns", + "schema": "public", + "table": "invitation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "jwt_secret" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "jwt_secret" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "secret", + "entityType": "columns", + "schema": "public", + "table": "jwt_secret" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "jwt_secret" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "revoked_at", + "entityType": "columns", + "schema": "public", + "table": "jwt_secret" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "member" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "member" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "member" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'manager'", + "generated": null, + "identity": null, + "name": "role", + "entityType": "columns", + "schema": "public", + "table": "member" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "member" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "logo", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "jwt_max_token_lifetime_minutes", + "entityType": "columns", + "schema": "public", + "table": "organization" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "trial_interval", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "trial_interval_count", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "recurring_interval", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "recurring_interval_count", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "is_recurring", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "is_archived", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_organization_id", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "visibility", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "prices", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "product" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "token", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ip_address", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_agent", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "impersonated_by", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "active_organization_id", + "entityType": "columns", + "schema": "public", + "table": "session" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "real", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "amount", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cancel_at_period_end", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "currency", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "recurring_interval", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "recurring_interval_count", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "current_period_start", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "current_period_end", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "trial_start", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "trial_end", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "canceled_at", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "started_at", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ends_at", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ended_at", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "customer_id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "product_id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "discount_id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "checkout_id", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "seats", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "secret", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "backup_codes", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "two_factor" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "email_verified", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "timezone", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "image", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "role", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "banned", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ban_reason", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ban_expires", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "two_factor_enabled", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_login_method", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "jwt_auto_login_at", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email_hash", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "restricted_to_organization_id", + "entityType": "columns", + "schema": "public", + "table": "user" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "identifier", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "verification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "board_visibility", + "typeSchema": "public", + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "visibility", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_id", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_member_id", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "board" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "changelog_category_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "changelog_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_category_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "category_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_category_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_category_link" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "changelog_category_link" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "changelog_category_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'color'", + "generated": null, + "identity": null, + "name": "icon_type", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "icon", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "changelog_category" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "changelog_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "changelog_post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "cover_image", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "excerpt", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "changelog_status", + "typeSchema": "public", + "notNull": true, + "dimensions": 0, + "default": "'draft'", + "generated": null, + "identity": null, + "name": "status", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scheduled_at", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "published_at", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_id", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_member_id", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "changelog" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "member_id", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "comment_id", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "emoji", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "comment_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "member_id", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "post_comment_visibility", + "typeSchema": "public", + "notNull": true, + "dimensions": 0, + "default": "'PUBLIC'", + "generated": null, + "identity": null, + "name": "visibility", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "parent_comment_id", + "entityType": "columns", + "schema": "public", + "table": "comment" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "key", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "config", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "is_required", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "company_id", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "attribute_id", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_text", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_integer", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "real", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_decimal", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_boolean", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_date", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "company_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_id", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatar", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_created_at", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'DASHBOARD'", + "generated": null, + "identity": null, + "name": "source", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "company" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "key", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "config", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "is_required", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contact_id", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "attribute_id", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_text", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_integer", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "real", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_decimal", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_boolean", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "value_date", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "phone", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_id", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "avatar", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "company_id", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'DASHBOARD'", + "generated": null, + "identity": null, + "name": "source", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "verification_state", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "verified_at", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "email_contact" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "outbox_id", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contact_id", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "recipient_email", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "template", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "template_version", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "template_payload", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "message_id", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "attempt_count", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "next_attempt_at", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "accepted_at", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "delivered_at", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_error", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider_metadata", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "email_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "aggregate_type", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "aggregate_id", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deduplication_key", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "payload", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "scheduled_at", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "expires_at", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "email_outbox" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider_event_id", + "entityType": "columns", + "schema": "public", + "table": "email_provider_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "delivery_id", + "entityType": "columns", + "schema": "public", + "table": "email_provider_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "email_provider_event" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "occurred_at", + "entityType": "columns", + "schema": "public", + "table": "email_provider_event" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "received_at", + "entityType": "columns", + "schema": "public", + "table": "email_provider_event" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "email_provider_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contact_id", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "topic_type", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "topic_id", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "source", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "verification_token_hash", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "verification_expires_at", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "unsubscribe_token_hash", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "verified_at", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "unsubscribed_at", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "email_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "email", + "entityType": "columns", + "schema": "public", + "table": "email_suppression" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "reason", + "entityType": "columns", + "schema": "public", + "table": "email_suppression" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider_event_id", + "entityType": "columns", + "schema": "public", + "table": "email_suppression" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "email_suppression" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "recipient_member_id", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actor_member_id", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resource_type", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resource_id", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "body", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "href", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "deduplication_key", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "read_at", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "notification" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actor_id", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "actor_member_id", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "previous_value", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "next_value", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "comment_id", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post_activity" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "member_id", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "emoji", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "post_reaction" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post_status" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "post_status" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "order_index", + "entityType": "columns", + "schema": "public", + "table": "post_status" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "post_status" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post_status" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "post_status" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "member_id", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "post_subscription" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "content", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "excerpt", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "board_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "status_schema_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "eta_quarter", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_member_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "contact_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'DASHBOARD'", + "generated": null, + "identity": null, + "name": "source", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "'{}'", + "generated": null, + "identity": null, + "name": "metadata", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "locked_at", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "archived_at", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "merged_into_post_id", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "merged_at", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "vector(1536)", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "embedding", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "embedding_model", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "embedded_at", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "post" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post_tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "post_tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "tag_id", + "entityType": "columns", + "schema": "public", + "table": "post_tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "post_tag" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post_tag" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "post_tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "roadmap_id", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "position", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "config", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "roadmap_column" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "description", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "is_primary", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "mode", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "saved_roadmap_visibility", + "typeSchema": "public", + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "visibility", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "filter", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "roadmap" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "subdomain", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "custom_domain", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "changelog_visibility", + "typeSchema": "public", + "notNull": true, + "dimensions": 0, + "default": "'PUBLIC'", + "generated": null, + "identity": null, + "name": "changelog_visibility", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "roadmap_visibility", + "typeSchema": "public", + "notNull": true, + "dimensions": 0, + "default": "'PUBLIC'", + "generated": null, + "identity": null, + "name": "roadmap_visibility", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "no_index", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "false", + "generated": null, + "identity": null, + "name": "hide_powered_by", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "site" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "slug", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_id", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "creator_member_id", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "tag" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "member_id", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "upvote" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "idempotency_key", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_resource_id", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_external_resource_link_id", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "installation_id", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "account_id", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "account_login", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "account_type", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "suspended_at", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "github_installation" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "issue_match_mode", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "issue_state", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_status_id", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "upvoter_notification_policy", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "enabled", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "github_sync_rule" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "delivery_id", + "entityType": "columns", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "event_name", + "entityType": "columns", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "received_at", + "entityType": "columns", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "name", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "remote_account_id", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lifecycle", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "1", + "generated": null, + "identity": null, + "name": "credential_generation", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "credentials_ciphertext", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "safe_display_metadata", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "consecutive_exhausted_deliveries", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_succeeded_at", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_failed_at", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "archived_at", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "retention_expires_at", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "integration_connection" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "delivery_id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "attempt_number", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "started_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "finished_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "duration_ms", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "http_status", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "error_tag", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "retry_decision", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "diagnostics", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "retention_expires_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "route_id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "event_id", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "action_key", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "ordering_key", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "0", + "generated": null, + "identity": null, + "name": "attempt_count", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "next_attempt_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lease_owner", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "lease_expires_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "succeeded_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "exhausted_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "canceled_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "last_error", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "retention_expires_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "integration_delivery" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "type", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "version", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "occurred_at", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "origin", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "causation_id", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "correlation_id", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "causal_hop_count", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "payload", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "retention_expires_at", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "integration_event" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "resource_type", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "remote_id", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "remote_url", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "display_key", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "title", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "state_key", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "safe_metadata", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "integration_external_resource" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "connection_id", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "capability_key", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "boolean", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "true", + "generated": null, + "identity": null, + "name": "enabled", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "event_types", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "''", + "generated": null, + "identity": null, + "name": "route_key", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "integer", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "config_version", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "provider_config", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "jsonb", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "safe_display_metadata", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "integration_route" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "external_resource_id", + "entityType": "columns", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "id", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "bucket", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "key", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "url", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "kind", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "user_id", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": false, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "organization_id", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "created_at", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "timestamp with time zone", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": "now()", + "generated": null, + "identity": null, + "name": "updated_at", + "entityType": "columns", + "schema": "public", + "table": "asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "changelog_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "asset_id", + "entityType": "columns", + "schema": "public", + "table": "changelog_asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "post_id", + "entityType": "columns", + "schema": "public", + "table": "post_asset" + }, + { + "type": "text", + "typeSchema": null, + "notNull": true, + "dimensions": 0, + "default": null, + "generated": null, + "identity": null, + "name": "asset_id", + "entityType": "columns", + "schema": "public", + "table": "post_asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "account_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "account" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "issuer", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "account_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "account_issuer_account_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "account" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "invitation_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "invitation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "email", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "invitation_email_idx", + "entityType": "indexes", + "schema": "public", + "table": "invitation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "jwt_secret_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "jwt_secret" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"revoked_at\" is null", + "with": "", + "method": "btree", + "concurrently": false, + "name": "jwt_secret_organizationId_active_uidx", + "entityType": "indexes", + "schema": "public", + "table": "jwt_secret" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "member_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "member" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "member_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "member" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "member_organizationId_userId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "member" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "organization_slug_uidx", + "entityType": "indexes", + "schema": "public", + "table": "organization" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "session_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "session" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "secret", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "twoFactor_secret_idx", + "entityType": "indexes", + "schema": "public", + "table": "two_factor" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "twoFactor_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "two_factor" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "email_hash", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "user_emailHash_idx", + "entityType": "indexes", + "schema": "public", + "table": "user" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "restricted_to_organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "user_restricted_to_organization_id_idx", + "entityType": "indexes", + "schema": "public", + "table": "user" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "identifier", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "verification_identifier_idx", + "entityType": "indexes", + "schema": "public", + "table": "verification" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "board_organizationId_slug_uidx", + "entityType": "indexes", + "schema": "public", + "table": "board" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "changelog_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_category_link_changelogId_idx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_category_link" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "category_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_category_link_categoryId_idx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_category_link" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "changelog_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "category_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_category_link_changelogId_categoryId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_category_link" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "name", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_category_organizationId_name_uidx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_category" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_post_postId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_post_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_organizationId_slug_uidx", + "entityType": "indexes", + "schema": "public", + "table": "changelog" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "comment_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "emoji", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "commentReaction_userId_commentId_emoji_uidx", + "entityType": "indexes", + "schema": "public", + "table": "comment_reaction" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_attribute_definition_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_attribute_definition_organizationId_key_uidx", + "entityType": "indexes", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_attribute_value_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "company_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_attribute_value_companyId_idx", + "entityType": "indexes", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "attribute_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_attribute_value_attributeId_idx", + "entityType": "indexes", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "company_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "attribute_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_attribute_value_companyId_attributeId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "company" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "external_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_organizationId_externalId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "company" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "name", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "company_organizationId_name_uidx", + "entityType": "indexes", + "schema": "public", + "table": "company" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_attribute_definition_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_attribute_definition_organizationId_key_uidx", + "entityType": "indexes", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_attribute_value_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contact_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_attribute_value_contactId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "attribute_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_attribute_value_attributeId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contact_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "attribute_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_attribute_value_contactId_attributeId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "company_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_companyId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "external_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_organizationId_externalId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "email", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "contact_organizationId_email_uidx", + "entityType": "indexes", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "email", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_contact_organizationId_email_uidx", + "entityType": "indexes", + "schema": "public", + "table": "email_contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_contact_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_contact" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "outbox_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "recipient_email", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_delivery_outboxId_recipientEmail_uidx", + "entityType": "indexes", + "schema": "public", + "table": "email_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "message_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_delivery_messageId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "email_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "next_attempt_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_delivery_state_nextAttemptAt_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "contact_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_delivery_contactId_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "deduplication_key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_outbox_organizationId_deduplicationKey_uidx", + "entityType": "indexes", + "schema": "public", + "table": "email_outbox" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "scheduled_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_outbox_state_scheduledAt_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_outbox" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_outbox_organizationId_state_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_outbox" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "kind", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "aggregate_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"state\" = 'pending' AND \"kind\" = 'post.status_changed'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_outbox_pendingStatusAggregate_uidx", + "entityType": "indexes", + "schema": "public", + "table": "email_outbox" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "delivery_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "occurred_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_provider_event_deliveryId_occurredAt_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_provider_event" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_subscription_organizationId_state_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_subscription" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "topic_type", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "topic_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "contact_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_subscription_recipientLookup_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_subscription" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_subscription_state_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "email_subscription" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "provider_event_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "email_suppression_providerEventId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "email_suppression" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "recipient_member_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "read_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "created_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "notification_recipient_read_created_idx", + "entityType": "indexes", + "schema": "public", + "table": "notification" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "notification_organization_idx", + "entityType": "indexes", + "schema": "public", + "table": "notification" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "recipient_member_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "deduplication_key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "notification_recipient_deduplication_uidx", + "entityType": "indexes", + "schema": "public", + "table": "notification" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "created_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_activity_postId_createdAt_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_activity" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_activity_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_activity" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "emoji", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "postReaction_userId_postId_emoji_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_reaction" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_status_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_status" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_status_organizationId_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_status" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "type", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_status_organizationId_type_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_status" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "order_index", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_status_organizationId_orderIndex_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_status" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_subscription_postId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_subscription_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_subscription_postId_userId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "status_schema_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_statusId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "archived_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_archivedAt_idx", + "entityType": "indexes", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "merged_into_post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_mergedIntoPostId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "embedding", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": { + "name": "vector_cosine_ops", + "default": false + } + } + ], + "isUnique": false, + "where": "\"embedding\" is not null", + "with": "", + "method": "hnsw", + "concurrently": false, + "name": "post_embedding_hnsw_idx", + "entityType": "indexes", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_id_organizationId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_organizationId_slug_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_tag_postId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_tag" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "tag_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_tag_tagId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_tag" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "tag_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_tag_postId_tagId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_tag" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "roadmap_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "roadmap_column_roadmapId_idx", + "entityType": "indexes", + "schema": "public", + "table": "roadmap_column" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "roadmap_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "position", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "roadmap_column_roadmapId_position_idx", + "entityType": "indexes", + "schema": "public", + "table": "roadmap_column" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "roadmap_organizationId_slug_uidx", + "entityType": "indexes", + "schema": "public", + "table": "roadmap" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "roadmap_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "roadmap" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"is_primary\"", + "with": "", + "method": "btree", + "concurrently": false, + "name": "roadmap_primary_organizationId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "roadmap" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "site_organizationId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "site" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "subdomain", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "site_subdomain_uidx", + "entityType": "indexes", + "schema": "public", + "table": "site" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "name", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "tag_organizationId_name_uidx", + "entityType": "indexes", + "schema": "public", + "table": "tag" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "slug", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "tag_organizationId_slug_uidx", + "entityType": "indexes", + "schema": "public", + "table": "tag" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "upvote_postId_idx", + "entityType": "indexes", + "schema": "public", + "table": "upvote" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "upvote_userId_postId_uidx", + "entityType": "indexes", + "schema": "public", + "table": "upvote" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "idempotency_key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "external_resource_create_request_connection_key_uidx", + "entityType": "indexes", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "installation_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_installation_installation_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "github_installation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "account_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_installation_account_idx", + "entityType": "indexes", + "schema": "public", + "table": "github_installation" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"issue_match_mode\" = 'any' AND \"issue_state\" = 'open'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_sync_rule_open_connection_uq", + "entityType": "indexes", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"issue_match_mode\" = 'all' AND \"issue_state\" = 'closed'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_sync_rule_closed_connection_uq", + "entityType": "indexes", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "enabled", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_sync_rule_connection_enabled_idx", + "entityType": "indexes", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_sync_rule_organization_idx", + "entityType": "indexes", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "delivery_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "github_webhook_delivery_connection_delivery_uidx", + "entityType": "indexes", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "provider", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_connection_organization_provider_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_connection" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "lifecycle", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_connection_organization_lifecycle_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_connection" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_connection_organization_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_connection" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "provider", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "remote_account_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"provider\" = 'discord' and \"remote_account_id\" is not null and \"lifecycle\" = 'active'", + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_connection_provider_remote_account_active_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_connection" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "delivery_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "attempt_number", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_attempt_delivery_number_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "delivery_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "started_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_attempt_delivery_started_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "retention_expires_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_attempt_retention_expires_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "route_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "event_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "action_key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_route_event_action_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "next_attempt_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "lease_expires_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_lease_claim_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_connection_state_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "state", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_organization_state_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "retention_expires_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_delivery_retention_expires_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "occurred_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_event_organization_occurred_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_event" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "retention_expires_at", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_event_retention_expires_at_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_event" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_event_organization_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_event" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_external_resource_organization_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_external_resource" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "resource_type", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "remote_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_external_resource_connection_type_remote_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_external_resource" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_external_resource_organization_connection_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_external_resource" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "enabled", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_route_connection_enabled_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "enabled", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_route_organization_enabled_idx", + "entityType": "indexes", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_route_organization_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_route_connection_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "connection_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "capability_key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "route_key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "integration_route_connection_capability_key_uidx", + "entityType": "indexes", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_external_resource_link_organization_id_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "external_resource_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_external_resource_link_post_resource_uidx", + "entityType": "indexes", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "post_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_external_resource_link_organization_post_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "bucket", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "key", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "asset_key_uidx", + "entityType": "indexes", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "COALESCE(\"user_id\", \"organization_id\")", + "isExpression": true, + "asc": true, + "nullsFirst": false, + "opclass": null + }, + { + "value": "kind", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": true, + "where": "\"kind\" IN ('profile_image', 'organization_logo')", + "with": "", + "method": "btree", + "concurrently": false, + "name": "asset_owner_kind_singleton_uidx", + "entityType": "indexes", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "user_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "asset_userId_idx", + "entityType": "indexes", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "organization_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "asset_organizationId_idx", + "entityType": "indexes", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "url", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "asset_url_idx", + "entityType": "indexes", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "asset_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "changelog_asset_assetId_idx", + "entityType": "indexes", + "schema": "public", + "table": "changelog_asset" + }, + { + "nameExplicit": true, + "columns": [ + { + "value": "asset_id", + "isExpression": false, + "asc": true, + "nullsFirst": false, + "opclass": null + } + ], + "isUnique": false, + "where": null, + "with": "", + "method": "btree", + "concurrently": false, + "name": "post_asset_assetId_idx", + "entityType": "indexes", + "schema": "public", + "table": "post_asset" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "account_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "account" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "invitation_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "invitation" + }, + { + "nameExplicit": false, + "columns": [ + "inviter_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "invitation_inviter_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "invitation" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "jwt_secret_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "jwt_secret" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "member_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "member" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "member_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "member" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "session_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "session" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "subscription_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "subscription" + }, + { + "nameExplicit": false, + "columns": [ + "product_id" + ], + "schemaTo": "public", + "tableTo": "product", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "subscription_product_id_product_id_fk", + "entityType": "fks", + "schema": "public", + "table": "subscription" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "two_factor_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "two_factor" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "board_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "board" + }, + { + "nameExplicit": false, + "columns": [ + "creator_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "board_creator_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "board" + }, + { + "nameExplicit": false, + "columns": [ + "creator_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "board_creator_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "board" + }, + { + "nameExplicit": false, + "columns": [ + "changelog_id" + ], + "schemaTo": "public", + "tableTo": "changelog", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_category_link_changelog_id_changelog_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_category_link" + }, + { + "nameExplicit": false, + "columns": [ + "category_id" + ], + "schemaTo": "public", + "tableTo": "changelog_category", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_category_link_category_id_changelog_category_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_category_link" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_category_link_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_category_link" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_category_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_category" + }, + { + "nameExplicit": false, + "columns": [ + "changelog_id" + ], + "schemaTo": "public", + "tableTo": "changelog", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_post_changelog_id_changelog_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_post" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_post_post_id_post_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_post" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_post_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_post" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "changelog" + }, + { + "nameExplicit": false, + "columns": [ + "creator_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "changelog_creator_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "changelog" + }, + { + "nameExplicit": false, + "columns": [ + "creator_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "changelog_creator_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "changelog" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "comment_reaction_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment_reaction" + }, + { + "nameExplicit": false, + "columns": [ + "member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "comment_reaction_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment_reaction" + }, + { + "nameExplicit": false, + "columns": [ + "comment_id" + ], + "schemaTo": "public", + "tableTo": "comment", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "comment_reaction_comment_id_comment_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment_reaction" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "comment_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "comment_post_id_post_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "comment_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment" + }, + { + "nameExplicit": false, + "columns": [ + "member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "comment_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment" + }, + { + "nameExplicit": false, + "columns": [ + "parent_comment_id" + ], + "schemaTo": "public", + "tableTo": "comment", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "comment_parent_comment_id_comment_id_fk", + "entityType": "fks", + "schema": "public", + "table": "comment" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "company_attribute_definition_kTIdzOEhY84w_fkey", + "entityType": "fks", + "schema": "public", + "table": "company_attribute_definition" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "company_attribute_value_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": false, + "columns": [ + "company_id" + ], + "schemaTo": "public", + "tableTo": "company", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "company_attribute_value_company_id_company_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": false, + "columns": [ + "attribute_id" + ], + "schemaTo": "public", + "tableTo": "company_attribute_definition", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "company_attribute_value_llKdT8uQbpgY_fkey", + "entityType": "fks", + "schema": "public", + "table": "company_attribute_value" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "company_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "company" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "contact_attribute_definition_kTIdzMCiJSi5_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact_attribute_definition" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "contact_attribute_value_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": false, + "columns": [ + "contact_id" + ], + "schemaTo": "public", + "tableTo": "contact", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "contact_attribute_value_contact_id_contact_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": false, + "columns": [ + "attribute_id" + ], + "schemaTo": "public", + "tableTo": "contact_attribute_definition", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "contact_attribute_value_4kkzVjc1dj7o_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact_attribute_value" + }, + { + "nameExplicit": false, + "columns": [ + "company_id" + ], + "schemaTo": "public", + "tableTo": "company", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "contact_company_id_company_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "contact_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "contact_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "contact" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "email_contact_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_contact" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "email_contact_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_contact" + }, + { + "nameExplicit": false, + "columns": [ + "outbox_id" + ], + "schemaTo": "public", + "tableTo": "email_outbox", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "email_delivery_outbox_id_email_outbox_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_delivery" + }, + { + "nameExplicit": false, + "columns": [ + "contact_id" + ], + "schemaTo": "public", + "tableTo": "email_contact", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "email_delivery_contact_id_email_contact_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_delivery" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "email_outbox_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_outbox" + }, + { + "nameExplicit": false, + "columns": [ + "delivery_id" + ], + "schemaTo": "public", + "tableTo": "email_delivery", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "email_provider_event_delivery_id_email_delivery_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_provider_event" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "email_subscription_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "contact_id" + ], + "schemaTo": "public", + "tableTo": "email_contact", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "email_subscription_contact_id_email_contact_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "email_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "notification_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "notification" + }, + { + "nameExplicit": false, + "columns": [ + "recipient_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "notification_recipient_member_id_member_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "notification" + }, + { + "nameExplicit": false, + "columns": [ + "actor_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "notification_actor_member_id_member_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "notification" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_activity_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_activity" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_activity_post_id_post_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_activity" + }, + { + "nameExplicit": false, + "columns": [ + "actor_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_activity_actor_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_activity" + }, + { + "nameExplicit": false, + "columns": [ + "actor_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_activity_actor_member_id_member_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_activity" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_reaction_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_reaction" + }, + { + "nameExplicit": false, + "columns": [ + "member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_reaction_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_reaction" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_reaction_post_id_post_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_reaction" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_status_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_status" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_subscription_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_subscription_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_subscription_post_id_post_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_subscription_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "board_id" + ], + "schemaTo": "public", + "tableTo": "board", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_board_id_board_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": false, + "columns": [ + "status_schema_id" + ], + "schemaTo": "public", + "tableTo": "post_status", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "RESTRICT", + "name": "post_status_schema_id_post_status_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": false, + "columns": [ + "creator_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_creator_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": false, + "columns": [ + "creator_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_creator_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": false, + "columns": [ + "contact_id" + ], + "schemaTo": "public", + "tableTo": "contact", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "post_contact_id_contact_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": true, + "columns": [ + "merged_into_post_id", + "organization_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id", + "organization_id" + ], + "onUpdate": "NO ACTION", + "onDelete": "RESTRICT", + "name": "post_merged_into_same_organization_fk", + "entityType": "fks", + "schema": "public", + "table": "post" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_tag_post_id_post_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_tag" + }, + { + "nameExplicit": false, + "columns": [ + "tag_id" + ], + "schemaTo": "public", + "tableTo": "tag", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_tag_tag_id_tag_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_tag" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_tag_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "post_tag" + }, + { + "nameExplicit": false, + "columns": [ + "roadmap_id" + ], + "schemaTo": "public", + "tableTo": "roadmap", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "roadmap_column_roadmap_id_roadmap_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "roadmap_column" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "roadmap_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "roadmap" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "site_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "site" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "tag_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "tag" + }, + { + "nameExplicit": false, + "columns": [ + "creator_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "tag_creator_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "tag" + }, + { + "nameExplicit": false, + "columns": [ + "creator_member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "tag_creator_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "tag" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "upvote_user_id_user_id_fk", + "entityType": "fks", + "schema": "public", + "table": "upvote" + }, + { + "nameExplicit": false, + "columns": [ + "member_id" + ], + "schemaTo": "public", + "tableTo": "member", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "upvote_member_id_member_id_fk", + "entityType": "fks", + "schema": "public", + "table": "upvote" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "upvote_post_id_post_id_fk", + "entityType": "fks", + "schema": "public", + "table": "upvote" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "upvote_organization_id_organization_id_fk", + "entityType": "fks", + "schema": "public", + "table": "upvote" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "external_resource_create_request_eU77wOAyFsGn_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "external_resource_create_request_organization_connection_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + "post_id", + "organization_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id", + "organization_id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "external_resource_create_request_post_organization_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + "external_resource_id" + ], + "schemaTo": "public", + "tableTo": "integration_external_resource", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "external_resource_create_request_resource_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + "post_external_resource_link_id" + ], + "schemaTo": "public", + "tableTo": "post_external_resource_link", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "SET NULL", + "name": "external_resource_create_request_link_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "external_resource_id" + ], + "schemaTo": "public", + "tableTo": "integration_external_resource", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "NO ACTION", + "name": "external_resource_create_request_organization_resource_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "post_external_resource_link_id" + ], + "schemaTo": "public", + "tableTo": "post_external_resource_link", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "NO ACTION", + "name": "external_resource_create_request_organization_link_fkey", + "entityType": "fks", + "schema": "public", + "table": "external_resource_create_request" + }, + { + "nameExplicit": false, + "columns": [ + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "github_installation_hxjCxRRkLkaP_fkey", + "entityType": "fks", + "schema": "public", + "table": "github_installation" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "github_sync_rule_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "github_sync_rule_organization_connection_fkey", + "entityType": "fks", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "post_status_id" + ], + "schemaTo": "public", + "tableTo": "post_status", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "github_sync_rule_organization_status_fkey", + "entityType": "fks", + "schema": "public", + "table": "github_sync_rule" + }, + { + "nameExplicit": false, + "columns": [ + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "github_webhook_delivery_XC1Ae9VBXiU3_fkey", + "entityType": "fks", + "schema": "public", + "table": "github_webhook_delivery" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_connection_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_connection" + }, + { + "nameExplicit": false, + "columns": [ + "delivery_id" + ], + "schemaTo": "public", + "tableTo": "integration_delivery", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_delivery_attempt_xOqDtFxhvWcc_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_delivery_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_delivery_organization_connection_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "route_id" + ], + "schemaTo": "public", + "tableTo": "integration_route", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_delivery_organization_route_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + "connection_id", + "route_id" + ], + "schemaTo": "public", + "tableTo": "integration_route", + "columnsTo": [ + "connection_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_delivery_connection_route_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "event_id" + ], + "schemaTo": "public", + "tableTo": "integration_event", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_delivery_organization_event_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_delivery" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_event_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_event" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_external_resource_DDcoUtAHSqcr_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_external_resource" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_external_resource_organization_connection_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_external_resource" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_route_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "connection_id" + ], + "schemaTo": "public", + "tableTo": "integration_connection", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "integration_route_organization_connection_fkey", + "entityType": "fks", + "schema": "public", + "table": "integration_route" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_external_resource_link_ywAvLx23F2Vs_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "nameExplicit": true, + "columns": [ + "post_id", + "organization_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id", + "organization_id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_external_resource_link_post_organization_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "external_resource_id" + ], + "schemaTo": "public", + "tableTo": "integration_external_resource", + "columnsTo": [ + "organization_id", + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_external_resource_link_organization_resource_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_external_resource_link" + }, + { + "nameExplicit": false, + "columns": [ + "user_id" + ], + "schemaTo": "public", + "tableTo": "user", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "asset_user_id_user_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": false, + "columns": [ + "organization_id" + ], + "schemaTo": "public", + "tableTo": "organization", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "asset_organization_id_organization_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "asset" + }, + { + "nameExplicit": false, + "columns": [ + "changelog_id" + ], + "schemaTo": "public", + "tableTo": "changelog", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_asset_changelog_id_changelog_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_asset" + }, + { + "nameExplicit": false, + "columns": [ + "asset_id" + ], + "schemaTo": "public", + "tableTo": "asset", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "changelog_asset_asset_id_asset_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "changelog_asset" + }, + { + "nameExplicit": false, + "columns": [ + "post_id" + ], + "schemaTo": "public", + "tableTo": "post", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_asset_post_id_post_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_asset" + }, + { + "nameExplicit": false, + "columns": [ + "asset_id" + ], + "schemaTo": "public", + "tableTo": "asset", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "name": "post_asset_asset_id_asset_id_fkey", + "entityType": "fks", + "schema": "public", + "table": "post_asset" + }, + { + "columns": [ + "changelog_id", + "post_id" + ], + "nameExplicit": false, + "name": "changelog_post_pkey", + "entityType": "pks", + "schema": "public", + "table": "changelog_post" + }, + { + "columns": [ + "changelog_id", + "asset_id" + ], + "nameExplicit": false, + "name": "changelog_asset_pkey", + "entityType": "pks", + "schema": "public", + "table": "changelog_asset" + }, + { + "columns": [ + "post_id", + "asset_id" + ], + "nameExplicit": false, + "name": "post_asset_pkey", + "entityType": "pks", + "schema": "public", + "table": "post_asset" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "account_pkey", + "schema": "public", + "table": "account", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "invitation_pkey", + "schema": "public", + "table": "invitation", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "jwt_secret_pkey", + "schema": "public", + "table": "jwt_secret", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "member_pkey", + "schema": "public", + "table": "member", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "organization_pkey", + "schema": "public", + "table": "organization", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "product_pkey", + "schema": "public", + "table": "product", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "session_pkey", + "schema": "public", + "table": "session", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "subscription_pkey", + "schema": "public", + "table": "subscription", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "two_factor_pkey", + "schema": "public", + "table": "two_factor", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "user_pkey", + "schema": "public", + "table": "user", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "verification_pkey", + "schema": "public", + "table": "verification", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "board_pkey", + "schema": "public", + "table": "board", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "changelog_category_link_pkey", + "schema": "public", + "table": "changelog_category_link", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "changelog_category_pkey", + "schema": "public", + "table": "changelog_category", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "changelog_pkey", + "schema": "public", + "table": "changelog", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "comment_reaction_pkey", + "schema": "public", + "table": "comment_reaction", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "comment_pkey", + "schema": "public", + "table": "comment", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "company_attribute_definition_pkey", + "schema": "public", + "table": "company_attribute_definition", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "company_attribute_value_pkey", + "schema": "public", + "table": "company_attribute_value", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "company_pkey", + "schema": "public", + "table": "company", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "contact_attribute_definition_pkey", + "schema": "public", + "table": "contact_attribute_definition", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "contact_attribute_value_pkey", + "schema": "public", + "table": "contact_attribute_value", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "contact_pkey", + "schema": "public", + "table": "contact", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "email_contact_pkey", + "schema": "public", + "table": "email_contact", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "email_delivery_pkey", + "schema": "public", + "table": "email_delivery", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "email_outbox_pkey", + "schema": "public", + "table": "email_outbox", + "entityType": "pks" + }, + { + "columns": [ + "provider_event_id" + ], + "nameExplicit": false, + "name": "email_provider_event_pkey", + "schema": "public", + "table": "email_provider_event", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "email_subscription_pkey", + "schema": "public", + "table": "email_subscription", + "entityType": "pks" + }, + { + "columns": [ + "email" + ], + "nameExplicit": false, + "name": "email_suppression_pkey", + "schema": "public", + "table": "email_suppression", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "notification_pkey", + "schema": "public", + "table": "notification", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_activity_pkey", + "schema": "public", + "table": "post_activity", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_reaction_pkey", + "schema": "public", + "table": "post_reaction", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_status_pkey", + "schema": "public", + "table": "post_status", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_subscription_pkey", + "schema": "public", + "table": "post_subscription", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_pkey", + "schema": "public", + "table": "post", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_tag_pkey", + "schema": "public", + "table": "post_tag", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "roadmap_column_pkey", + "schema": "public", + "table": "roadmap_column", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "roadmap_pkey", + "schema": "public", + "table": "roadmap", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "site_pkey", + "schema": "public", + "table": "site", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "tag_pkey", + "schema": "public", + "table": "tag", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "upvote_pkey", + "schema": "public", + "table": "upvote", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "external_resource_create_request_pkey", + "schema": "public", + "table": "external_resource_create_request", + "entityType": "pks" + }, + { + "columns": [ + "connection_id" + ], + "nameExplicit": false, + "name": "github_installation_pkey", + "schema": "public", + "table": "github_installation", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "github_sync_rule_pkey", + "schema": "public", + "table": "github_sync_rule", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "github_webhook_delivery_pkey", + "schema": "public", + "table": "github_webhook_delivery", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "integration_connection_pkey", + "schema": "public", + "table": "integration_connection", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "integration_delivery_attempt_pkey", + "schema": "public", + "table": "integration_delivery_attempt", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "integration_delivery_pkey", + "schema": "public", + "table": "integration_delivery", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "integration_event_pkey", + "schema": "public", + "table": "integration_event", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "integration_external_resource_pkey", + "schema": "public", + "table": "integration_external_resource", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "integration_route_pkey", + "schema": "public", + "table": "integration_route", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "post_external_resource_link_pkey", + "schema": "public", + "table": "post_external_resource_link", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "asset_pkey", + "schema": "public", + "table": "asset", + "entityType": "pks" + }, + { + "nameExplicit": true, + "columns": [ + "organization_id", + "secret", + "revoked_at" + ], + "nullsNotDistinct": true, + "name": "jwt_secret_organizationId_secret_revokedAt_uidx", + "entityType": "uniques", + "schema": "public", + "table": "jwt_secret" + }, + { + "nameExplicit": true, + "columns": [ + "contact_id", + "topic_type", + "topic_id" + ], + "nullsNotDistinct": true, + "name": "email_subscription_contactId_topicType_topicId_uidx", + "entityType": "uniques", + "schema": "public", + "table": "email_subscription" + }, + { + "nameExplicit": false, + "columns": [ + "slug" + ], + "nullsNotDistinct": false, + "name": "organization_slug_unique", + "schema": "public", + "table": "organization", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "token" + ], + "nullsNotDistinct": false, + "name": "session_token_unique", + "schema": "public", + "table": "session", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "external_id" + ], + "nullsNotDistinct": false, + "name": "subscription_external_id_unique", + "schema": "public", + "table": "subscription", + "entityType": "uniques" + }, + { + "nameExplicit": false, + "columns": [ + "email" + ], + "nullsNotDistinct": false, + "name": "user_email_unique", + "schema": "public", + "table": "user", + "entityType": "uniques" + }, + { + "value": "(\"merged_into_post_id\" is null and \"merged_at\" is null) or (\"merged_into_post_id\" is not null and \"merged_at\" is not null)", + "name": "post_merge_requires_target_and_timestamp_chk", + "entityType": "checks", + "schema": "public", + "table": "post" + }, + { + "value": "\"merged_into_post_id\" is null or \"archived_at\" is not null", + "name": "post_merged_rows_must_be_archived_chk", + "entityType": "checks", + "schema": "public", + "table": "post" + }, + { + "value": "\"merged_into_post_id\" is null or \"merged_into_post_id\" <> \"id\"", + "name": "post_no_self_merge_chk", + "entityType": "checks", + "schema": "public", + "table": "post" + }, + { + "value": "(\"embedding\" is null and \"embedding_model\" is null and \"embedded_at\" is null) or (\"embedding\" is not null and \"embedding_model\" is not null and \"embedded_at\" is not null)", + "name": "post_embedding_metadata_chk", + "entityType": "checks", + "schema": "public", + "table": "post" + }, + { + "value": "\"eta_quarter\" is null or \"eta_quarter\" ~ '^[0-9]{4}-Q[1-4]$'", + "name": "post_eta_quarter_format_chk", + "entityType": "checks", + "schema": "public", + "table": "post" + }, + { + "value": "(\"issue_match_mode\" = 'any' AND \"issue_state\" = 'open') OR (\"issue_match_mode\" = 'all' AND \"issue_state\" = 'closed')", + "name": "github_sync_rule_combo_ck", + "entityType": "checks", + "schema": "public", + "table": "github_sync_rule" + }, + { + "value": "\"credential_generation\" > 0", + "name": "integration_connection_credential_generation_check", + "entityType": "checks", + "schema": "public", + "table": "integration_connection" + }, + { + "value": "\"consecutive_exhausted_deliveries\" >= 0", + "name": "integration_connection_exhausted_count_check", + "entityType": "checks", + "schema": "public", + "table": "integration_connection" + }, + { + "value": "\"attempt_number\" > 0", + "name": "integration_delivery_attempt_number_check", + "entityType": "checks", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "value": "\"duration_ms\" IS NULL OR \"duration_ms\" >= 0", + "name": "integration_delivery_attempt_duration_check", + "entityType": "checks", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "value": "\"http_status\" IS NULL OR \"http_status\" BETWEEN 100 AND 599", + "name": "integration_delivery_attempt_http_status_check", + "entityType": "checks", + "schema": "public", + "table": "integration_delivery_attempt" + }, + { + "value": "\"attempt_count\" >= 0", + "name": "integration_delivery_attempt_count_check", + "entityType": "checks", + "schema": "public", + "table": "integration_delivery" + }, + { + "value": "(\"state\" = 'leased') = (\"lease_owner\" IS NOT NULL AND \"lease_expires_at\" IS NOT NULL)", + "name": "integration_delivery_lease_state_check", + "entityType": "checks", + "schema": "public", + "table": "integration_delivery" + }, + { + "value": "(\"state\" = 'succeeded') = (\"succeeded_at\" IS NOT NULL) AND (\"state\" = 'exhausted') = (\"exhausted_at\" IS NOT NULL) AND (\"state\" = 'canceled') = (\"canceled_at\" IS NOT NULL)", + "name": "integration_delivery_terminal_timestamp_check", + "entityType": "checks", + "schema": "public", + "table": "integration_delivery" + }, + { + "value": "\"version\" > 0", + "name": "integration_event_version_check", + "entityType": "checks", + "schema": "public", + "table": "integration_event" + }, + { + "value": "\"causal_hop_count\" >= 0", + "name": "integration_event_causal_hop_count_check", + "entityType": "checks", + "schema": "public", + "table": "integration_event" + }, + { + "value": "\"config_version\" > 0", + "name": "integration_route_config_version_check", + "entityType": "checks", + "schema": "public", + "table": "integration_route" + }, + { + "value": "(\"user_id\" IS NOT NULL) <> (\"organization_id\" IS NOT NULL)", + "name": "asset_owner_check", + "entityType": "checks", + "schema": "public", + "table": "asset" + } + ], + "renames": [] +} \ No newline at end of file diff --git a/packages/db/src/schema/auth.ts b/packages/db/src/schema/auth.ts index ad3a16704..9d73f8c3e 100644 --- a/packages/db/src/schema/auth.ts +++ b/packages/db/src/schema/auth.ts @@ -153,6 +153,8 @@ export const organizationTable = pgTable( logo: text("logo"), createdAt: timestamp("created_at", { withTimezone: true }).notNull(), metadata: text("metadata"), + /** Per-workspace cap on identity-token lifetime, in minutes. NULL means the 24h default. */ + jwtMaxTokenLifetimeMinutes: integer("jwt_max_token_lifetime_minutes"), }, (table) => [uniqueIndex("organization_slug_uidx").on(table.slug)] ); diff --git a/packages/domain/src/contact/jwt-parsing.test.ts b/packages/domain/src/contact/jwt-parsing.test.ts index b463d60a0..9dc4d4783 100644 --- a/packages/domain/src/contact/jwt-parsing.test.ts +++ b/packages/domain/src/contact/jwt-parsing.test.ts @@ -66,15 +66,14 @@ describe("JWT payload parsing", () => { }) ); - it.effect("ignores standard JWT claims (iss, sub, iat, exp, aud)", () => + it.effect("ignores standard JWT claims (iss, iat, exp, aud) except sub", () => Effect.gen(function* () { const now = Math.floor(Date.now() / 1000); const userData = { - userId: "user_123", + sub: "user_123", email: "test@example.com", name: "Alice", iss: "feeblo", - sub: "some-sub", iat: now, exp: now + 60, aud: "feeblo-app", @@ -93,7 +92,60 @@ describe("JWT payload parsing", () => { }) ); - it("fails when required fields (userId, email, name) are missing", async () => { + it.effect("falls back to userId when sub is absent", () => + Effect.gen(function* () { + const verified = yield* Effect.promise(() => + signAndVerify({ + userId: "legacy_user", + email: "test@example.com", + name: "Alice", + }) + ); + + const result = yield* parsePersonAttributes(verified, [], []); + + expect(result.commonFields).toEqual({ + userId: "legacy_user", + email: "test@example.com", + name: "Alice", + }); + }) + ); + + it.effect("prefers sub over userId when both agree", () => + Effect.gen(function* () { + const verified = yield* Effect.promise(() => + signAndVerify({ + sub: "user_123", + userId: "user_123", + email: "test@example.com", + name: "Alice", + }) + ); + + const result = yield* parsePersonAttributes(verified, [], []); + + expect(result.commonFields.userId).toBe("user_123"); + }) + ); + + it("rejects a token carrying sub and userId with different values", async () => { + const verified = await signAndVerify({ + sub: "sub_user", + userId: "legacy_user", + email: "test@example.com", + name: "Alice", + }); + + await expect( + Effect.runPromise(parsePersonAttributes(verified, [], [])) + ).rejects.toBeInstanceOf(DataValidationError); + await expect( + Effect.runPromise(parsePersonAttributes(verified, [], [])) + ).rejects.toThrow("Conflicting identity"); + }); + + it("fails when required fields (userId/sub, email, name) are missing", async () => { const verified = await signAndVerify({ sub: "some-sub", iss: "feeblo", diff --git a/packages/domain/src/contact/utils.test.ts b/packages/domain/src/contact/utils.test.ts index 8bbb4cb0c..b702d065a 100644 --- a/packages/domain/src/contact/utils.test.ts +++ b/packages/domain/src/contact/utils.test.ts @@ -242,6 +242,55 @@ describe("parseContactCustomAttributes", () => { }) ); + it.effect("ignores array values for custom attributes (scalar-only)", () => + Effect.gen(function* () { + const def = makeContactDef({ key: "tags", type: "TEXT" }); + const result = yield* parseContactCustomAttributes( + { customFields: { tags: ["a", "b"] } }, + [def] + ); + expect(result).toEqual([]); + }) + ); + + it.effect( + "ignores nested object values for custom attributes (scalar-only)", + () => + Effect.gen(function* () { + const def = makeContactDef({ key: "address", type: "TEXT" }); + const result = yield* parseContactCustomAttributes( + { + customFields: { + address: { street: "Main" }, + city: "Berlin", + }, + }, + [def, makeContactDef({ key: "city", type: "TEXT" })] + ); + expect(result).toEqual([ + { definitionId: def.id, key: "city", value: "Berlin" }, + ]); + }) + ); + + it.effect("fails when a required attribute has a non-scalar value", () => + Effect.gen(function* () { + const def = makeContactDef({ + key: "requiredField", + type: "TEXT", + isRequired: true, + }); + // The key-presence check passes for any value shape, so a required + // attribute carrying an object must fail instead of being dropped + // (which would create contacts without workspace-required data). + const error = yield* parseContactCustomAttributes( + { customFields: { requiredField: { nested: true } } }, + [def] + ).pipe(Effect.flip); + expect(error).toBeInstanceOf(DataValidationError); + }) + ); + it("fails when required attribute is missing", async () => { const def = makeContactDef({ key: "requiredField", @@ -340,28 +389,23 @@ describe("parseContactCustomAttributes", () => { }) ); - it("rejects an invalid Date instance for a DATE attribute", async () => { - const def = makeContactDef({ - key: "birthday", - type: "DATE", - }); - await expect( - Effect.runPromise( - parseContactCustomAttributes( - { customFields: { birthday: new Date(Number.NaN) } }, - [def] - ) - ) - ).rejects.toBeInstanceOf(DataValidationError); - await expect( - Effect.runPromise( - parseContactCustomAttributes( + it.effect( + "ignores an invalid Date instance for a DATE attribute (non-scalar)", + () => + Effect.gen(function* () { + const def = makeContactDef({ + key: "birthday", + type: "DATE", + }); + // A Date instance cannot occur in a JSON JWT payload; like every other + // non-scalar value it is ignored rather than persisted or failed on. + const result = yield* parseContactCustomAttributes( { customFields: { birthday: new Date(Number.NaN) } }, [def] - ) - ) - ).rejects.toThrow('Invalid value for attribute "birthday"'); - }); + ); + expect(result).toEqual([]); + }) + ); it("rejects a non-date string for a DATE attribute", async () => { const def = makeContactDef({ diff --git a/packages/domain/src/contact/utils.ts b/packages/domain/src/contact/utils.ts index 5f692eb27..5b1d20910 100644 --- a/packages/domain/src/contact/utils.ts +++ b/packages/domain/src/contact/utils.ts @@ -1,3 +1,4 @@ +import { isBoolean, isNumber, isString } from "@feeblo/utils/runtime-kind"; import * as Effect from "effect/Effect"; import * as S from "effect/Schema"; import type { JWTPayload } from "jose"; @@ -145,6 +146,7 @@ export type ParsedPersonAttributes = { const KNOWN_CONTACT_FIELDS = new Set([ "userId", + "sub", "email", "name", "avatar", @@ -310,6 +312,16 @@ const validateRequiredAttributes = ( : Effect.void; }; +/** + * Custom attribute values are persisted and rendered client-side, so only + * JSON scalars are accepted from untrusted JWT payloads. Arrays and nested + * objects are ignored entirely (never stored, never rendered): they are not + * valid attribute values and rejecting the whole token for them would let an + * attacker with a leaked secret block sign-ins. + */ +const isJsonScalar = (value: AttributeSourceValue): boolean => + value === null || isString(value) || isNumber(value) || isBoolean(value); + const parseCustomAttributes = ( customFields: AttributeSource, definitions: readonly AttributeDefinition[], @@ -329,6 +341,19 @@ const parseCustomAttributes = ( if (!definition) { continue; } + if (!isJsonScalar(raw)) { + // Arrays and nested objects are not valid attribute values. Optional + // ones are ignored instead of persisting or failing the whole payload; + // a required one must fail here — the key-presence check above already + // passed, so ignoring it would silently create records without + // workspace-required data. + if (definition.isRequired) { + return yield* new DataValidationError({ + message: `Invalid value for required attribute "${definition.key}": must be a string, number, boolean, or null`, + }); + } + continue; + } effects.push( validateSingleAttribute(definition, raw).pipe( Effect.map((value): ParsedAttribute => ({ @@ -436,6 +461,44 @@ const parseCompanies = ( ) : Effect.succeed([]); +/** + * Resolves the user id from the token payload: `sub` is the documented claim + * and `userId` is still accepted while customers migrate (both already minted + * since 2024). A token carrying both with different values is a conflict and + * is rejected — it cannot be a deliberate token. + * + * `userId` support is scheduled for removal after 2026-12-31; customers are + * expected to have switched to `sub` by then. + */ +const resolveUserId = ( + input: AttributeSource +): Effect.Effect => { + const sub = input.sub; + const userId = input.userId; + + if (sub !== undefined && userId !== undefined && sub !== userId) { + return Effect.fail( + new DataValidationError({ + message: `Conflicting identity: "sub" and "userId" claims differ ("${String( + sub + )}" vs "${String(userId)}"). Use "sub" only; "userId" is deprecated.`, + }) + ); + } + + // `sub` wins when both agree; `userId` is the legacy fallback. A non-string + // value is left for CommonContactFields to reject with a typed error. + const resolved = isString(sub) + ? sub + : isString(userId) + ? userId + : (sub ?? userId); + // SAFETY: `sub`/`userId` are either strings already (kept above) or left + // for CommonContactFields to reject; the boxed view is only used so the + // attribute contract (string) matches the JWT's own string semantics. + return Effect.succeed(resolved as string | undefined); +}; + export function parsePersonAttributes( data: JWTPayload | null, contactAttributeDefinitions: readonly TContactAttributeDefinition[], @@ -444,11 +507,13 @@ export function parsePersonAttributes( return Effect.gen(function* () { const input = asRecord(data); + const userId = yield* resolveUserId(input); + const commonFields = yield* decodeCommonFields( CommonContactFields, "contact", { - userId: input.userId, + userId, email: input.email, name: input.name, avatar: input.avatar, diff --git a/packages/domain/src/jwt-secret/verification.test.ts b/packages/domain/src/jwt-secret/verification.test.ts index d94de5500..41f1ed505 100644 --- a/packages/domain/src/jwt-secret/verification.test.ts +++ b/packages/domain/src/jwt-secret/verification.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from "@effect/vitest"; +import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; import * as jose from "jose"; @@ -9,29 +10,30 @@ const SECRET = "a".repeat(64); const OTHER_SECRET = "b".repeat(64); const ORGANIZATION_ID = "org_test"; +const nowSeconds = () => Math.floor(Date.now() / 1000); +const futureExp = () => nowSeconds() + 3600; +const pastExp = () => nowSeconds() - 3600; + async function signToken(payload: jose.JWTPayload, secret: string) { return await new jose.SignJWT(payload) .setProtectedHeader({ alg: "HS256" }) .sign(new Uint8Array(Buffer.from(secret, "hex"))); } -const futureExp = Math.floor(Date.now() / 1000) + 3600; -const pastExp = Math.floor(Date.now() / 1000) - 3600; +const basePayload = (): jose.JWTPayload => ({ + userId: "u_1", + email: "test@example.com", + name: "Ada", + aud: ORGANIZATION_ID, + iat: nowSeconds(), + exp: futureExp(), +}); describe("verifyJwt", () => { it.effect("verifies a token bound to the organization via aud with exp", () => Effect.gen(function* () { const token = yield* Effect.promise(() => - signToken( - { - userId: "u_1", - email: "test@example.com", - name: "Ada", - aud: ORGANIZATION_ID, - exp: futureExp, - }, - SECRET - ) + signToken(basePayload(), SECRET) ); const payload = yield* verifyJwt(token, [SECRET], ORGANIZATION_ID); @@ -44,7 +46,23 @@ describe("verifyJwt", () => { it("rejects a token with the organization only in the iss claim", async () => { const token = await signToken( - { userId: "u_1", iss: ORGANIZATION_ID, exp: futureExp }, + { userId: "u_1", iss: ORGANIZATION_ID, exp: futureExp() }, + SECRET + ); + + await expect( + Effect.runPromise(verifyJwt(token, [SECRET], ORGANIZATION_ID)) + ).rejects.toBeInstanceOf(UnauthorizedError); + }); + + it("rejects a token without an exp claim (exp is required)", async () => { + const token = await signToken( + { + userId: "u_1", + email: "test@example.com", + name: "Ada", + aud: ORGANIZATION_ID, + }, SECRET ); @@ -53,30 +71,57 @@ describe("verifyJwt", () => { ).rejects.toBeInstanceOf(UnauthorizedError); }); - it.effect("accepts a token without an exp claim (exp is optional)", () => + it("rejects an expired token when exp is present", async () => { + const token = await signToken({ ...basePayload(), exp: pastExp() }, SECRET); + + await expect( + Effect.runPromise(verifyJwt(token, [SECRET], ORGANIZATION_ID)) + ).rejects.toBeInstanceOf(UnauthorizedError); + }); + + it.effect("accepts a token expired within the 30s clock-skew leeway", () => Effect.gen(function* () { const token = yield* Effect.promise(() => signToken( - { - userId: "u_1", - email: "test@example.com", - name: "Ada", - aud: ORGANIZATION_ID, - }, + { ...basePayload(), iat: nowSeconds() - 60, exp: nowSeconds() - 10 }, SECRET ) ); const payload = yield* verifyJwt(token, [SECRET], ORGANIZATION_ID); + expect(payload.exp).toBe(nowSeconds() - 10); + }) + ); - expect(payload.userId).toBe("u_1"); - expect(payload.aud).toBe(ORGANIZATION_ID); + it("rejects a token with iat more than 30s in the future", async () => { + const token = await signToken( + { ...basePayload(), iat: nowSeconds() + 120 }, + SECRET + ); + + await expect( + Effect.runPromise(verifyJwt(token, [SECRET], ORGANIZATION_ID)) + ).rejects.toBeInstanceOf(UnauthorizedError); + }); + + it.effect("accepts a token with iat within the 30s clock-skew leeway", () => + Effect.gen(function* () { + const token = yield* Effect.promise(() => + signToken({ ...basePayload(), iat: nowSeconds() + 10 }, SECRET) + ); + + const payload = yield* verifyJwt(token, [SECRET], ORGANIZATION_ID); + expect(payload.iat).toBeGreaterThan(nowSeconds()); }) ); - it("rejects an expired token when exp is present", async () => { + it("rejects a token with a lifetime beyond the 24h default cap", async () => { const token = await signToken( - { userId: "u_1", aud: ORGANIZATION_ID, exp: pastExp }, + { + ...basePayload(), + iat: nowSeconds(), + exp: nowSeconds() + 25 * 3600, + }, SECRET ); @@ -85,9 +130,76 @@ describe("verifyJwt", () => { ).rejects.toBeInstanceOf(UnauthorizedError); }); + it("rejects a token without iat whose exp is beyond the 24h default cap", async () => { + const { iat: _iat, ...payloadWithoutIat } = basePayload(); + const token = await signToken( + { ...payloadWithoutIat, exp: nowSeconds() + 25 * 3600 }, + SECRET + ); + + await expect( + Effect.runPromise(verifyJwt(token, [SECRET], ORGANIZATION_ID)) + ).rejects.toBeInstanceOf(UnauthorizedError); + }); + + it.effect("accepts a token with a lifetime within the default cap", () => + Effect.gen(function* () { + const token = yield* Effect.promise(() => + signToken( + { + ...basePayload(), + iat: nowSeconds(), + exp: nowSeconds() + 23 * 3600, + }, + SECRET + ) + ); + + const payload = yield* verifyJwt(token, [SECRET], ORGANIZATION_ID); + expect(payload.exp).toBeDefined(); + }) + ); + + it("respects a per-workspace maxTokenLifetime override", async () => { + // 2-hour cap: a 3-hour token must be rejected even though the 24h + // default would accept it. + const token = await signToken( + { + ...basePayload(), + iat: nowSeconds(), + exp: nowSeconds() + 3 * 3600, + }, + SECRET + ); + + await expect( + Effect.runPromise( + verifyJwt(token, [SECRET], ORGANIZATION_ID, { + maxTokenLifetime: Duration.hours(2), + }) + ) + ).rejects.toBeInstanceOf(UnauthorizedError); + }); + + it.effect("accepts a token within a tightened per-workspace cap", () => + Effect.gen(function* () { + const token = yield* Effect.promise(() => + signToken( + { ...basePayload(), iat: nowSeconds(), exp: nowSeconds() + 3600 }, + SECRET + ) + ); + + const payload = yield* verifyJwt(token, [SECRET], ORGANIZATION_ID, { + maxTokenLifetime: Duration.hours(2), + }); + expect(payload.exp).toBeDefined(); + }) + ); + it("rejects a token bound to a different organization", async () => { const token = await signToken( - { userId: "u_1", aud: "org_other", exp: futureExp }, + { ...basePayload(), aud: "org_other" }, SECRET ); @@ -97,7 +209,8 @@ describe("verifyJwt", () => { }); it("rejects an unbound token (no aud claim)", async () => { - const token = await signToken({ userId: "u_1", exp: futureExp }, SECRET); + const { aud: _aud, ...payloadWithoutAud } = basePayload(); + const token = await signToken(payloadWithoutAud, SECRET); await expect( Effect.runPromise(verifyJwt(token, [SECRET], ORGANIZATION_ID)) @@ -107,10 +220,7 @@ describe("verifyJwt", () => { it.effect("succeeds when at least one secret matches", () => Effect.gen(function* () { const token = yield* Effect.promise(() => - signToken( - { userId: "u_1", aud: ORGANIZATION_ID, exp: futureExp }, - OTHER_SECRET - ) + signToken(basePayload(), OTHER_SECRET) ); const payload = yield* verifyJwt( @@ -124,10 +234,7 @@ describe("verifyJwt", () => { ); it("fails when no secret matches", async () => { - const token = await signToken( - { userId: "u_1", aud: ORGANIZATION_ID, exp: futureExp }, - "c".repeat(64) - ); + const token = await signToken(basePayload(), "c".repeat(64)); await expect( Effect.runPromise(verifyJwt(token, [SECRET], ORGANIZATION_ID)) diff --git a/packages/domain/src/jwt-secret/verification.ts b/packages/domain/src/jwt-secret/verification.ts index b5c2a16b0..f18ac88e2 100644 --- a/packages/domain/src/jwt-secret/verification.ts +++ b/packages/domain/src/jwt-secret/verification.ts @@ -1,3 +1,5 @@ +import { isNumber } from "@feeblo/utils/runtime-kind"; +import * as Duration from "effect/Duration"; import * as Effect from "effect/Effect"; import * as jose from "jose"; @@ -11,6 +13,42 @@ import { UnauthorizedError } from "../rpc-errors"; */ const MAX_JWT_LENGTH = 16 * 1024; +/** + * Clock-skew tolerance in seconds. `exp`/`nbf` checks by jose and the `iat` + * check below all tolerate this much skew between the caller's clock and + * Feeblo's. 30s keeps mint-on-demand tokens (5-minute `exp`) comfortably + * inside the cap while still bounding a clock-skewed issuer. + */ +const CLOCK_SKEW_LEEWAY_SECONDS = 30; + +/** + * Default maximum token lifetime (`exp - iat`). Tokens claiming to live + * longer are rejected even when the signature is valid: nothing else stops a + * leaked long-lived token from staying replayable. Workspaces can tighten + * this per-org via `organization.jwt_max_token_lifetime_minutes` (see + * docs/widget-sso.md); 24h is the deliberate default because it matches the + * rotation grace window. + */ +export const DEFAULT_MAX_TOKEN_LIFETIME = Duration.hours(24); + +/** + * Converts the nullable `organization.jwt_max_token_lifetime_minutes` column + * into a lifetime cap. The column has no database constraint, so stored values + * are untrusted: the documented policy is tightening-only, so an override is + * honored only when it is a positive integer no larger than the 24h default. + * Any other stored value (zero, negative, oversized, non-integer) falls back + * to the default rather than extending JWT replay or breaking sign-ins. + */ +export const maxTokenLifetimeFromMinutes = ( + minutes: number | null +): Duration.Duration => + minutes !== null && + Number.isInteger(minutes) && + minutes > 0 && + minutes <= Duration.toMinutes(DEFAULT_MAX_TOKEN_LIFETIME) + ? Duration.minutes(minutes) + : DEFAULT_MAX_TOKEN_LIFETIME; + /** * Verifies an HS256-signed org JWT and binds it to the organization. * @@ -21,9 +59,21 @@ const MAX_JWT_LENGTH = 16 * 1024; * holding a leaked secret could forge a payload for any org and the signature * check alone would accept it. * - * An `exp` claim is optional but, when present, is validated by jose — an - * expired token is rejected. Minting short-lived tokens is still strongly - * recommended (see docs/widget-sso.md). + * The `exp` claim is **required**: a token without it is rejected after the + * signature verifies (jose only validates `exp` when present, so the absence + * is checked here). `exp`/`nbf` are checked by jose with a 30s clock-skew + * tolerance. `iat` is additionally rejected when it lies more than 30s in the + * future (a fresh token can never legitimately carry a future `iat`). + * + * The total token lifetime (`exp - iat`, or `exp - now` when `iat` is + * absent) is capped at {@link DEFAULT_MAX_TOKEN_LIFETIME} or the per-org + * override in `options.maxTokenLifetime`, so `exp = now + 30 days` is + * rejected even though the signature is valid. + * + * `iss` is intentionally NOT verified: there is no per-org expected-issuer + * configuration yet, so checking it against nothing would be theater. The + * docs recommend customers set `iss` to their app URL now so it can be + * promoted to required in a future release without breaking their tokens. * * Secrets are stored as 64-char hex (32 bytes). Decode hex to raw bytes. */ @@ -33,23 +83,31 @@ const secretToKey = (secret: string): Uint8Array => export const verifyJwt = ( token: string, secrets: readonly string[], - expectedOrganizationId: string + expectedOrganizationId: string, + options: { readonly maxTokenLifetime?: Duration.Duration } = {} ): Effect.Effect => Effect.gen(function* () { if (token.length > MAX_JWT_LENGTH) { return yield* new UnauthorizedError({ message: "Invalid JWT" }); } + const maxTokenLifetime = + options.maxTokenLifetime ?? DEFAULT_MAX_TOKEN_LIFETIME; + for (const secret of secrets) { const key = secretToKey(secret); - // jwtVerify rejects expired tokens (when `exp` is present) and tokens - // with an invalid signature; any failure just moves on to the next - // candidate secret (active first, then the 24h-grace revoked one). + // jwtVerify rejects expired tokens (or tokens with an invalid + // signature); any failure just moves on to the next candidate secret + // (active first, then the 24h-grace revoked one). `clockTolerance` + // gives both sides a 30s clock-skew allowance. const result = yield* Effect.catch( Effect.map( Effect.tryPromise(() => - jose.jwtVerify(token, key, { algorithms: ["HS256"] }) + jose.jwtVerify(token, key, { + algorithms: ["HS256"], + clockTolerance: CLOCK_SKEW_LEEWAY_SECONDS, + }) ), (r) => r.payload ), @@ -57,8 +115,67 @@ export const verifyJwt = ( ); if (result !== null && result.aud === expectedOrganizationId) { + yield* enforceTimeClaims(result); + yield* enforceMaxLifetime(result, maxTokenLifetime); return result; } } return yield* new UnauthorizedError({ message: "Invalid JWT" }); }); + +/** + * Post-signature time-claim rules that jose does not enforce on its own. + * + * - `exp` is required; jose only validates it when present. + * - `iat` must not be more than the skew tolerance into the future. + * + * Fails with `UnauthorizedError` mutating nothing, so it can run inside the + * candidate-secret loop above. + */ +const enforceTimeClaims = ( + payload: jose.JWTPayload, + nowSeconds: number = Math.floor(Date.now() / 1000) +): Effect.Effect => + Effect.gen(function* () { + if (payload.exp === undefined) { + return yield* new UnauthorizedError({ + message: "Invalid JWT: missing exp claim", + }); + } + + if ( + isNumber(payload.iat) && + payload.iat > nowSeconds + CLOCK_SKEW_LEEWAY_SECONDS + ) { + return yield* new UnauthorizedError({ + message: "Invalid JWT: iat claim is in the future", + }); + } + }); + +/** + * Rejects tokens claiming a lifetime longer than the workspace cap. When + * `iat` is absent the token is assumed to have been minted now, so the check + * degrades to `exp - now`, which still stops `exp = now + 30 days` tokens. + */ +const enforceMaxLifetime = ( + payload: jose.JWTPayload, + maxTokenLifetime: Duration.Duration, + nowSeconds: number = Math.floor(Date.now() / 1000) +): Effect.Effect => + Effect.gen(function* () { + if (!isNumber(payload.exp)) { + // enforceTimeClaims already rejected a missing exp; this is defensive + // against a non-numeric exp that jose somehow let through. + return yield* new UnauthorizedError({ message: "Invalid JWT" }); + } + + const issuedAt = isNumber(payload.iat) ? payload.iat : nowSeconds; + const maxLifetimeSeconds = Duration.toSeconds(maxTokenLifetime); + + if (payload.exp - issuedAt > maxLifetimeSeconds) { + return yield* new UnauthorizedError({ + message: "Invalid JWT: token lifetime exceeds the workspace cap", + }); + } + }); diff --git a/packages/domain/src/organization/repository.ts b/packages/domain/src/organization/repository.ts index 6d0b288a9..48ea86d0b 100644 --- a/packages/domain/src/organization/repository.ts +++ b/packages/domain/src/organization/repository.ts @@ -21,6 +21,10 @@ interface TFindMemberRole { userId: string; } +interface TFindJwtMaxTokenLifetime { + organizationId: string; +} + const makeOrganizationRepository = Effect.gen(function* () { const db = yield* currentDb; @@ -56,6 +60,22 @@ const makeOrganizationRepository = Effect.gen(function* () { createdAt: schema.organizationTable.createdAt, }) .pipe(Effect.map(EffectArray.get(0))), + findJwtMaxTokenLifetimeMinutes: ({ + organizationId, + }: TFindJwtMaxTokenLifetime) => + db + .select({ + jwtMaxTokenLifetimeMinutes: + schema.organizationTable.jwtMaxTokenLifetimeMinutes, + }) + .from(schema.organizationTable) + .where(eq(schema.organizationTable.id, organizationId)) + .pipe( + Effect.map((rows) => { + const [row] = rows; + return row?.jwtMaxTokenLifetimeMinutes ?? null; + }) + ), findMemberRole: ({ organizationId, userId }: TFindMemberRole) => db .select({ diff --git a/packages/domain/src/widget/api-live.ts b/packages/domain/src/widget/api-live.ts index 078bc340b..b37c90a64 100644 --- a/packages/domain/src/widget/api-live.ts +++ b/packages/domain/src/widget/api-live.ts @@ -22,7 +22,11 @@ import { EmailOutboxConfig } from "../email-outbox/config"; import { Api } from "../http/api"; import { recordPostIntegrationEvent } from "../integration/post-event-recording"; import { JwtSecretRepository } from "../jwt-secret/repository"; -import { verifyJwt } from "../jwt-secret/verification"; +import { + maxTokenLifetimeFromMinutes, + verifyJwt, +} from "../jwt-secret/verification"; +import { OrganizationRepository } from "../organization/repository"; import { PostStatusRepository } from "../post-status/repository"; import { PostEmbeddingService, @@ -266,6 +270,17 @@ export const WidgetApiLive = HttpApiBuilder.group( }); } + // Per-workspace lifetime cap tightens (never loosens) the 24h + // default; invalid stored values fall back to the default. + const organizationRepository = yield* OrganizationRepository; + const maxTokenLifetimeMinutes = + yield* organizationRepository.findJwtMaxTokenLifetimeMinutes({ + organizationId, + }); + const maxTokenLifetime = maxTokenLifetimeFromMinutes( + maxTokenLifetimeMinutes + ); + const contactDefs = // SAFETY: the repository contract returns contact attribute definitions // in the canonical domain shape; the cast bridges the DB-row encoding. @@ -282,7 +297,8 @@ export const WidgetApiLive = HttpApiBuilder.group( const jwtPayload = yield* verifyJwt( token, secrets.map((s) => s.secret), - organizationId + organizationId, + { maxTokenLifetime } ); const parsedContact = yield* parsePersonAttributes( @@ -384,6 +400,7 @@ export const WidgetApiLive = HttpApiBuilder.group( CompanyRepository.layer, ContactRepository.layer, JwtSecretRepository.layer, + OrganizationRepository.layer, EmailOutboxConfig.layer, PostRepository.layer, PostStatusRepository.layer, diff --git a/packages/domain/src/widget/sso.test.ts b/packages/domain/src/widget/sso.test.ts index 3f48cbb09..ec6b9074f 100644 --- a/packages/domain/src/widget/sso.test.ts +++ b/packages/domain/src/widget/sso.test.ts @@ -196,19 +196,20 @@ describe("createSsoSession", () => { }) ); - it.effect("accepts a token without an exp claim (exp is optional)", () => + it.effect("rejects a token without an exp claim (exp is required)", () => Effect.gen(function* () { const fixture = yield* makeFixture(true); const { exp: _exp, ...payloadWithoutExp } = validPayload(fixture); const token = yield* signToken(payloadWithoutExp, fixture.secret); - const result = yield* createSsoSession({ - clientIp: fixture.clientIp, - organizationId: fixture.organizationId, - token, - }); - - expect(result.name).toBe("Ada Lovelace"); + const error = yield* Effect.flip( + createSsoSession({ + clientIp: fixture.clientIp, + organizationId: fixture.organizationId, + token, + }) + ); + expect(error.code).toBe("INVALID_JWT"); }) ); @@ -234,6 +235,90 @@ describe("createSsoSession", () => { }) ); + it.effect( + "rejects a token claiming a lifetime beyond the 24h default cap", + () => + Effect.gen(function* () { + const fixture = yield* makeFixture(true); + const token = yield* signToken( + { + ...validPayload(fixture), + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 25 * 3600, + }, + fixture.secret + ); + + const error = yield* Effect.flip( + createSsoSession({ + clientIp: fixture.clientIp, + organizationId: fixture.organizationId, + token, + }) + ); + expect(error.code).toBe("INVALID_JWT"); + }) + ); + + it.effect("enforces a tightened per-organization lifetime cap", () => + Effect.gen(function* () { + const fixture = yield* makeFixture(true); + const db = yield* currentDb; + yield* db + .update(schema.organizationTable) + .set({ jwtMaxTokenLifetimeMinutes: 60 }) // 1 hour + .where(eq(schema.organizationTable.id, fixture.organizationId)); + + // 2-hour lifetime: fine under the 24h default, too long for this org. + const token = yield* signToken( + { + ...validPayload(fixture), + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 2 * 3600, + }, + fixture.secret + ); + + const error = yield* Effect.flip( + createSsoSession({ + clientIp: fixture.clientIp, + organizationId: fixture.organizationId, + token, + }) + ); + expect(error.code).toBe("INVALID_JWT"); + }) + ); + + it.effect( + "accepts a token within a tightened per-organization lifetime cap", + () => + Effect.gen(function* () { + const fixture = yield* makeFixture(true); + const db = yield* currentDb; + yield* db + .update(schema.organizationTable) + .set({ jwtMaxTokenLifetimeMinutes: 60 }) + .where(eq(schema.organizationTable.id, fixture.organizationId)); + + const token = yield* signToken( + { + ...validPayload(fixture), + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 30 * 60, + }, + fixture.secret + ); + + const result = yield* createSsoSession({ + clientIp: fixture.clientIp, + organizationId: fixture.organizationId, + token, + }); + expect(result.name).toBe("Ada Lovelace"); + }) + ); + it.effect("rejects a token signed with another organization's secret", () => Effect.gen(function* () { const fixture = yield* makeFixture(true); diff --git a/packages/domain/src/widget/sso.ts b/packages/domain/src/widget/sso.ts index 9a3f0fde1..77e9de0c0 100644 --- a/packages/domain/src/widget/sso.ts +++ b/packages/domain/src/widget/sso.ts @@ -23,7 +23,11 @@ import type { ParsedPersonAttributes } from "../contact/utils"; import { parsePersonAttributes } from "../contact/utils"; import { EntitlementPolicy } from "../entitlement/policies"; import { JwtSecretRepository } from "../jwt-secret/repository"; -import { verifyJwt } from "../jwt-secret/verification"; +import { + maxTokenLifetimeFromMinutes, + verifyJwt, +} from "../jwt-secret/verification"; +import { OrganizationRepository } from "../organization/repository"; import { PolicyDeniedError } from "../policy"; import { RateLimitService } from "../rate-limit/service"; import { UserRepository } from "../user/repository"; @@ -206,10 +210,26 @@ export const createSsoSession = ({ }); } + // Per-workspace lifetime cap: `organization.jwt_max_token_lifetime_minutes` + // tightens (never loosens) the 24h default so a workspace can shorten how + // long a leaked token stays replayable. Invalid stored values fall back to + // the default. A missing org row (impossible via + // the FK) falls back to the default; other failures are normalized by the + // outer catch below. + const organizationRepository = yield* OrganizationRepository; + const maxTokenLifetimeMinutes = + yield* organizationRepository.findJwtMaxTokenLifetimeMinutes({ + organizationId, + }); + const maxTokenLifetime = maxTokenLifetimeFromMinutes( + maxTokenLifetimeMinutes + ); + const jwtPayload = yield* verifyJwt( token, secrets.map((s) => s.secret), - organizationId + organizationId, + { maxTokenLifetime } ).pipe(Effect.mapError(() => new SsoError({ code: "INVALID_JWT" }))); // Bound contact and user provisioning only after a JWT has proved that @@ -352,5 +372,6 @@ export const SsoRepositoriesLive = Layer.mergeAll( CompanyRepository.layer, ContactRepository.layer, JwtSecretRepository.layer, + OrganizationRepository.layer, UserRepository.layer );