From 16c558e5baeca3f9ef8990e326fbac6b3d7c1a6b Mon Sep 17 00:00:00 2001 From: kevin li Date: Tue, 3 Nov 2026 21:23:27 -0500 Subject: [PATCH 1/2] [#647] Add Career job storage schema and migration Co-authored-by: Codex --- .forge/features/career-job-storage/spec.md | 17 + .forge/features/career-job-storage/srd.md | 100 + .forge/features/career-job-storage/status.md | 151 + .../features/career-job-storage/test-cases.md | 15 + .../src/lib/member-profile-form-values.ts | 2 + .../tests/member/member-dashboard.test.tsx | 2 + .../member-profile-settings-form.test.tsx | 2 + docs/DATABASE-USAGE.md | 45 + .../db/drizzle/0064_career_job_storage.sql | 177 + packages/db/drizzle/meta/0064_snapshot.json | 16427 ++++++++++++++++ packages/db/drizzle/meta/_journal.json | 7 + packages/db/src/client.ts | 3 + packages/db/src/schemas/job-board.ts | 420 + packages/db/src/schemas/knight-hacks.ts | 2 + packages/db/src/schemas/relations.ts | 57 + .../db/src/tests/job-board-migration.test.ts | 452 + .../db/src/tests/migration-lineage.test.ts | 6 +- 17 files changed, 17882 insertions(+), 3 deletions(-) create mode 100644 .forge/features/career-job-storage/spec.md create mode 100644 .forge/features/career-job-storage/srd.md create mode 100644 .forge/features/career-job-storage/status.md create mode 100644 .forge/features/career-job-storage/test-cases.md create mode 100644 packages/db/drizzle/0064_career_job_storage.sql create mode 100644 packages/db/drizzle/meta/0064_snapshot.json create mode 100644 packages/db/src/schemas/job-board.ts create mode 100644 packages/db/src/tests/job-board-migration.test.ts diff --git a/.forge/features/career-job-storage/spec.md b/.forge/features/career-job-storage/spec.md new file mode 100644 index 000000000..7be4f9d1a --- /dev/null +++ b/.forge/features/career-job-storage/spec.md @@ -0,0 +1,17 @@ +# Career Job Storage + +Implement storage for #647, part of #633. Members will explore jobs, track +applications, find others in process, and configure alerts. Officers will register +employer boards for supported providers. This slice adds storage and tests only. + +Agreed behavior: seven new tables; one primary Discord post total per job; multiple +locations per listing; shared daily digests with separate track opt-ins. Retain +inactive jobs for application history. Rolling-feed disappearance or failed polls +cannot establish closure. Explicit employer evidence determines track; otherwise +keep the first accepted track. Reclassification never authorizes another post. + +Reuse existing company identity without auto-approving scraped companies. Members +control application visibility and private notes always remain private. No UI, +API workflows, production migration, old preference import or historical job +import is included. Acceptance: isolated migration succeeds, existing data survives, +opt-ins default off, constraints reject invalid/duplicate records, consumers compile. diff --git a/.forge/features/career-job-storage/srd.md b/.forge/features/career-job-storage/srd.md new file mode 100644 index 000000000..a8249fd09 --- /dev/null +++ b/.forge/features/career-job-storage/srd.md @@ -0,0 +1,100 @@ +# Career Job Storage SRD + +Status: Implementing the design approved in the November 3 conversation. +References: #647, parent #633, vocabulary #646 / PR #658. + +## Ownership and access + +Seven tables live in packages/db/src/schemas/job-board.ts, with relations registered +in the existing client. Enums reuse JOB_BOARD. API owns matching, normalization, +transactions and access; Cron orchestrates adapters/delivery; Blade owns interfaces. +No API/Cron/UI behavior is implemented here. Career reads require sign-in and a +Member profile. Members mutate only their applications/preferences. Community DTOs +exclude private applications and never select privateNotes. Officer changes require +explicit control permissions and audits in the later API/settings issue. The DB +schema does not enforce end-user authorization. + +## Tables + +| Table | Identity and state | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Job | Unique identityKey; company label/key and optional Company FK; title/track/category/URL/description/compensation/arrangement; posted/first-seen/last-seen dates; active/inactive state; single Discord destination, frozen delivery track, receipt and retry/claim state | +| JobSource | Unique provider/boardKey; label, optional Company FK, enabled flag, polling interval/checkpoints, baseline completion, conditional-request validators and claim/error state | +| JobObservation | Unique source/external ID; Job FK; source URL/data, posted/first/last-seen dates and inactivity evidence | +| JobLocation | Job FK; original text; city/state/remote_us/unknown kind; Census city key and state | +| JobAlertPreference | Unique member/track/kind/targetKey; optional original custom value | +| JobApplication | Unique member/job; stage/round/visibility/private notes; timestamps | +| JobDigest | Unique track/scheduled instant; frozen window/destination; receipt and retry/claim state | + +Member gets two non-null, false-default digest opt-in booleans. All seven tables +count against the limit; no join-table exception. Reuse DiscordConfig for channel +and role IDs in the later settings implementation, with no routing changes here. + +Provider is a code-owned adapter key. boardKey is officer-managed feed/board identity. +New providers require code; existing supported boards can be registered later via +Blade. Sources default disabled; jobs default suppressed. No seed or runtime import. +Polling baselines and source health live on JobSource, not a generic config store. + +API computes identityKey from a namespaced employer requisition ID or normalized +employer apply URL; unknown identities use namespaced source/external identity. +Never match on company/title alone. Unique identities protect concurrent inserts; +cross-source matching and conflict retries require API code. Create/find a job and +link its observation in one transaction. Source/observation history is retained; +disable sources and inactivate jobs rather than deleting them. + +Keep companyLabel/companyKey even if Company resolution fails. Do not automatically +create/approve Guild companies. Company FKs SET NULL on delete; future reads resolve +mergedIntoCompanyId and merge integration needs API tests. Existing moderation is +unchanged. Locations use existing NN-NNNNN Census keys. City requires city/state; +state requires state alone; remote/unknown have neither. Preserve original text; +remote alone is not U.S. evidence. Catalog membership is API validation. Multiple +source descriptions may resolve to the same city. + +Alert targetKey is a normalized company key, Census city key, remote_us or normalized +custom location text. customValue preserves Other input. API normalization dedupes +semantically equivalent targets. Applications reference Member.id; deleting a member +cascades preferences/applications. Jobs with applications cannot be deleted. Rounds +are integers 1..10 only for interviewing. Notes are capped at 2000 characters. + +## Delivery contracts for follow-up work + +Sent requires message ID and timestamp. Sending requires a claim; token/expiry are +paired. Non-suppressed job delivery requires channel and frozen delivery track. +Workers atomically claim rows and fence completion by token. Discord calls happen +outside DB transactions. Expired sending becomes uncertain: reconcile a deterministic +job/digest marker before retrying. Schema alone does not guarantee exactly-once sends. +A sent job is never requeued merely because its classification or channel changes. + +Digests use a row per track/scheduled instant, even if routing changes. Select sent +jobs by frozen delivery track/channel and deliveredAt in (windowStart, windowEnd]. +Window end cannot exceed scheduledAt. Freeze boundaries before sending; suppress +empty windows. Preserve daily 4 PM America/New_York behavior in the future worker. +Member flags represent desired digest role subscriptions; role reconciliation uses +User.discordUserId, never Member.discordUser (a username). + +Posted dates remain separate from discovery. Closure requires explicit evidence or +absence from a successful complete employer inventory. Rolling-feed disappearance +and failures do not close observations. API aggregates trustworthy observation +activity. No closure, track-selection or delivery triggers are introduced. + +## Migration and verification + +Generate additive SQL, snapshot and journal. Validate only in disposable local DBs. +No existing job/preference import or production migration. Existing member opt-ins +become false. Application rollback leaves unused storage intact; never drop user +history casually. Root format/lint/typecheck cover affected consumers; run DB tests +and validator regressions. No React changes. User approval authorizes local work; +GitHub #633 review remains separately recorded, not claimed complete. + +### Identifier fingerprints + +Job.identityHash, JobSource.boardKeyHash and JobObservation.externalIdHash are +stored, database-generated SHA-256 hex fingerprints of the original UTF-8 keys. +Unique constraints target the fingerprint, with provider/sourceId where applicable, +so long URLs and provider identifiers do not exceed PostgreSQL B-tree limits. +The original values remain intact. Future writers must use these columns as +Drizzle conflict targets and verify the original key matches before updating a +conflicting row; a mismatched key is an error, never permission to overwrite. +Indexed lookups should compute the same SHA-256 fingerprint and compare the raw +key as well. No ingestion/upsert service is implemented in this database-only work. +Migration 0064 creates the fingerprint columns and their unique constraints directly. diff --git a/.forge/features/career-job-storage/status.md b/.forge/features/career-job-storage/status.md new file mode 100644 index 000000000..f1b136b34 --- /dev/null +++ b/.forge/features/career-job-storage/status.md @@ -0,0 +1,151 @@ +# Career Job Storage Status + +Current phase: Squashed migration validated; awaiting dev-lead schema approval and PR review. + +## Decisions + +- 2026-11-03: User approved database-only #647 after reverse prompting: seven tables, + one post per job, supported-source configuration, Member digest opt-ins and JobDigest. +- Employer track evidence wins; fallback is first accepted track. No repost on + reclassification. Rolling-feed disappearance cannot close a job. +- User requested following through with the agreed plan, authorizing local schema + and migration work. No production database writes. +- Branch: db/career-job-storage. Existing .claude/settings.local.json is unrelated. + +## Progress + +- [x] Reverse-prompt scope and decisions; document agreed design and test scenarios. +- [x] Complete schema and relations. +- [x] Generate and review additive migration. +- [x] Run isolated database tests and validator regressions. +- [x] Run root checks, inspect diff and prepare handoff. + +## Validation + +- Feature generator passed. Git refs and pnpm store required sandbox escalation. +- Use pnpm.cmd: PowerShell blocks pnpm.ps1. Node is 25.8.0; repo wants ^24.22.1. +- `pnpm.cmd typecheck`: passed, 33 tasks. Adding Member fields required two + Blade fixture updates and excluding digest fields from the profile form source + type; no rendered UI or form behavior changed. +- `pnpm.cmd lint`: passed, 31 tasks, warnings only (including existing large + files and the new integration-test describe block). +- `pnpm.cmd --filter @forge/db with-env vitest run`: 166 passed, 2 failed. + One failure was the expected migration-count update, now fixed and verified. + The other is the unchanged historical SQL checksum described below. +- Final `pnpm.cmd --filter @forge/db with-env vitest run +src/tests/job-board-migration.test.ts src/tests/migration-lineage.test.ts`: + 10 passed, 1 failed. All 9 new storage tests and the updated journal/snapshot + lineage test pass. Fresh migration and populated-table upgrade run on disposable + databases, including concurrent inserts through independent pool connections. +- Remaining checksum failure: `0010_wooden_supreme_intelligence.sql` is CRLF in + this Windows checkout (SHA-256 starts e5285213); Git HEAD and LF-normalized bytes + both match the expected a620ea7e hash. Historical SQL files were not changed. +- `pnpm.cmd --filter @forge/validators exec vitest run +src/tests/job-board.test.ts`: 30 passed. +- Three targeted Blade files (member-dashboard, member-profile-settings-form, + member-profile-form-values): 19 tests passed. +- `pnpm.cmd format`: failed across 24 packages on existing checkout formatting. + Untouched `packages/consts/src/career.ts` fails Prettier with its CRLF bytes and + passes when checked in memory with LF only. No repo-wide formatting changes. +- Explicit Prettier check of all changed source, test, document and metadata + files: passed. `git diff --check`: passed. +- `pnpm.cmd --filter @forge/db with-env drizzle-kit generate`: final check + reports no schema changes. Generated `0064_career_job_storage.sql`, snapshot and + journal are aligned. Original line endings restored on unchanged older snapshots + after the generator's broad metadata formatter; no historical content changes. + +## Handoff + +- Renamed the uncommitted migration to `0064_career_job_storage.sql` at the + user's request; updated journal and test references. Targeted rerun: 10 passed, + with the unrelated historical checksum test excluded (1 skipped). +- Seven tables, eight enums, two false-default Member columns, query relations, + named uniqueness/check constraints and search/delivery indexes are implemented. +- Design and follow-up runtime/access contracts are in srd.md. No current app + sends jobs, syncs digest roles, or accepts source settings through this change. +- Migration is local and uncommitted; no production/shared database was migrated. +- Root formatting and historical checksum remain checkout limitations. No commit + or push was made, and GitHub review in #633 is still outstanding. + +## Linux contribution review + +- Ran the Forge standard review with migration, test-quality and placement + reviewers after a green static gate. Used an isolated LF copy in Docker with + Node 24.22.1 and PostgreSQL 16, matching CI; only .env.example placeholders and + disposable database credentials were used. The original checkout was preserved. +- `pnpm verify:precommit`: passed (React changed-file analysis, root formatting, + 31 lint tasks and 33 typecheck tasks). Cold API lint/build exceeded Node's default + heap; retry used NODE_OPTIONS=--max-old-space-size=6144 and TURBO_CONCURRENCY=1. +- `pnpm build`: passed, 21 tasks. `pnpm lint:ws` also passed during installation. +- Full non-DB CI command, `pnpm exec turbo run test --filter='!@forge/db'`: + passed, 28 tasks, including 1,134 API tests and 911 Blade tests. Other consumers + also passed (2026: 190, Club: 11, Cron: 62, Guild: 18). Final modified DB test + file passed its targeted lint and formatting checks after the review fixes. +- `pnpm db:migrate` applied the complete migration chain successfully; running it + a second time succeeded without pending changes. +- Full DB suite: 168 tests across 31 files passed on LF/PostgreSQL 16. The first + concurrent run hit an unrelated 5-second event-workflow timeout; a one-worker + retry passed without changing that test or increasing its timeout. +- Fixed a real CI portability issue: PostgreSQL 16 reports 23503 for the protected + job deletion while PostgreSQL 18 reports 23001. The assertion now checks the + specific application foreign-key constraint instead of the version-dependent code. +- Fixed a masked receipt test: set a valid destination before asserting that sent + jobs require receipts, assert the receipt constraint by name, and test both + one-sided receipt cases. All 9 storage tests passed again after this change. +- No actionable placement/current-consumer findings. Existing Guild projections + do not expose application notes or the new digest fields; profile updates do + not overwrite digest preferences. + +### Resolved P2: unbounded keys in unique B-tree indexes + +Review reproduced index-size failures for long Job.identityKey, JobSource.boardKey +and JobObservation.externalId values on PostgreSQL 16. User requested continuing +with the fix. The squashed migration 0064 creates stored SHA-256 fingerprint +columns and the three unique constraints directly, preserving original keys. +Named generated columns support typed Drizzle conflict targets. The immutable +conversion preserves Unicode and literal backslashes. Future writers must verify +raw-key equality before updating a fingerprint conflict; ingestion is out of scope. + +Regression coverage includes incompressible 8KB identifiers, Unicode/backslashes, +duplicate upserts, distinct identifiers, and preservation of existing member/company data. + +Final validation after the fix: + +- `pnpm verify:precommit` passed in the isolated LF/Node 24.22.1 environment: + React analysis, format (24 tasks), lint (31 tasks), typecheck (33 tasks). +- Full PostgreSQL 16 DB suite: 169 tests across 31 files passed. +- `pnpm db:migrate` passed twice against the isolated DB; Drizzle generation found + no schema drift. +- Normalized checksums confirm all changed app/package files match the tested copy. +- Standard review: migration and test reviewers rechecked the fix with no remaining + blockers; the earlier placement review remains applicable. +- Full build and non-DB suites passed earlier in this review; after the fingerprint + change, the root static gate and complete DB suite were rerun. +- No new tables, dependencies, or CI-setting changes in the identifier fix. + GitHub #633 design approval remains outstanding. No push or production migration. + +## Links + +- https://github.com/KnightHacks/forge/issues/647 +- https://github.com/KnightHacks/forge/issues/633 +- https://github.com/KnightHacks/forge/pull/658 +- No GitHub comment, PR or lead review has been recorded by this session. + +## Migration squash follow-up + +User explicitly requested squashing 0064/0065 and clarifying the hash helper. +Only disposable local databases were migrated by this session; no shared deployment +or push occurred. Regenerated one descriptive 0064 migration and snapshot from +0063, updated the journal/lineage assertions and single-migration upgrade test, +and removed the obsolete intermediate-state backfill test. Hash behavior and +seven-table scope are unchanged. The helper explains the B-tree entry limit, +literal backslash handling, and generated-column immutability requirement. +Validation passed: 12 focused migration/lineage tests on PostgreSQL 16; fresh +migration and idempotent rerun; targeted formatting/lint, DB typecheck, and no +Drizzle schema drift. The user additionally confirmed that root lint, root +typecheck, DB tests, and db:generate ran after the squash. The local 0010 lineage +check has a CRLF-only failure; the isolated LF lineage suite passed. +User authorized committing and pushing this branch. PR text will be drafted for +review only; posting requires an explicit request. Dev-lead schema approval is +still outstanding. Optional follow-ups: delivery_track digest index coverage and +an automated schema-drift regression test. diff --git a/.forge/features/career-job-storage/test-cases.md b/.forge/features/career-job-storage/test-cases.md new file mode 100644 index 000000000..13f947559 --- /dev/null +++ b/.forge/features/career-job-storage/test-cases.md @@ -0,0 +1,15 @@ +# Career Job Storage Test Cases + +- TC01: Fresh migration creates seven tables; sources default disabled and jobs suppressed. +- TC02: Concurrent duplicate job and observation identities yield one successful insert; multiple sources may reference one job. +- TC03: City/state/remote/unknown locations retain text. Reject malformed keys and contradictory shapes. +- TC04: One application per member/job; enforce stage/round bounds. Inactivity preserves history and deletion cannot remove referenced jobs. +- TC05: Sent job/digest records require receipts; reject malformed IDs, unpaired leases and sending without a claim. +- TC06: Duplicate digest schedule fails despite destination changes; reject reversed/future windows. +- TC07: Alert identity is unique per member/track/kind/target; member deletion cascades personal records. +- TC08: Upgrade pre-feature member/company fixtures; preserve values and default both opt-ins false. +- TC09: Query new relations through the DB client; all consumers typecheck and validators regress cleanly. +- TC10: Preserve incompressible long identifiers, Unicode and literal backslashes; generated fingerprints match UTF-8 SHA-256 and typed upserts resolve duplicates. Distinct job identifiers remain distinct. + +API privacy, matching, closure, authorization, role sync and actual Discord recovery +are follow-up tests, not claims made by this schema implementation. diff --git a/apps/blade/src/lib/member-profile-form-values.ts b/apps/blade/src/lib/member-profile-form-values.ts index ec87cea37..10b55de07 100644 --- a/apps/blade/src/lib/member-profile-form-values.ts +++ b/apps/blade/src/lib/member-profile-form-values.ts @@ -13,6 +13,8 @@ export type MemberProfileFormSource = Omit< | "currentCityKey" | "gender" | "guildLocationVisible" + | "jobInternshipDigestEnabled" + | "jobNewGradDigestEnabled" | "levelOfStudy" | "major" | "raceOrEthnicity" diff --git a/apps/blade/src/tests/member/member-dashboard.test.tsx b/apps/blade/src/tests/member/member-dashboard.test.tsx index a7ffb16ba..0f52aad64 100644 --- a/apps/blade/src/tests/member/member-dashboard.test.tsx +++ b/apps/blade/src/tests/member/member-dashboard.test.tsx @@ -54,6 +54,8 @@ vi.mock("~/app/_components/member/guild-preferences-dialog", () => ({ })); const member: CurrentMember = { + jobInternshipDigestEnabled: false, + jobNewGradDigestEnabled: false, about: "My name is Dylan Vidal, and I am the Dev Lead of Knight Hacks. My messages are always open.", alumniConfirmedAt: null, diff --git a/apps/blade/src/tests/member/member-profile-settings-form.test.tsx b/apps/blade/src/tests/member/member-profile-settings-form.test.tsx index 45b09fe06..388913526 100644 --- a/apps/blade/src/tests/member/member-profile-settings-form.test.tsx +++ b/apps/blade/src/tests/member/member-profile-settings-form.test.tsx @@ -88,6 +88,8 @@ vi.mock("~/app/_components/member/member-resume-upload", () => ({ })); const member: CurrentMember = { + jobInternshipDigestEnabled: false, + jobNewGradDigestEnabled: false, about: "I like building member tools.", alumniConfirmedAt: null, age: 24, diff --git a/docs/DATABASE-USAGE.md b/docs/DATABASE-USAGE.md index 0148c97e5..6c86efcb6 100644 --- a/docs/DATABASE-USAGE.md +++ b/docs/DATABASE-USAGE.md @@ -178,6 +178,38 @@ Notes: - There is no admin UI yet, so writes happen in SQL — the same state the Discord config table is in. - `auth_roles.event_feedback_excluded` is unrelated to these tables and remains the durable source for feedback eligibility. The role-name lists that used to seed it are gone; migration `0013` already wrote the column. +## Career job storage + +The seven tables in `schemas/job-board.ts` support the Career integration (#647). +They are storage contracts; ingestion, member APIs and Discord workers are separate +follow-up work. Sources default disabled and jobs default to suppressed delivery. + +| Table | Usage | +| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Job` | Canonical listing with a unique API-normalized identity key, optional existing Company link, original company label/grouping key, dates, active state and one primary Discord delivery receipt/claim. | +| `JobSource` | Supported adapter/board identity, officer-editable enablement, poll schedule, baseline and conditional-request/claim state. | +| `JobObservation` | One upstream listing per source/external ID, pointing to a canonical job; not one row per poll. | +| `JobLocation` | Multiple locations for a job, preserving original text even when unknown. Census city keys use `NN-NNNNN`; remote alone does not imply U.S. eligibility. | +| `JobAlertPreference` | Member-owned normalized company/location targets per track, retaining custom Other text. | +| `JobApplication` | One member/job application, with stage, optional interview round, visibility and private notes. Inactive jobs retain history. | +| `JobDigest` | Shared daily digest delivery per track/scheduled instant, with frozen window/destination and recovery state. | + +`Member.jobInternshipDigestEnabled` and `jobNewGradDigestEnabled` default false and +represent desired digest-role subscriptions, not proof of Discord role assignment. +Member records reference `User` for numeric Discord identity. `Member.discordUser` +is a username and must not be used for mentions. + +Keep company moderation separate from ingestion: jobs may have no `companyId`; +they always retain company label/key. Resolve Company merges in API reads. Never +auto-approve scraped employers into Guild. Discord routing belongs in existing +`DiscordConfig`, not an additional job configuration table. + +API workers must fence claim completion and reconcile uncertain Discord sends. +Unique keys and receipt checks alone cannot guarantee exactly-once external sends. +Do not return raw application rows: private notes are always private, including +when application visibility is community. No end-user row authorization is implied +by these foreign keys. + ## Undocumented columns If a task needs a table or column not explained here, inspect existing usage first. If the intended semantics are still not clear from code, ask a clarifying question before setting a new precedent. @@ -191,3 +223,16 @@ Team mutations and check-in share the hackathon allocation advisory lock. The fi Organizer status changes away from confirmed/checked-in, application withdrawal, and deletion remove membership in the same transaction, promote a random remaining member if the owner leaves, and delete an empty team. Composite foreign keys keep attendees, teams, and the stored class within one hackathon. Both team tables are excluded from sanitized development backups. Legacy bulk status check-in rejects hackers with teams or pending requests; the Hackathon Check-in workspace performs their class assignment. The attendee membership foreign key uses `NO ACTION` so account cascades cannot silently orphan teams. Account deletion asks the user to leave teams/cancel requests first, with organizer removal available when their Teams page is locked. + +### Identifier fingerprints + +Job.identityHash, JobSource.boardKeyHash and JobObservation.externalIdHash are +stored, database-generated SHA-256 hex fingerprints of the original UTF-8 keys. +Unique constraints target the fingerprint, with provider/sourceId where applicable, +so long URLs and provider identifiers do not exceed PostgreSQL B-tree limits. +The original values remain intact. Future writers must use these columns as +Drizzle conflict targets and verify the original key matches before updating a +conflicting row; a mismatched key is an error, never permission to overwrite. +Indexed lookups should compute the same SHA-256 fingerprint and compare the raw +key as well. No ingestion/upsert service is implemented in this database-only work. +Migration 0064 creates the fingerprint columns and their unique constraints directly. diff --git a/packages/db/drizzle/0064_career_job_storage.sql b/packages/db/drizzle/0064_career_job_storage.sql new file mode 100644 index 000000000..40836d0c0 --- /dev/null +++ b/packages/db/drizzle/0064_career_job_storage.sql @@ -0,0 +1,177 @@ +CREATE TYPE "public"."job_alert_target_kind" AS ENUM('company', 'location');--> statement-breakpoint +CREATE TYPE "public"."job_application_stage" AS ENUM('saved', 'applied', 'online_assessment', 'recruiter_screen', 'interviewing', 'final_round', 'offer', 'rejected', 'withdrawn');--> statement-breakpoint +CREATE TYPE "public"."job_application_visibility" AS ENUM('community', 'private');--> statement-breakpoint +CREATE TYPE "public"."job_category" AS ENUM('swe', 'data_ai', 'pm', 'it_security', 'quant', 'analyst', 'hardware', 'design', 'other');--> statement-breakpoint +CREATE TYPE "public"."job_delivery_state" AS ENUM('pending', 'sending', 'sent', 'uncertain', 'suppressed');--> statement-breakpoint +CREATE TYPE "public"."job_location_kind" AS ENUM('city', 'state', 'remote_us', 'unknown');--> statement-breakpoint +CREATE TYPE "public"."job_track" AS ENUM('internship', 'new_grad');--> statement-breakpoint +CREATE TYPE "public"."job_work_arrangement" AS ENUM('onsite', 'hybrid', 'remote');--> statement-breakpoint +CREATE TABLE "knight_hacks_job" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "identity_key" text NOT NULL, + "identity_hash" text GENERATED ALWAYS AS (encode(sha256(decode(replace("identity_key", chr(92), chr(92) || chr(92)), 'escape')), 'hex')) STORED NOT NULL, + "company_id" uuid, + "company_label" varchar(200) NOT NULL, + "company_key" varchar(120) NOT NULL, + "title" text NOT NULL, + "track" "job_track" NOT NULL, + "category" "job_category", + "apply_url" text NOT NULL, + "description" text, + "compensation" text, + "work_arrangement" "job_work_arrangement", + "posted_at" timestamp with time zone, + "first_seen_at" timestamp with time zone DEFAULT now() NOT NULL, + "last_seen_at" timestamp with time zone DEFAULT now() NOT NULL, + "active" boolean DEFAULT true NOT NULL, + "inactive_at" timestamp with time zone, + "delivery_state" "job_delivery_state" DEFAULT 'suppressed' NOT NULL, + "delivery_track" "job_track", + "discord_channel_id" varchar(20), + "discord_message_id" varchar(20), + "delivered_at" timestamp with time zone, + "delivery_claim_token" uuid, + "delivery_lease_expires_at" timestamp with time zone, + "delivery_next_attempt_at" timestamp with time zone, + "delivery_attempts" integer DEFAULT 0 NOT NULL, + "delivery_error" text, + CONSTRAINT "knight_hacks_job_identity_unique" UNIQUE("identity_hash"), + CONSTRAINT "knight_hacks_job_discord_message_unique" UNIQUE("discord_message_id"), + CONSTRAINT "knight_hacks_job_values_check" CHECK ("knight_hacks_job"."identity_key" ~ '[^[:space:]]' AND "knight_hacks_job"."company_label" ~ '[^[:space:]]' AND "knight_hacks_job"."company_key" ~ '[^[:space:]]' AND "knight_hacks_job"."title" ~ '[^[:space:]]' AND "knight_hacks_job"."apply_url" ~ '^https?://' AND "knight_hacks_job"."delivery_attempts" >= 0), + CONSTRAINT "knight_hacks_job_dates_check" CHECK ("knight_hacks_job"."last_seen_at" >= "knight_hacks_job"."first_seen_at" AND ("knight_hacks_job"."active" = ("knight_hacks_job"."inactive_at" IS NULL))), + CONSTRAINT "knight_hacks_job_channel_check" CHECK ("knight_hacks_job"."discord_channel_id" IS NULL OR "knight_hacks_job"."discord_channel_id" ~ '^[0-9]{17,20}$'), + CONSTRAINT "knight_hacks_job_message_check" CHECK ("knight_hacks_job"."discord_message_id" IS NULL OR "knight_hacks_job"."discord_message_id" ~ '^[0-9]{17,20}$'), + CONSTRAINT "knight_hacks_job_lease_check" CHECK (("knight_hacks_job"."delivery_claim_token" IS NULL) = ("knight_hacks_job"."delivery_lease_expires_at" IS NULL)), + CONSTRAINT "knight_hacks_job_destination_check" CHECK ("knight_hacks_job"."delivery_state" = 'suppressed' OR ("knight_hacks_job"."discord_channel_id" IS NOT NULL AND "knight_hacks_job"."delivery_track" IS NOT NULL)), + CONSTRAINT "knight_hacks_job_receipt_check" CHECK (("knight_hacks_job"."delivery_state" = 'sent') = ("knight_hacks_job"."discord_message_id" IS NOT NULL AND "knight_hacks_job"."delivered_at" IS NOT NULL) AND ("knight_hacks_job"."discord_message_id" IS NULL) = ("knight_hacks_job"."delivered_at" IS NULL)), + CONSTRAINT "knight_hacks_job_sending_check" CHECK ("knight_hacks_job"."delivery_state" <> 'sending' OR "knight_hacks_job"."delivery_claim_token" IS NOT NULL) +); +--> statement-breakpoint +CREATE TABLE "knight_hacks_job_alert_preference" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "member_id" uuid NOT NULL, + "track" "job_track" NOT NULL, + "kind" "job_alert_target_kind" NOT NULL, + "target_key" varchar(120) NOT NULL, + "custom_value" varchar(120), + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "knight_hacks_job_alert_member_target_unique" UNIQUE("member_id","track","kind","target_key"), + CONSTRAINT "knight_hacks_job_alert_values_check" CHECK ("knight_hacks_job_alert_preference"."target_key" ~ '[^[:space:]]' AND ("knight_hacks_job_alert_preference"."custom_value" IS NULL OR "knight_hacks_job_alert_preference"."custom_value" ~ '[^[:space:]]')) +); +--> statement-breakpoint +CREATE TABLE "knight_hacks_job_application" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "member_id" uuid NOT NULL, + "job_id" uuid NOT NULL, + "stage" "job_application_stage" DEFAULT 'saved' NOT NULL, + "round" integer, + "visibility" "job_application_visibility" DEFAULT 'community' NOT NULL, + "private_notes" varchar(2000), + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "knight_hacks_job_application_member_job_unique" UNIQUE("member_id","job_id"), + CONSTRAINT "knight_hacks_job_application_round_check" CHECK ("knight_hacks_job_application"."round" IS NULL OR ("knight_hacks_job_application"."stage" = 'interviewing' AND "knight_hacks_job_application"."round" BETWEEN 1 AND 10)) +); +--> statement-breakpoint +CREATE TABLE "knight_hacks_job_digest" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "track" "job_track" NOT NULL, + "scheduled_at" timestamp with time zone NOT NULL, + "window_start" timestamp with time zone NOT NULL, + "window_end" timestamp with time zone NOT NULL, + "discord_channel_id" varchar(20) NOT NULL, + "discord_message_id" varchar(20), + "delivery_state" "job_delivery_state" DEFAULT 'pending' NOT NULL, + "delivered_at" timestamp with time zone, + "claim_token" uuid, + "lease_expires_at" timestamp with time zone, + "next_attempt_at" timestamp with time zone, + "attempts" integer DEFAULT 0 NOT NULL, + "last_error" text, + CONSTRAINT "knight_hacks_job_digest_schedule_unique" UNIQUE("track","scheduled_at"), + CONSTRAINT "knight_hacks_job_digest_message_unique" UNIQUE("discord_message_id"), + CONSTRAINT "knight_hacks_job_digest_values_check" CHECK ("knight_hacks_job_digest"."window_start" < "knight_hacks_job_digest"."window_end" AND "knight_hacks_job_digest"."window_end" <= "knight_hacks_job_digest"."scheduled_at" AND "knight_hacks_job_digest"."attempts" >= 0 AND "knight_hacks_job_digest"."discord_channel_id" ~ '^[0-9]{17,20}$' AND ("knight_hacks_job_digest"."discord_message_id" IS NULL OR "knight_hacks_job_digest"."discord_message_id" ~ '^[0-9]{17,20}$')), + CONSTRAINT "knight_hacks_job_digest_lease_check" CHECK (("knight_hacks_job_digest"."claim_token" IS NULL) = ("knight_hacks_job_digest"."lease_expires_at" IS NULL)), + CONSTRAINT "knight_hacks_job_digest_receipt_check" CHECK (("knight_hacks_job_digest"."delivery_state" = 'sent') = ("knight_hacks_job_digest"."discord_message_id" IS NOT NULL AND "knight_hacks_job_digest"."delivered_at" IS NOT NULL) AND ("knight_hacks_job_digest"."discord_message_id" IS NULL) = ("knight_hacks_job_digest"."delivered_at" IS NULL)), + CONSTRAINT "knight_hacks_job_digest_sending_check" CHECK ("knight_hacks_job_digest"."delivery_state" <> 'sending' OR "knight_hacks_job_digest"."claim_token" IS NOT NULL) +); +--> statement-breakpoint +CREATE TABLE "knight_hacks_job_location" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "job_id" uuid NOT NULL, + "source_text" text NOT NULL, + "kind" "job_location_kind" NOT NULL, + "city_key" varchar(8), + "state" varchar(2), + CONSTRAINT "knight_hacks_job_location_values_check" CHECK ("knight_hacks_job_location"."source_text" ~ '[^[:space:]]' AND ("knight_hacks_job_location"."state" IS NULL OR "knight_hacks_job_location"."state" ~ '^[A-Z]{2}$') AND ("knight_hacks_job_location"."city_key" IS NULL OR "knight_hacks_job_location"."city_key" ~ '^[0-9]{2}-[0-9]{5}$')), + CONSTRAINT "knight_hacks_job_location_shape_check" CHECK (("knight_hacks_job_location"."kind" = 'city' AND "knight_hacks_job_location"."city_key" IS NOT NULL AND "knight_hacks_job_location"."state" IS NOT NULL) OR ("knight_hacks_job_location"."kind" = 'state' AND "knight_hacks_job_location"."state" IS NOT NULL AND "knight_hacks_job_location"."city_key" IS NULL) OR ("knight_hacks_job_location"."kind" IN ('remote_us', 'unknown') AND "knight_hacks_job_location"."city_key" IS NULL AND "knight_hacks_job_location"."state" IS NULL)) +); +--> statement-breakpoint +CREATE TABLE "knight_hacks_job_observation" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "source_id" uuid NOT NULL, + "job_id" uuid NOT NULL, + "external_id" text NOT NULL, + "external_id_hash" text GENERATED ALWAYS AS (encode(sha256(decode(replace("external_id", chr(92), chr(92) || chr(92)), 'escape')), 'hex')) STORED NOT NULL, + "source_url" text, + "source_data" jsonb, + "posted_at" timestamp with time zone, + "first_seen_at" timestamp with time zone DEFAULT now() NOT NULL, + "last_seen_at" timestamp with time zone DEFAULT now() NOT NULL, + "inactive_at" timestamp with time zone, + CONSTRAINT "knight_hacks_job_observation_source_external_unique" UNIQUE("source_id","external_id_hash"), + CONSTRAINT "knight_hacks_job_observation_values_check" CHECK ("knight_hacks_job_observation"."external_id" ~ '[^[:space:]]' AND "knight_hacks_job_observation"."last_seen_at" >= "knight_hacks_job_observation"."first_seen_at") +); +--> statement-breakpoint +CREATE TABLE "knight_hacks_job_source" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "provider" varchar(64) NOT NULL, + "board_key" text NOT NULL, + "board_key_hash" text GENERATED ALWAYS AS (encode(sha256(decode(replace("board_key", chr(92), chr(92) || chr(92)), 'escape')), 'hex')) STORED NOT NULL, + "label" varchar(200) NOT NULL, + "company_id" uuid, + "enabled" boolean DEFAULT false NOT NULL, + "poll_interval_seconds" integer DEFAULT 900 NOT NULL, + "next_poll_at" timestamp with time zone DEFAULT now() NOT NULL, + "last_attempt_at" timestamp with time zone, + "last_success_at" timestamp with time zone, + "baseline_completed_at" timestamp with time zone, + "etag" text, + "last_modified" text, + "last_error" text, + "claim_token" uuid, + "lease_expires_at" timestamp with time zone, + "created_at" timestamp with time zone DEFAULT now() NOT NULL, + "updated_at" timestamp with time zone DEFAULT now() NOT NULL, + CONSTRAINT "knight_hacks_job_source_provider_board_unique" UNIQUE("provider","board_key_hash"), + CONSTRAINT "knight_hacks_job_source_values_check" CHECK ("knight_hacks_job_source"."provider" ~ '^[a-z][a-z0-9_]*$' AND "knight_hacks_job_source"."board_key" ~ '[^[:space:]]' AND "knight_hacks_job_source"."label" ~ '[^[:space:]]' AND "knight_hacks_job_source"."poll_interval_seconds" > 0), + CONSTRAINT "knight_hacks_job_source_lease_check" CHECK (("knight_hacks_job_source"."claim_token" IS NULL) = ("knight_hacks_job_source"."lease_expires_at" IS NULL)) +); +--> statement-breakpoint +ALTER TABLE "knight_hacks_member" ADD COLUMN "job_internship_digest_enabled" boolean DEFAULT false NOT NULL;--> statement-breakpoint +ALTER TABLE "knight_hacks_member" ADD COLUMN "job_new_grad_digest_enabled" boolean DEFAULT false NOT NULL;--> statement-breakpoint +ALTER TABLE "knight_hacks_job" ADD CONSTRAINT "knight_hacks_job_company_id_knight_hacks_company_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."knight_hacks_company"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_alert_preference" ADD CONSTRAINT "knight_hacks_job_alert_preference_member_id_knight_hacks_member_id_fk" FOREIGN KEY ("member_id") REFERENCES "public"."knight_hacks_member"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_application" ADD CONSTRAINT "knight_hacks_job_application_member_id_knight_hacks_member_id_fk" FOREIGN KEY ("member_id") REFERENCES "public"."knight_hacks_member"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_application" ADD CONSTRAINT "knight_hacks_job_application_job_id_knight_hacks_job_id_fk" FOREIGN KEY ("job_id") REFERENCES "public"."knight_hacks_job"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_location" ADD CONSTRAINT "knight_hacks_job_location_job_id_knight_hacks_job_id_fk" FOREIGN KEY ("job_id") REFERENCES "public"."knight_hacks_job"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_observation" ADD CONSTRAINT "knight_hacks_job_observation_source_id_knight_hacks_job_source_id_fk" FOREIGN KEY ("source_id") REFERENCES "public"."knight_hacks_job_source"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_observation" ADD CONSTRAINT "knight_hacks_job_observation_job_id_knight_hacks_job_id_fk" FOREIGN KEY ("job_id") REFERENCES "public"."knight_hacks_job"("id") ON DELETE restrict ON UPDATE no action;--> statement-breakpoint +ALTER TABLE "knight_hacks_job_source" ADD CONSTRAINT "knight_hacks_job_source_company_id_knight_hacks_company_id_fk" FOREIGN KEY ("company_id") REFERENCES "public"."knight_hacks_company"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint +CREATE INDEX "knight_hacks_job_company_idx" ON "knight_hacks_job" USING btree ("company_id");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_company_search_idx" ON "knight_hacks_job" USING btree ("company_key","track");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_search_idx" ON "knight_hacks_job" USING btree ("active","track","first_seen_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_posted_idx" ON "knight_hacks_job" USING btree ("active","posted_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_delivery_idx" ON "knight_hacks_job" USING btree ("delivery_state","delivery_next_attempt_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_digest_idx" ON "knight_hacks_job" USING btree ("discord_channel_id","delivered_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_alert_matching_idx" ON "knight_hacks_job_alert_preference" USING btree ("kind","target_key","track");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_application_community_idx" ON "knight_hacks_job_application" USING btree ("job_id","visibility","stage");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_digest_pending_idx" ON "knight_hacks_job_digest" USING btree ("delivery_state","next_attempt_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_location_job_idx" ON "knight_hacks_job_location" USING btree ("job_id");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_location_city_idx" ON "knight_hacks_job_location" USING btree ("city_key","job_id");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_location_state_idx" ON "knight_hacks_job_location" USING btree ("state","job_id");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_location_kind_idx" ON "knight_hacks_job_location" USING btree ("kind","job_id");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_observation_job_idx" ON "knight_hacks_job_observation" USING btree ("job_id");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_observation_seen_idx" ON "knight_hacks_job_observation" USING btree ("source_id","last_seen_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_source_schedule_idx" ON "knight_hacks_job_source" USING btree ("enabled","next_poll_at");--> statement-breakpoint +CREATE INDEX "knight_hacks_job_source_company_idx" ON "knight_hacks_job_source" USING btree ("company_id"); \ No newline at end of file diff --git a/packages/db/drizzle/meta/0064_snapshot.json b/packages/db/drizzle/meta/0064_snapshot.json new file mode 100644 index 000000000..bbb1c770f --- /dev/null +++ b/packages/db/drizzle/meta/0064_snapshot.json @@ -0,0 +1,16427 @@ +{ + "id": "dcc254d0-0ff5-4a03-995b-61592b756a56", + "prevId": "1d33ad72-c70b-41cb-86c5-1bc48565f581", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.audit_event": { + "name": "audit_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "occurred_at": { + "name": "occurred_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "action_key": { + "name": "action_key", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "outcome": { + "name": "outcome", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "operation_id": { + "name": "operation_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_user_id": { + "name": "actor_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_member_id": { + "name": "actor_member_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_discord_user_id": { + "name": "actor_discord_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "actor_label": { + "name": "actor_label", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "actor_role_label": { + "name": "actor_role_label", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "actor_role_color": { + "name": "actor_role_color", + "type": "varchar(7)", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "changes": { + "name": "changes", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + } + }, + "indexes": { + "audit_event_action_occurred_idx": { + "name": "audit_event_action_occurred_idx", + "columns": [ + { + "expression": "action_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_event_actor_occurred_idx": { + "name": "audit_event_actor_occurred_idx", + "columns": [ + { + "expression": "actor_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_event_actor_member_occurred_idx": { + "name": "audit_event_actor_member_occurred_idx", + "columns": [ + { + "expression": "actor_member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_event_domain_occurred_idx": { + "name": "audit_event_domain_occurred_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_event_occurred_idx": { + "name": "audit_event_occurred_idx", + "columns": [ + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_event_operation_idx": { + "name": "audit_event_operation_idx", + "columns": [ + { + "expression": "operation_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_event_outcome_occurred_idx": { + "name": "audit_event_outcome_occurred_idx", + "columns": [ + { + "expression": "outcome", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "occurred_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "audit_event_actor_role_color_check": { + "name": "audit_event_actor_role_color_check", + "value": "\"audit_event\".\"actor_role_color\" IS NULL OR \"audit_event\".\"actor_role_color\" ~ '^#[0-9A-Fa-f]{6}$'" + }, + "audit_event_outcome_check": { + "name": "audit_event_outcome_check", + "value": "\"audit_event\".\"outcome\" IN ('committed', 'partial_external')" + } + }, + "isRLSEnabled": false + }, + "public.audit_subject": { + "name": "audit_subject", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "relation": { + "name": "relation", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "target_type": { + "name": "target_type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "target_id": { + "name": "target_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "target_label": { + "name": "target_label", + "type": "varchar(512)", + "primaryKey": false, + "notNull": true + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "result_outcome": { + "name": "result_outcome", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "position": { + "name": "position", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + } + }, + "indexes": { + "audit_subject_event_position_idx": { + "name": "audit_subject_event_position_idx", + "columns": [ + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "position", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_subject_member_event_idx": { + "name": "audit_subject_member_event_idx", + "columns": [ + { + "expression": "member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_subject_one_primary_idx": { + "name": "audit_subject_one_primary_idx", + "columns": [ + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"audit_subject\".\"relation\" = 'primary'", + "concurrently": false, + "method": "btree", + "with": {} + }, + "audit_subject_target_event_idx": { + "name": "audit_subject_target_event_idx", + "columns": [ + { + "expression": "target_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "audit_subject_event_id_audit_event_id_fk": { + "name": "audit_subject_event_id_audit_event_id_fk", + "tableFrom": "audit_subject", + "tableTo": "audit_event", + "columnsFrom": ["event_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "audit_subject_relation_check": { + "name": "audit_subject_relation_check", + "value": "\"audit_subject\".\"relation\" IN ('primary', 'secondary', 'result')" + }, + "audit_subject_result_outcome_check": { + "name": "audit_subject_result_outcome_check", + "value": "\"audit_subject\".\"result_outcome\" IS NULL OR \"audit_subject\".\"result_outcome\" IN ('succeeded', 'skipped', 'failed_external', 'failed_internal', 'compensated')" + }, + "audit_subject_result_outcome_shape_check": { + "name": "audit_subject_result_outcome_shape_check", + "value": "(\"audit_subject\".\"relation\" = 'result') = (\"audit_subject\".\"result_outcome\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.auth_account": { + "name": "auth_account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider_account_id": { + "name": "provider_account_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "auth_account_user_id_auth_user_id_fk": { + "name": "auth_account_user_id_auth_user_id_fk", + "tableFrom": "auth_account", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "auth_account_provider_provider_account_id_pk": { + "name": "auth_account_provider_provider_account_id_pk", + "columns": ["provider", "provider_account_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.auth_permissions": { + "name": "auth_permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "auth_permissions_role_id_auth_roles_id_fk": { + "name": "auth_permissions_role_id_auth_roles_id_fk", + "tableFrom": "auth_permissions", + "tableTo": "auth_roles", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "auth_permissions_user_id_auth_user_id_fk": { + "name": "auth_permissions_user_id_auth_user_id_fk", + "tableFrom": "auth_permissions", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.auth_roles": { + "name": "auth_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "discord_role_id": { + "name": "discord_role_id", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "event_feedback_excluded": { + "name": "event_feedback_excluded", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_audience_enabled": { + "name": "email_audience_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "issue_reminder_channel": { + "name": "issue_reminder_channel", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "default": "'1459204271655489567'" + }, + "issue_reminders_enabled": { + "name": "issue_reminders_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "team_hexcode_color": { + "name": "team_hexcode_color", + "type": "varchar(7)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "auth_roles_discordRoleId_unique": { + "name": "auth_roles_discordRoleId_unique", + "nullsNotDistinct": false, + "columns": ["discord_role_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.auth_session": { + "name": "auth_session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "session_token": { + "name": "session_token", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "expires": { + "name": "expires", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "varchar(1024)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "auth_session_user_id_auth_user_id_fk": { + "name": "auth_session_user_id_auth_user_id_fk", + "tableFrom": "auth_session", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.auth_user": { + "name": "auth_user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "discord_user_id": { + "name": "discord_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.auth_verification": { + "name": "auth_verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_club_team": { + "name": "knight_hacks_club_team", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "slug": { + "name": "slug", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "heading": { + "name": "heading", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_club_team_display_order_unique": { + "name": "knight_hacks_club_team_display_order_unique", + "columns": [ + { + "expression": "display_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_club_team_kind_unique": { + "name": "knight_hacks_club_team_kind_unique", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_club_team\".\"kind\" <> 'team'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_club_team_slug_unique": { + "name": "knight_hacks_club_team_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_club_team_kind_check": { + "name": "knight_hacks_club_team_kind_check", + "value": "\"knight_hacks_club_team\".\"kind\" IN ('executive', 'director', 'team')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_club_team_role": { + "name": "knight_hacks_club_team_role", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "rank": { + "name": "rank", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "roster_label": { + "name": "roster_label", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "callout_label": { + "name": "callout_label", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_club_team_role_role_id_auth_roles_id_fk": { + "name": "knight_hacks_club_team_role_role_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_club_team_role", + "tableTo": "auth_roles", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_club_team_role_team_id_knight_hacks_club_team_id_fk": { + "name": "knight_hacks_club_team_role_team_id_knight_hacks_club_team_id_fk", + "tableFrom": "knight_hacks_club_team_role", + "tableTo": "knight_hacks_club_team", + "columnsFrom": ["team_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_club_team_role_roleId_unique": { + "name": "knight_hacks_club_team_role_roleId_unique", + "nullsNotDistinct": false, + "columns": ["role_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_club_team_role_kind_check": { + "name": "knight_hacks_club_team_role_kind_check", + "value": "\"knight_hacks_club_team_role\".\"kind\" IN ('executive', 'director', 'team')" + }, + "knight_hacks_club_team_role_team_check": { + "name": "knight_hacks_club_team_role_team_check", + "value": "\"knight_hacks_club_team_role\".\"kind\" <> 'team' OR \"knight_hacks_club_team_role\".\"team_id\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_discord_config": { + "name": "knight_hacks_discord_config", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "key": { + "name": "key", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "production_id": { + "name": "production_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "development_id": { + "name": "development_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_discord_config_key_unique": { + "name": "knight_hacks_discord_config_key_unique", + "nullsNotDistinct": false, + "columns": ["key"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_discord_config_kind_check": { + "name": "knight_hacks_discord_config_kind_check", + "value": "\"knight_hacks_discord_config\".\"kind\" IN ('channel', 'guild', 'role')" + }, + "knight_hacks_discord_config_production_id_check": { + "name": "knight_hacks_discord_config_production_id_check", + "value": "\"knight_hacks_discord_config\".\"production_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_discord_config_development_id_check": { + "name": "knight_hacks_discord_config_development_id_check", + "value": "\"knight_hacks_discord_config\".\"development_id\" IS NULL OR \"knight_hacks_discord_config\".\"development_id\" ~ '^[0-9]{17,20}$'" + } + }, + "isRLSEnabled": false + }, + "public.discord_archive_channel": { + "name": "discord_archive_channel", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(20)", + "primaryKey": true, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "topic": { + "name": "topic", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_thread": { + "name": "is_thread", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_private_thread": { + "name": "is_private_thread", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "archived": { + "name": "archived", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "locked": { + "name": "locked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "discovered_at": { + "name": "discovered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "discord_updated_at": { + "name": "discord_updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "discord_archive_channel_guild_type_idx": { + "name": "discord_archive_channel_guild_type_idx", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "type", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "discord_archive_channel_parent_idx": { + "name": "discord_archive_channel_parent_idx", + "columns": [ + { + "expression": "parent_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.discord_archive_checkpoint": { + "name": "discord_archive_checkpoint", + "schema": "", + "columns": { + "channel_id": { + "name": "channel_id", + "type": "varchar(20)", + "primaryKey": true, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "oldest_message_id": { + "name": "oldest_message_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "newest_message_id": { + "name": "newest_message_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "backfill_before_message_id": { + "name": "backfill_before_message_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "backfill_status": { + "name": "backfill_status", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "backfill_completed_at": { + "name": "backfill_completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_backfill_at": { + "name": "last_backfill_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_discovered_at": { + "name": "last_discovered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_reconciled_at": { + "name": "last_reconciled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "processed_message_count": { + "name": "processed_message_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error_code": { + "name": "last_error_code", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "last_error_message": { + "name": "last_error_message", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "discord_archive_checkpoint_guild_status_updated_idx": { + "name": "discord_archive_checkpoint_guild_status_updated_idx", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "backfill_status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "discord_archive_checkpoint_channel_id_discord_archive_channel_id_fk": { + "name": "discord_archive_checkpoint_channel_id_discord_archive_channel_id_fk", + "tableFrom": "discord_archive_checkpoint", + "tableTo": "discord_archive_channel", + "columnsFrom": ["channel_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "discord_archive_checkpoint_status_check": { + "name": "discord_archive_checkpoint_status_check", + "value": "\"discord_archive_checkpoint\".\"backfill_status\" IN ('pending', 'running', 'complete', 'failed')" + } + }, + "isRLSEnabled": false + }, + "public.discord_archive_message": { + "name": "discord_archive_message", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(20)", + "primaryKey": true, + "notNull": true + }, + "guild_id": { + "name": "guild_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "channel_id": { + "name": "channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "author_discord_user_id": { + "name": "author_discord_user_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "author_label": { + "name": "author_label", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "author_avatar_url": { + "name": "author_avatar_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "author_is_bot": { + "name": "author_is_bot", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "webhook_id": { + "name": "webhook_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "application_id": { + "name": "application_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "message_type": { + "name": "message_type", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "edited_at": { + "name": "edited_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "reply_to_message_id": { + "name": "reply_to_message_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "pinned": { + "name": "pinned", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "flags": { + "name": "flags", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true, + "default": "'0'" + }, + "mentions": { + "name": "mentions", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{\"everyone\":false,\"roleIds\":[],\"userIds\":[]}'::jsonb" + }, + "embeds": { + "name": "embeds", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "attachments": { + "name": "attachments", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "components": { + "name": "components", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "stickers": { + "name": "stickers", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "poll": { + "name": "poll", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "ingested_at": { + "name": "ingested_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_observed_at": { + "name": "last_observed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "discord_archive_message_author_created_idx": { + "name": "discord_archive_message_author_created_idx", + "columns": [ + { + "expression": "author_discord_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "discord_archive_message_channel_created_idx": { + "name": "discord_archive_message_channel_created_idx", + "columns": [ + { + "expression": "channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "discord_archive_message_guild_created_idx": { + "name": "discord_archive_message_guild_created_idx", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "discord_archive_message_non_deleted_created_idx": { + "name": "discord_archive_message_non_deleted_created_idx", + "columns": [ + { + "expression": "guild_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"discord_archive_message\".\"deleted_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "discord_archive_message_channel_id_discord_archive_channel_id_fk": { + "name": "discord_archive_message_channel_id_discord_archive_channel_id_fk", + "tableFrom": "discord_archive_message", + "tableTo": "discord_archive_channel", + "columnsFrom": ["channel_id"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.discord_archive_state": { + "name": "discord_archive_state", + "schema": "", + "columns": { + "guild_id": { + "name": "guild_id", + "type": "varchar(20)", + "primaryKey": true, + "notNull": true + }, + "status": { + "name": "status", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "last_gateway_event_at": { + "name": "last_gateway_event_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_live_write_at": { + "name": "last_live_write_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_discovery_started_at": { + "name": "last_discovery_started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_discovery_completed_at": { + "name": "last_discovery_completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_reconciliation_started_at": { + "name": "last_reconciliation_started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_reconciliation_completed_at": { + "name": "last_reconciliation_completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_backfill_progress_at": { + "name": "last_backfill_progress_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "lease_owner": { + "name": "lease_owner", + "type": "varchar(128)", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_error_code": { + "name": "last_error_code", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "last_error_message": { + "name": "last_error_message", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "failure_count": { + "name": "failure_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "discord_archive_state_status_check": { + "name": "discord_archive_state_status_check", + "value": "\"discord_archive_state\".\"status\" IN ('disabled', 'idle', 'healthy', 'degraded', 'failed')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job": { + "name": "knight_hacks_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "identity_key": { + "name": "identity_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identity_hash": { + "name": "identity_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "generated": { + "as": "encode(sha256(decode(replace(\"identity_key\", chr(92), chr(92) || chr(92)), 'escape')), 'hex')", + "type": "stored" + } + }, + "company_id": { + "name": "company_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "company_label": { + "name": "company_label", + "type": "varchar(200)", + "primaryKey": false, + "notNull": true + }, + "company_key": { + "name": "company_key", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "track": { + "name": "track", + "type": "job_track", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "job_category", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "apply_url": { + "name": "apply_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "compensation": { + "name": "compensation", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "work_arrangement": { + "name": "work_arrangement", + "type": "job_work_arrangement", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "posted_at": { + "name": "posted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "inactive_at": { + "name": "inactive_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivery_state": { + "name": "delivery_state", + "type": "job_delivery_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'suppressed'" + }, + "delivery_track": { + "name": "delivery_track", + "type": "job_track", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "discord_channel_id": { + "name": "discord_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "discord_message_id": { + "name": "discord_message_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivery_claim_token": { + "name": "delivery_claim_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "delivery_lease_expires_at": { + "name": "delivery_lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivery_next_attempt_at": { + "name": "delivery_next_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivery_attempts": { + "name": "delivery_attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "delivery_error": { + "name": "delivery_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_job_company_idx": { + "name": "knight_hacks_job_company_idx", + "columns": [ + { + "expression": "company_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_company_search_idx": { + "name": "knight_hacks_job_company_search_idx", + "columns": [ + { + "expression": "company_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "track", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_search_idx": { + "name": "knight_hacks_job_search_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "track", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "first_seen_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_posted_idx": { + "name": "knight_hacks_job_posted_idx", + "columns": [ + { + "expression": "active", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "posted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_delivery_idx": { + "name": "knight_hacks_job_delivery_idx", + "columns": [ + { + "expression": "delivery_state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "delivery_next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_digest_idx": { + "name": "knight_hacks_job_digest_idx", + "columns": [ + { + "expression": "discord_channel_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "delivered_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_job_company_id_knight_hacks_company_id_fk": { + "name": "knight_hacks_job_company_id_knight_hacks_company_id_fk", + "tableFrom": "knight_hacks_job", + "tableTo": "knight_hacks_company", + "columnsFrom": ["company_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_job_identity_unique": { + "name": "knight_hacks_job_identity_unique", + "nullsNotDistinct": false, + "columns": ["identity_hash"] + }, + "knight_hacks_job_discord_message_unique": { + "name": "knight_hacks_job_discord_message_unique", + "nullsNotDistinct": false, + "columns": ["discord_message_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_values_check": { + "name": "knight_hacks_job_values_check", + "value": "\"knight_hacks_job\".\"identity_key\" ~ '[^[:space:]]' AND \"knight_hacks_job\".\"company_label\" ~ '[^[:space:]]' AND \"knight_hacks_job\".\"company_key\" ~ '[^[:space:]]' AND \"knight_hacks_job\".\"title\" ~ '[^[:space:]]' AND \"knight_hacks_job\".\"apply_url\" ~ '^https?://' AND \"knight_hacks_job\".\"delivery_attempts\" >= 0" + }, + "knight_hacks_job_dates_check": { + "name": "knight_hacks_job_dates_check", + "value": "\"knight_hacks_job\".\"last_seen_at\" >= \"knight_hacks_job\".\"first_seen_at\" AND (\"knight_hacks_job\".\"active\" = (\"knight_hacks_job\".\"inactive_at\" IS NULL))" + }, + "knight_hacks_job_channel_check": { + "name": "knight_hacks_job_channel_check", + "value": "\"knight_hacks_job\".\"discord_channel_id\" IS NULL OR \"knight_hacks_job\".\"discord_channel_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_job_message_check": { + "name": "knight_hacks_job_message_check", + "value": "\"knight_hacks_job\".\"discord_message_id\" IS NULL OR \"knight_hacks_job\".\"discord_message_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_job_lease_check": { + "name": "knight_hacks_job_lease_check", + "value": "(\"knight_hacks_job\".\"delivery_claim_token\" IS NULL) = (\"knight_hacks_job\".\"delivery_lease_expires_at\" IS NULL)" + }, + "knight_hacks_job_destination_check": { + "name": "knight_hacks_job_destination_check", + "value": "\"knight_hacks_job\".\"delivery_state\" = 'suppressed' OR (\"knight_hacks_job\".\"discord_channel_id\" IS NOT NULL AND \"knight_hacks_job\".\"delivery_track\" IS NOT NULL)" + }, + "knight_hacks_job_receipt_check": { + "name": "knight_hacks_job_receipt_check", + "value": "(\"knight_hacks_job\".\"delivery_state\" = 'sent') = (\"knight_hacks_job\".\"discord_message_id\" IS NOT NULL AND \"knight_hacks_job\".\"delivered_at\" IS NOT NULL) AND (\"knight_hacks_job\".\"discord_message_id\" IS NULL) = (\"knight_hacks_job\".\"delivered_at\" IS NULL)" + }, + "knight_hacks_job_sending_check": { + "name": "knight_hacks_job_sending_check", + "value": "\"knight_hacks_job\".\"delivery_state\" <> 'sending' OR \"knight_hacks_job\".\"delivery_claim_token\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job_alert_preference": { + "name": "knight_hacks_job_alert_preference", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "track": { + "name": "track", + "type": "job_track", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "job_alert_target_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "target_key": { + "name": "target_key", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "custom_value": { + "name": "custom_value", + "type": "varchar(120)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_job_alert_matching_idx": { + "name": "knight_hacks_job_alert_matching_idx", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "track", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_job_alert_preference_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_job_alert_preference_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_job_alert_preference", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_job_alert_member_target_unique": { + "name": "knight_hacks_job_alert_member_target_unique", + "nullsNotDistinct": false, + "columns": ["member_id", "track", "kind", "target_key"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_alert_values_check": { + "name": "knight_hacks_job_alert_values_check", + "value": "\"knight_hacks_job_alert_preference\".\"target_key\" ~ '[^[:space:]]' AND (\"knight_hacks_job_alert_preference\".\"custom_value\" IS NULL OR \"knight_hacks_job_alert_preference\".\"custom_value\" ~ '[^[:space:]]')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job_application": { + "name": "knight_hacks_job_application", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "stage": { + "name": "stage", + "type": "job_application_stage", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'saved'" + }, + "round": { + "name": "round", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "visibility": { + "name": "visibility", + "type": "job_application_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'community'" + }, + "private_notes": { + "name": "private_notes", + "type": "varchar(2000)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_job_application_community_idx": { + "name": "knight_hacks_job_application_community_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "visibility", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stage", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_job_application_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_job_application_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_job_application", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_job_application_job_id_knight_hacks_job_id_fk": { + "name": "knight_hacks_job_application_job_id_knight_hacks_job_id_fk", + "tableFrom": "knight_hacks_job_application", + "tableTo": "knight_hacks_job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_job_application_member_job_unique": { + "name": "knight_hacks_job_application_member_job_unique", + "nullsNotDistinct": false, + "columns": ["member_id", "job_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_application_round_check": { + "name": "knight_hacks_job_application_round_check", + "value": "\"knight_hacks_job_application\".\"round\" IS NULL OR (\"knight_hacks_job_application\".\"stage\" = 'interviewing' AND \"knight_hacks_job_application\".\"round\" BETWEEN 1 AND 10)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job_digest": { + "name": "knight_hacks_job_digest", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "track": { + "name": "track", + "type": "job_track", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "scheduled_at": { + "name": "scheduled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "window_start": { + "name": "window_start", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "window_end": { + "name": "window_end", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "discord_channel_id": { + "name": "discord_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "discord_message_id": { + "name": "discord_message_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "delivery_state": { + "name": "delivery_state", + "type": "job_delivery_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "claim_token": { + "name": "claim_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_job_digest_pending_idx": { + "name": "knight_hacks_job_digest_pending_idx", + "columns": [ + { + "expression": "delivery_state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_job_digest_schedule_unique": { + "name": "knight_hacks_job_digest_schedule_unique", + "nullsNotDistinct": false, + "columns": ["track", "scheduled_at"] + }, + "knight_hacks_job_digest_message_unique": { + "name": "knight_hacks_job_digest_message_unique", + "nullsNotDistinct": false, + "columns": ["discord_message_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_digest_values_check": { + "name": "knight_hacks_job_digest_values_check", + "value": "\"knight_hacks_job_digest\".\"window_start\" < \"knight_hacks_job_digest\".\"window_end\" AND \"knight_hacks_job_digest\".\"window_end\" <= \"knight_hacks_job_digest\".\"scheduled_at\" AND \"knight_hacks_job_digest\".\"attempts\" >= 0 AND \"knight_hacks_job_digest\".\"discord_channel_id\" ~ '^[0-9]{17,20}$' AND (\"knight_hacks_job_digest\".\"discord_message_id\" IS NULL OR \"knight_hacks_job_digest\".\"discord_message_id\" ~ '^[0-9]{17,20}$')" + }, + "knight_hacks_job_digest_lease_check": { + "name": "knight_hacks_job_digest_lease_check", + "value": "(\"knight_hacks_job_digest\".\"claim_token\" IS NULL) = (\"knight_hacks_job_digest\".\"lease_expires_at\" IS NULL)" + }, + "knight_hacks_job_digest_receipt_check": { + "name": "knight_hacks_job_digest_receipt_check", + "value": "(\"knight_hacks_job_digest\".\"delivery_state\" = 'sent') = (\"knight_hacks_job_digest\".\"discord_message_id\" IS NOT NULL AND \"knight_hacks_job_digest\".\"delivered_at\" IS NOT NULL) AND (\"knight_hacks_job_digest\".\"discord_message_id\" IS NULL) = (\"knight_hacks_job_digest\".\"delivered_at\" IS NULL)" + }, + "knight_hacks_job_digest_sending_check": { + "name": "knight_hacks_job_digest_sending_check", + "value": "\"knight_hacks_job_digest\".\"delivery_state\" <> 'sending' OR \"knight_hacks_job_digest\".\"claim_token\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job_location": { + "name": "knight_hacks_job_location", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "source_text": { + "name": "source_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "job_location_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "city_key": { + "name": "city_key", + "type": "varchar(8)", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "varchar(2)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_job_location_job_idx": { + "name": "knight_hacks_job_location_job_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_location_city_idx": { + "name": "knight_hacks_job_location_city_idx", + "columns": [ + { + "expression": "city_key", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_location_state_idx": { + "name": "knight_hacks_job_location_state_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_location_kind_idx": { + "name": "knight_hacks_job_location_kind_idx", + "columns": [ + { + "expression": "kind", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_job_location_job_id_knight_hacks_job_id_fk": { + "name": "knight_hacks_job_location_job_id_knight_hacks_job_id_fk", + "tableFrom": "knight_hacks_job_location", + "tableTo": "knight_hacks_job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_location_values_check": { + "name": "knight_hacks_job_location_values_check", + "value": "\"knight_hacks_job_location\".\"source_text\" ~ '[^[:space:]]' AND (\"knight_hacks_job_location\".\"state\" IS NULL OR \"knight_hacks_job_location\".\"state\" ~ '^[A-Z]{2}$') AND (\"knight_hacks_job_location\".\"city_key\" IS NULL OR \"knight_hacks_job_location\".\"city_key\" ~ '^[0-9]{2}-[0-9]{5}$')" + }, + "knight_hacks_job_location_shape_check": { + "name": "knight_hacks_job_location_shape_check", + "value": "(\"knight_hacks_job_location\".\"kind\" = 'city' AND \"knight_hacks_job_location\".\"city_key\" IS NOT NULL AND \"knight_hacks_job_location\".\"state\" IS NOT NULL) OR (\"knight_hacks_job_location\".\"kind\" = 'state' AND \"knight_hacks_job_location\".\"state\" IS NOT NULL AND \"knight_hacks_job_location\".\"city_key\" IS NULL) OR (\"knight_hacks_job_location\".\"kind\" IN ('remote_us', 'unknown') AND \"knight_hacks_job_location\".\"city_key\" IS NULL AND \"knight_hacks_job_location\".\"state\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job_observation": { + "name": "knight_hacks_job_observation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "source_id": { + "name": "source_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "job_id": { + "name": "job_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "external_id": { + "name": "external_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "external_id_hash": { + "name": "external_id_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "generated": { + "as": "encode(sha256(decode(replace(\"external_id\", chr(92), chr(92) || chr(92)), 'escape')), 'hex')", + "type": "stored" + } + }, + "source_url": { + "name": "source_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source_data": { + "name": "source_data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "posted_at": { + "name": "posted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "inactive_at": { + "name": "inactive_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_job_observation_job_idx": { + "name": "knight_hacks_job_observation_job_idx", + "columns": [ + { + "expression": "job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_observation_seen_idx": { + "name": "knight_hacks_job_observation_seen_idx", + "columns": [ + { + "expression": "source_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "last_seen_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_job_observation_source_id_knight_hacks_job_source_id_fk": { + "name": "knight_hacks_job_observation_source_id_knight_hacks_job_source_id_fk", + "tableFrom": "knight_hacks_job_observation", + "tableTo": "knight_hacks_job_source", + "columnsFrom": ["source_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_job_observation_job_id_knight_hacks_job_id_fk": { + "name": "knight_hacks_job_observation_job_id_knight_hacks_job_id_fk", + "tableFrom": "knight_hacks_job_observation", + "tableTo": "knight_hacks_job", + "columnsFrom": ["job_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_job_observation_source_external_unique": { + "name": "knight_hacks_job_observation_source_external_unique", + "nullsNotDistinct": false, + "columns": ["source_id", "external_id_hash"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_observation_values_check": { + "name": "knight_hacks_job_observation_values_check", + "value": "\"knight_hacks_job_observation\".\"external_id\" ~ '[^[:space:]]' AND \"knight_hacks_job_observation\".\"last_seen_at\" >= \"knight_hacks_job_observation\".\"first_seen_at\"" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_job_source": { + "name": "knight_hacks_job_source", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "provider": { + "name": "provider", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "board_key": { + "name": "board_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "board_key_hash": { + "name": "board_key_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "generated": { + "as": "encode(sha256(decode(replace(\"board_key\", chr(92), chr(92) || chr(92)), 'escape')), 'hex')", + "type": "stored" + } + }, + "label": { + "name": "label", + "type": "varchar(200)", + "primaryKey": false, + "notNull": true + }, + "company_id": { + "name": "company_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "poll_interval_seconds": { + "name": "poll_interval_seconds", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 900 + }, + "next_poll_at": { + "name": "next_poll_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_success_at": { + "name": "last_success_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "baseline_completed_at": { + "name": "baseline_completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "etag": { + "name": "etag", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_modified": { + "name": "last_modified", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "claim_token": { + "name": "claim_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_job_source_schedule_idx": { + "name": "knight_hacks_job_source_schedule_idx", + "columns": [ + { + "expression": "enabled", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_poll_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_job_source_company_idx": { + "name": "knight_hacks_job_source_company_idx", + "columns": [ + { + "expression": "company_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_job_source_company_id_knight_hacks_company_id_fk": { + "name": "knight_hacks_job_source_company_id_knight_hacks_company_id_fk", + "tableFrom": "knight_hacks_job_source", + "tableTo": "knight_hacks_company", + "columnsFrom": ["company_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_job_source_provider_board_unique": { + "name": "knight_hacks_job_source_provider_board_unique", + "nullsNotDistinct": false, + "columns": ["provider", "board_key_hash"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_job_source_values_check": { + "name": "knight_hacks_job_source_values_check", + "value": "\"knight_hacks_job_source\".\"provider\" ~ '^[a-z][a-z0-9_]*$' AND \"knight_hacks_job_source\".\"board_key\" ~ '[^[:space:]]' AND \"knight_hacks_job_source\".\"label\" ~ '[^[:space:]]' AND \"knight_hacks_job_source\".\"poll_interval_seconds\" > 0" + }, + "knight_hacks_job_source_lease_check": { + "name": "knight_hacks_job_source_lease_check", + "value": "(\"knight_hacks_job_source\".\"claim_token\" IS NULL) = (\"knight_hacks_job_source\".\"lease_expires_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_alumni_bulletin_post": { + "name": "knight_hacks_alumni_bulletin_post", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "title": { + "name": "title", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "body": { + "name": "body", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "image_object_name": { + "name": "image_object_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "image_alt": { + "name": "image_alt", + "type": "varchar(240)", + "primaryKey": false, + "notNull": false + }, + "cta_label": { + "name": "cta_label", + "type": "varchar(80)", + "primaryKey": false, + "notNull": false + }, + "external_url": { + "name": "external_url", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": false + }, + "form_id": { + "name": "form_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "alumni_bulletin_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "publish_at": { + "name": "publish_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "updated_by_user_id": { + "name": "updated_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_alumni_bulletin_state_order_idx": { + "name": "knight_hacks_alumni_bulletin_state_order_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_alumni_bulletin_publication_window_idx": { + "name": "knight_hacks_alumni_bulletin_publication_window_idx", + "columns": [ + { + "expression": "publish_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_alumni_bulletin_post_form_id_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_alumni_bulletin_post_form_id_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_alumni_bulletin_post", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_alumni_bulletin_post_created_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_alumni_bulletin_post_created_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_alumni_bulletin_post", + "tableTo": "auth_user", + "columnsFrom": ["created_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_alumni_bulletin_post_updated_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_alumni_bulletin_post_updated_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_alumni_bulletin_post", + "tableTo": "auth_user", + "columnsFrom": ["updated_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "alumni_bulletin_action_exclusive": { + "name": "alumni_bulletin_action_exclusive", + "value": "NOT (\"knight_hacks_alumni_bulletin_post\".\"external_url\" IS NOT NULL AND \"knight_hacks_alumni_bulletin_post\".\"form_id\" IS NOT NULL)" + }, + "alumni_bulletin_action_pair": { + "name": "alumni_bulletin_action_pair", + "value": "((\"knight_hacks_alumni_bulletin_post\".\"external_url\" IS NULL AND \"knight_hacks_alumni_bulletin_post\".\"form_id\" IS NULL) OR \"knight_hacks_alumni_bulletin_post\".\"cta_label\" IS NOT NULL)" + }, + "alumni_bulletin_display_order_nonnegative": { + "name": "alumni_bulletin_display_order_nonnegative", + "value": "\"knight_hacks_alumni_bulletin_post\".\"display_order\" >= 0" + }, + "alumni_bulletin_image_alt_pair": { + "name": "alumni_bulletin_image_alt_pair", + "value": "((\"knight_hacks_alumni_bulletin_post\".\"image_object_name\" IS NULL AND \"knight_hacks_alumni_bulletin_post\".\"image_alt\" IS NULL) OR (\"knight_hacks_alumni_bulletin_post\".\"image_object_name\" IS NOT NULL AND \"knight_hacks_alumni_bulletin_post\".\"image_alt\" IS NOT NULL))" + }, + "alumni_bulletin_schedule_order": { + "name": "alumni_bulletin_schedule_order", + "value": "\"knight_hacks_alumni_bulletin_post\".\"expires_at\" IS NULL OR \"knight_hacks_alumni_bulletin_post\".\"publish_at\" IS NULL OR \"knight_hacks_alumni_bulletin_post\".\"expires_at\" > \"knight_hacks_alumni_bulletin_post\".\"publish_at\"" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_company": { + "name": "knight_hacks_company", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "display_name": { + "name": "display_name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "normalized_display_name": { + "name": "normalized_display_name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "legal_name": { + "name": "legal_name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": false + }, + "domain": { + "name": "domain", + "type": "varchar(253)", + "primaryKey": false, + "notNull": false + }, + "logo_object_name": { + "name": "logo_object_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "aliases": { + "name": "aliases", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "review_state": { + "name": "review_state", + "type": "company_review_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "merged_into_company_id": { + "name": "merged_into_company_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_company_review_state_idx": { + "name": "knight_hacks_company_review_state_idx", + "columns": [ + { + "expression": "review_state", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_company_domain_idx": { + "name": "knight_hacks_company_domain_idx", + "columns": [ + { + "expression": "domain", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_company_created_by_user_idx": { + "name": "knight_hacks_company_created_by_user_idx", + "columns": [ + { + "expression": "created_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_company_created_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_company_created_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_company", + "tableTo": "auth_user", + "columnsFrom": ["created_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_company_merged_into_fk": { + "name": "knight_hacks_company_merged_into_fk", + "tableFrom": "knight_hacks_company", + "tableTo": "knight_hacks_company", + "columnsFrom": ["merged_into_company_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_company_normalized_display_name_unique": { + "name": "knight_hacks_company_normalized_display_name_unique", + "nullsNotDistinct": false, + "columns": ["normalized_display_name"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_company_merged_state_consistency": { + "name": "knight_hacks_company_merged_state_consistency", + "value": "(\"knight_hacks_company\".\"review_state\" = 'merged') = (\"knight_hacks_company\".\"merged_into_company_id\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_dues_configuration": { + "name": "knight_hacks_dues_configuration", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(32)", + "primaryKey": true, + "notNull": true + }, + "payments_enabled": { + "name": "payments_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_dues_configuration_singleton_check": { + "name": "knight_hacks_dues_configuration_singleton_check", + "value": "\"knight_hacks_dues_configuration\".\"id\" = 'global'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_dues_payment": { + "name": "knight_hacks_dues_payment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "amount": { + "name": "amount", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "payment_date": { + "name": "payment_date", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "year": { + "name": "year", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "stripe_payment_intent_id": { + "name": "stripe_payment_intent_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_dues_payment_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_dues_payment_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_dues_payment", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_dues_payment_memberId_year_unique": { + "name": "knight_hacks_dues_payment_memberId_year_unique", + "nullsNotDistinct": false, + "columns": ["member_id", "year"] + }, + "knight_hacks_dues_payment_stripe_payment_intent_id_unique": { + "name": "knight_hacks_dues_payment_stripe_payment_intent_id_unique", + "nullsNotDistinct": false, + "columns": ["stripe_payment_intent_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.email_send": { + "name": "email_send", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "subject": { + "name": "subject", + "type": "varchar(200)", + "primaryKey": false, + "notNull": true + }, + "template_revision_id": { + "name": "template_revision_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "plain_text_source": { + "name": "plain_text_source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "compiled_html": { + "name": "compiled_html", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "compiled_text": { + "name": "compiled_text", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content_hash": { + "name": "content_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "audience_definition": { + "name": "audience_definition", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "audience_version": { + "name": "audience_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "audience_hash": { + "name": "audience_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "preview_version": { + "name": "preview_version", + "type": "varchar(80)", + "primaryKey": false, + "notNull": true + }, + "preview_expires_at": { + "name": "preview_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "raw_match_count": { + "name": "raw_match_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "duplicate_count": { + "name": "duplicate_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "excluded_invalid_count": { + "name": "excluded_invalid_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "excluded_suppressed_count": { + "name": "excluded_suppressed_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "excluded_missing_field_count": { + "name": "excluded_missing_field_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "excluded_manual_count": { + "name": "excluded_manual_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "final_recipient_count": { + "name": "final_recipient_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "scheduled_for": { + "name": "scheduled_for", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "listmonk_list_id": { + "name": "listmonk_list_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "listmonk_campaign_id": { + "name": "listmonk_campaign_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "provider_tag": { + "name": "provider_tag", + "type": "varchar(80)", + "primaryKey": false, + "notNull": true + }, + "provider_may_have_started": { + "name": "provider_may_have_started", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "provider_sent_count": { + "name": "provider_sent_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "provider_bounce_count": { + "name": "provider_bounce_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "retry_attempt_count": { + "name": "retry_attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "retry_lease_expires_at": { + "name": "retry_lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "next_retry_at": { + "name": "next_retry_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "safe_error": { + "name": "safe_error", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "confirmed_at": { + "name": "confirmed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancelled_at": { + "name": "cancelled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cancelled_by": { + "name": "cancelled_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "terminal_at": { + "name": "terminal_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_send_status_scheduled_for_idx": { + "name": "email_send_status_scheduled_for_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scheduled_for", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "email_send_retry_idx": { + "name": "email_send_retry_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_retry_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "retry_lease_expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_send_template_revision_id_email_template_revision_id_fk": { + "name": "email_send_template_revision_id_email_template_revision_id_fk", + "tableFrom": "email_send", + "tableTo": "email_template_revision", + "columnsFrom": ["template_revision_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "email_send_created_by_auth_user_id_fk": { + "name": "email_send_created_by_auth_user_id_fk", + "tableFrom": "email_send", + "tableTo": "auth_user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "email_send_cancelled_by_auth_user_id_fk": { + "name": "email_send_cancelled_by_auth_user_id_fk", + "tableFrom": "email_send", + "tableTo": "auth_user", + "columnsFrom": ["cancelled_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_send_provider_tag_unique": { + "name": "email_send_provider_tag_unique", + "nullsNotDistinct": false, + "columns": ["provider_tag"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.email_send_event": { + "name": "email_send_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "send_id": { + "name": "send_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "from_status": { + "name": "from_status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "to_status": { + "name": "to_status", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_send_event_send_created_idx": { + "name": "email_send_event_send_created_idx", + "columns": [ + { + "expression": "send_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_send_event_send_id_email_send_id_fk": { + "name": "email_send_event_send_id_email_send_id_fk", + "tableFrom": "email_send_event", + "tableTo": "email_send", + "columnsFrom": ["send_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "email_send_event_actor_id_auth_user_id_fk": { + "name": "email_send_event_actor_id_auth_user_id_fk", + "tableFrom": "email_send_event", + "tableTo": "auth_user", + "columnsFrom": ["actor_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.email_send_recipient": { + "name": "email_send_recipient", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "send_id": { + "name": "send_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(320)", + "primaryKey": false, + "notNull": true + }, + "normalized_email": { + "name": "normalized_email", + "type": "varchar(320)", + "primaryKey": false, + "notNull": true + }, + "attributes": { + "name": "attributes", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "match_reasons": { + "name": "match_reasons", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "exclusion_reason": { + "name": "exclusion_reason", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "listmonk_subscriber_id": { + "name": "listmonk_subscriber_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_send_recipient_send_id_idx": { + "name": "email_send_recipient_send_id_idx", + "columns": [ + { + "expression": "send_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "exclusion_reason", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_send_recipient_send_id_email_send_id_fk": { + "name": "email_send_recipient_send_id_email_send_id_fk", + "tableFrom": "email_send_recipient", + "tableTo": "email_send", + "columnsFrom": ["send_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_send_recipient_send_id_normalized_email_unique": { + "name": "email_send_recipient_send_id_normalized_email_unique", + "nullsNotDistinct": false, + "columns": ["send_id", "normalized_email"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.email_template": { + "name": "email_template", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "normalized_name": { + "name": "normalized_name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "domain": { + "name": "domain", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'club'" + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "updated_by": { + "name": "updated_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_template_archived_updated_idx": { + "name": "email_template_archived_updated_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_template_created_by_auth_user_id_fk": { + "name": "email_template_created_by_auth_user_id_fk", + "tableFrom": "email_template", + "tableTo": "auth_user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "email_template_updated_by_auth_user_id_fk": { + "name": "email_template_updated_by_auth_user_id_fk", + "tableFrom": "email_template", + "tableTo": "auth_user", + "columnsFrom": ["updated_by"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_template_normalized_name_unique": { + "name": "email_template_normalized_name_unique", + "nullsNotDistinct": false, + "columns": ["normalized_name"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.email_template_revision": { + "name": "email_template_revision", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "template_id": { + "name": "template_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "visual_document": { + "name": "visual_document", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "compiled_html": { + "name": "compiled_html", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "compiled_text": { + "name": "compiled_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "personalization_contract": { + "name": "personalization_contract", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "checksum": { + "name": "checksum", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "published_at": { + "name": "published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "email_template_revision_template_state_idx": { + "name": "email_template_revision_template_state_idx", + "columns": [ + { + "expression": "template_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "version", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "email_template_revision_template_id_email_template_id_fk": { + "name": "email_template_revision_template_id_email_template_id_fk", + "tableFrom": "email_template_revision", + "tableTo": "email_template", + "columnsFrom": ["template_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "email_template_revision_created_by_auth_user_id_fk": { + "name": "email_template_revision_created_by_auth_user_id_fk", + "tableFrom": "email_template_revision", + "tableTo": "auth_user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "email_template_revision_template_version_unique": { + "name": "email_template_revision_template_version_unique", + "nullsNotDistinct": false, + "columns": ["template_id", "version"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_employment": { + "name": "knight_hacks_employment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "company_id": { + "name": "company_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(120)", + "primaryKey": false, + "notNull": false + }, + "experience_type": { + "name": "experience_type", + "type": "employment_experience_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "employment_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "start_month": { + "name": "start_month", + "type": "varchar(7)", + "primaryKey": false, + "notNull": false + }, + "end_month": { + "name": "end_month", + "type": "varchar(7)", + "primaryKey": false, + "notNull": false + }, + "city_key": { + "name": "city_key", + "type": "varchar(8)", + "primaryKey": false, + "notNull": false + }, + "guild_visible": { + "name": "guild_visible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_employment_member_idx": { + "name": "knight_hacks_employment_member_idx", + "columns": [ + { + "expression": "member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_employment_company_idx": { + "name": "knight_hacks_employment_company_idx", + "columns": [ + { + "expression": "company_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_employment_company_state_idx": { + "name": "knight_hacks_employment_company_state_idx", + "columns": [ + { + "expression": "company_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_employment_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_employment_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_employment", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_employment_company_id_knight_hacks_company_id_fk": { + "name": "knight_hacks_employment_company_id_knight_hacks_company_id_fk", + "tableFrom": "knight_hacks_employment", + "tableTo": "knight_hacks_company", + "columnsFrom": ["company_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_employment_current_has_no_end": { + "name": "knight_hacks_employment_current_has_no_end", + "value": "\"knight_hacks_employment\".\"state\" <> 'current' OR \"knight_hacks_employment\".\"end_month\" IS NULL" + }, + "knight_hacks_employment_start_month_shape": { + "name": "knight_hacks_employment_start_month_shape", + "value": "\"knight_hacks_employment\".\"start_month\" IS NULL OR \"knight_hacks_employment\".\"start_month\" ~ '^[0-9]{4}-(0[1-9]|1[0-2])$'" + }, + "knight_hacks_employment_end_month_shape": { + "name": "knight_hacks_employment_end_month_shape", + "value": "\"knight_hacks_employment\".\"end_month\" IS NULL OR \"knight_hacks_employment\".\"end_month\" ~ '^[0-9]{4}-(0[1-9]|1[0-2])$'" + }, + "knight_hacks_employment_date_order": { + "name": "knight_hacks_employment_date_order", + "value": "\"knight_hacks_employment\".\"start_month\" IS NULL OR \"knight_hacks_employment\".\"end_month\" IS NULL OR \"knight_hacks_employment\".\"end_month\" >= \"knight_hacks_employment\".\"start_month\"" + }, + "knight_hacks_employment_city_key_shape": { + "name": "knight_hacks_employment_city_key_shape", + "value": "\"knight_hacks_employment\".\"city_key\" IS NULL OR \"knight_hacks_employment\".\"city_key\" ~ '^[0-9]{2}-[0-9]{5}$'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_event": { + "name": "knight_hacks_event", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "discord_id": { + "name": "discord_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "google_id": { + "name": "google_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "tag": { + "name": "tag", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tag_id": { + "name": "tag_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "tag_color": { + "name": "tag_color", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true, + "default": "'#0D9488'" + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "start_datetime": { + "name": "start_datetime", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "end_datetime": { + "name": "end_datetime", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "location": { + "name": "location", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "dues_paying": { + "name": "dues_paying", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_operations_calendar": { + "name": "is_operations_calendar", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "roles": { + "name": "roles", + "type": "varchar(255)[]", + "primaryKey": false, + "notNull": true, + "default": "'{}'" + }, + "points": { + "name": "points", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "purpose": { + "name": "purpose", + "type": "event_purpose", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'event'" + }, + "discord_channel_id": { + "name": "discord_channel_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "legacy": { + "name": "legacy", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "discord_sync_state": { + "name": "discord_sync_state", + "type": "event_sync_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'pending'" + }, + "google_sync_state": { + "name": "google_sync_state", + "type": "event_sync_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": false, + "default": "'pending'" + }, + "discord_last_error": { + "name": "discord_last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "google_last_error": { + "name": "google_last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "published_at": { + "name": "published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "deletion_intent_at": { + "name": "deletion_intent_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "creation_key": { + "name": "creation_key", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "creation_payload_hash": { + "name": "creation_payload_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "sync_revision": { + "name": "sync_revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "sync_lease_token": { + "name": "sync_lease_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "sync_lease_expires_at": { + "name": "sync_lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sync_lease_revision": { + "name": "sync_lease_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "discord_outbound_attempt_token": { + "name": "discord_outbound_attempt_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "discord_outbound_attempted_at": { + "name": "discord_outbound_attempted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "discord_outbound_attempt_revision": { + "name": "discord_outbound_attempt_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "google_outbound_attempt_token": { + "name": "google_outbound_attempt_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "google_outbound_attempted_at": { + "name": "google_outbound_attempted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "google_outbound_attempt_revision": { + "name": "google_outbound_attempt_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "discord_applied_revision": { + "name": "discord_applied_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "discord_applied_entity_type": { + "name": "discord_applied_entity_type", + "type": "event_discord_entity_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "discord_applied_channel_id": { + "name": "discord_applied_channel_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "google_applied_revision": { + "name": "google_applied_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "google_applied_destination": { + "name": "google_applied_destination", + "type": "event_google_destination", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "google_applied_calendar_id": { + "name": "google_applied_calendar_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "visibility_revision": { + "name": "visibility_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "visibility_dues_paying": { + "name": "visibility_dues_paying", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "visibility_roles": { + "name": "visibility_roles", + "type": "varchar(255)[]", + "primaryKey": false, + "notNull": false + }, + "visibility_internal": { + "name": "visibility_internal", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "discord_no_projection_acknowledged_at": { + "name": "discord_no_projection_acknowledged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "discord_no_projection_acknowledged_by": { + "name": "discord_no_projection_acknowledged_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_event_start_datetime_idx": { + "name": "knight_hacks_event_start_datetime_idx", + "columns": [ + { + "expression": "start_datetime", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_hackathon_id_idx": { + "name": "knight_hacks_event_hackathon_id_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_one_primary_per_hackathon": { + "name": "knight_hacks_event_one_primary_per_hackathon", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_event\".\"purpose\" = 'primary_check_in'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_event_tag_id_knight_hacks_event_tag_id_fk": { + "name": "knight_hacks_event_tag_id_knight_hacks_event_tag_id_fk", + "tableFrom": "knight_hacks_event", + "tableTo": "knight_hacks_event_tag", + "columnsFrom": ["tag_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_event_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_event_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_event", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_event_discord_no_projection_acknowledged_by_auth_user_id_fk": { + "name": "knight_hacks_event_discord_no_projection_acknowledged_by_auth_user_id_fk", + "tableFrom": "knight_hacks_event", + "tableTo": "auth_user", + "columnsFrom": ["discord_no_projection_acknowledged_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_event_creationKey_unique": { + "name": "knight_hacks_event_creationKey_unique", + "nullsNotDistinct": false, + "columns": ["creation_key"] + }, + "knight_hacks_event_id_hackathon_unique": { + "name": "knight_hacks_event_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_event_primary_requires_hackathon_check": { + "name": "knight_hacks_event_primary_requires_hackathon_check", + "value": "\"knight_hacks_event\".\"purpose\" <> 'primary_check_in' OR \"knight_hacks_event\".\"hackathon_id\" IS NOT NULL" + }, + "knight_hacks_event_tag_color_check": { + "name": "knight_hacks_event_tag_color_check", + "value": "\"knight_hacks_event\".\"tag_color\" ~ '^#[0-9A-Fa-f]{6}$'" + }, + "knight_hacks_event_sync_revision_check": { + "name": "knight_hacks_event_sync_revision_check", + "value": "\"knight_hacks_event\".\"sync_revision\" >= 0" + }, + "knight_hacks_event_new_points_check": { + "name": "knight_hacks_event_new_points_check", + "value": "\"knight_hacks_event\".\"legacy\" OR (\"knight_hacks_event\".\"points\" IS NOT NULL AND \"knight_hacks_event\".\"points\" >= 0)" + }, + "knight_hacks_event_nonlegacy_sync_states_check": { + "name": "knight_hacks_event_nonlegacy_sync_states_check", + "value": "\"knight_hacks_event\".\"legacy\" OR (\"knight_hacks_event\".\"discord_sync_state\" IS NOT NULL AND \"knight_hacks_event\".\"google_sync_state\" IS NOT NULL)" + }, + "knight_hacks_event_creation_identity_pair_check": { + "name": "knight_hacks_event_creation_identity_pair_check", + "value": "(\"knight_hacks_event\".\"creation_key\" IS NULL) = (\"knight_hacks_event\".\"creation_payload_hash\" IS NULL)" + }, + "knight_hacks_event_new_creation_identity_check": { + "name": "knight_hacks_event_new_creation_identity_check", + "value": "\"knight_hacks_event\".\"legacy\" OR (\"knight_hacks_event\".\"creation_key\" IS NOT NULL AND \"knight_hacks_event\".\"creation_payload_hash\" IS NOT NULL)" + }, + "knight_hacks_event_sync_lease_set_check": { + "name": "knight_hacks_event_sync_lease_set_check", + "value": "(\"knight_hacks_event\".\"sync_lease_token\" IS NULL AND \"knight_hacks_event\".\"sync_lease_expires_at\" IS NULL AND \"knight_hacks_event\".\"sync_lease_revision\" IS NULL) OR (\"knight_hacks_event\".\"sync_lease_token\" IS NOT NULL AND \"knight_hacks_event\".\"sync_lease_expires_at\" IS NOT NULL AND \"knight_hacks_event\".\"sync_lease_revision\" IS NOT NULL)" + }, + "knight_hacks_event_discord_attempt_set_check": { + "name": "knight_hacks_event_discord_attempt_set_check", + "value": "(\"knight_hacks_event\".\"discord_outbound_attempt_token\" IS NULL AND \"knight_hacks_event\".\"discord_outbound_attempted_at\" IS NULL AND \"knight_hacks_event\".\"discord_outbound_attempt_revision\" IS NULL) OR (\"knight_hacks_event\".\"discord_outbound_attempt_token\" IS NOT NULL AND \"knight_hacks_event\".\"discord_outbound_attempted_at\" IS NOT NULL AND \"knight_hacks_event\".\"discord_outbound_attempt_revision\" IS NOT NULL)" + }, + "knight_hacks_event_google_attempt_set_check": { + "name": "knight_hacks_event_google_attempt_set_check", + "value": "(\"knight_hacks_event\".\"google_outbound_attempt_token\" IS NULL AND \"knight_hacks_event\".\"google_outbound_attempted_at\" IS NULL AND \"knight_hacks_event\".\"google_outbound_attempt_revision\" IS NULL) OR (\"knight_hacks_event\".\"google_outbound_attempt_token\" IS NOT NULL AND \"knight_hacks_event\".\"google_outbound_attempted_at\" IS NOT NULL AND \"knight_hacks_event\".\"google_outbound_attempt_revision\" IS NOT NULL)" + }, + "knight_hacks_event_visibility_set_check": { + "name": "knight_hacks_event_visibility_set_check", + "value": "(\"knight_hacks_event\".\"visibility_revision\" IS NULL AND \"knight_hacks_event\".\"visibility_dues_paying\" IS NULL AND \"knight_hacks_event\".\"visibility_roles\" IS NULL AND \"knight_hacks_event\".\"visibility_internal\" IS NULL) OR (\"knight_hacks_event\".\"visibility_revision\" IS NOT NULL AND \"knight_hacks_event\".\"visibility_dues_paying\" IS NOT NULL AND \"knight_hacks_event\".\"visibility_roles\" IS NOT NULL AND \"knight_hacks_event\".\"visibility_internal\" IS NOT NULL)" + }, + "knight_hacks_event_visibility_revision_check": { + "name": "knight_hacks_event_visibility_revision_check", + "value": "\"knight_hacks_event\".\"visibility_revision\" IS NULL OR \"knight_hacks_event\".\"visibility_revision\" <= \"knight_hacks_event\".\"sync_revision\"" + }, + "knight_hacks_event_discord_applied_revision_check": { + "name": "knight_hacks_event_discord_applied_revision_check", + "value": "\"knight_hacks_event\".\"discord_applied_revision\" IS NULL OR \"knight_hacks_event\".\"discord_applied_revision\" <= \"knight_hacks_event\".\"sync_revision\"" + }, + "knight_hacks_event_google_applied_revision_check": { + "name": "knight_hacks_event_google_applied_revision_check", + "value": "\"knight_hacks_event\".\"google_applied_revision\" IS NULL OR \"knight_hacks_event\".\"google_applied_revision\" <= \"knight_hacks_event\".\"sync_revision\"" + }, + "knight_hacks_event_discord_synced_state_check": { + "name": "knight_hacks_event_discord_synced_state_check", + "value": "\"knight_hacks_event\".\"discord_sync_state\" IS DISTINCT FROM 'synced' OR (\"knight_hacks_event\".\"discord_id\" IS NOT NULL AND \"knight_hacks_event\".\"discord_applied_revision\" IS NOT NULL AND \"knight_hacks_event\".\"discord_applied_revision\" = \"knight_hacks_event\".\"sync_revision\" AND \"knight_hacks_event\".\"discord_applied_entity_type\" IS NOT NULL AND ((\"knight_hacks_event\".\"discord_applied_entity_type\" = 'external' AND \"knight_hacks_event\".\"discord_applied_channel_id\" IS NULL) OR (\"knight_hacks_event\".\"discord_applied_entity_type\" IN ('voice', 'stage') AND \"knight_hacks_event\".\"discord_applied_channel_id\" IS NOT NULL)))" + }, + "knight_hacks_event_google_synced_state_check": { + "name": "knight_hacks_event_google_synced_state_check", + "value": "\"knight_hacks_event\".\"google_sync_state\" IS DISTINCT FROM 'synced' OR (\"knight_hacks_event\".\"google_id\" IS NOT NULL AND \"knight_hacks_event\".\"google_applied_revision\" IS NOT NULL AND \"knight_hacks_event\".\"google_applied_revision\" = \"knight_hacks_event\".\"sync_revision\" AND \"knight_hacks_event\".\"google_applied_destination\" IS NOT NULL AND \"knight_hacks_event\".\"google_applied_calendar_id\" IS NOT NULL)" + }, + "knight_hacks_event_published_visibility_check": { + "name": "knight_hacks_event_published_visibility_check", + "value": "\"knight_hacks_event\".\"published_at\" IS NULL OR (\"knight_hacks_event\".\"visibility_revision\" IS NOT NULL AND \"knight_hacks_event\".\"visibility_dues_paying\" IS NOT NULL AND \"knight_hacks_event\".\"visibility_roles\" IS NOT NULL AND \"knight_hacks_event\".\"visibility_internal\" IS NOT NULL)" + }, + "knight_hacks_event_discord_acknowledgement_time_check": { + "name": "knight_hacks_event_discord_acknowledgement_time_check", + "value": "\"knight_hacks_event\".\"discord_no_projection_acknowledged_by\" IS NULL OR \"knight_hacks_event\".\"discord_no_projection_acknowledged_at\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_event_attendee": { + "name": "knight_hacks_event_attendee", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "checked_in_at": { + "name": "checked_in_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "checked_in_by": { + "name": "checked_in_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "points_awarded": { + "name": "points_awarded", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "points_awarded_estimated": { + "name": "points_awarded_estimated", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "knight_hacks_event_attendee_event_member_idx": { + "name": "knight_hacks_event_attendee_event_member_idx", + "columns": [ + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_attendee_member_event_idx": { + "name": "knight_hacks_event_attendee_member_event_idx", + "columns": [ + { + "expression": "member_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_event_attendee_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_event_attendee_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_event_attendee", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_event_attendee_event_id_knight_hacks_event_id_fk": { + "name": "knight_hacks_event_attendee_event_id_knight_hacks_event_id_fk", + "tableFrom": "knight_hacks_event_attendee", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_event_attendee_checked_in_by_auth_user_id_fk": { + "name": "knight_hacks_event_attendee_checked_in_by_auth_user_id_fk", + "tableFrom": "knight_hacks_event_attendee", + "tableTo": "auth_user", + "columnsFrom": ["checked_in_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_event_feedback": { + "name": "knight_hacks_event_feedback", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "overall_event_rating": { + "name": "overall_event_rating", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "fun_rating": { + "name": "fun_rating", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "learned_rating": { + "name": "learned_rating", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "heard_about_us": { + "name": "heard_about_us", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "additional_feedback": { + "name": "additional_feedback", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "similar_event": { + "name": "similar_event", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_event_feedback_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_event_feedback_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_event_feedback", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_event_feedback_event_id_knight_hacks_event_id_fk": { + "name": "knight_hacks_event_feedback_event_id_knight_hacks_event_id_fk", + "tableFrom": "knight_hacks_event_feedback", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_event_feedback_config": { + "name": "knight_hacks_event_feedback_config", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "form_id": { + "name": "form_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "closes_at": { + "name": "closes_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "reward_points": { + "name": "reward_points", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 5 + }, + "template_revision": { + "name": "template_revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "custom_questions": { + "name": "custom_questions", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_event_feedback_config_event_id_knight_hacks_event_id_fk": { + "name": "knight_hacks_event_feedback_config_event_id_knight_hacks_event_id_fk", + "tableFrom": "knight_hacks_event_feedback_config", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_event_feedback_config_form_id_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_event_feedback_config_form_id_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_event_feedback_config", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_event_feedback_config_eventId_unique": { + "name": "knight_hacks_event_feedback_config_eventId_unique", + "nullsNotDistinct": false, + "columns": ["event_id"] + }, + "knight_hacks_event_feedback_config_formId_unique": { + "name": "knight_hacks_event_feedback_config_formId_unique", + "nullsNotDistinct": false, + "columns": ["form_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_event_feedback_config_reward_check": { + "name": "knight_hacks_event_feedback_config_reward_check", + "value": "\"knight_hacks_event_feedback_config\".\"reward_points\" = 5" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_event_feedback_reward": { + "name": "knight_hacks_event_feedback_reward", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "points_awarded": { + "name": "points_awarded", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 5 + }, + "awarded_at": { + "name": "awarded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_event_feedback_reward_event_id_knight_hacks_event_id_fk": { + "name": "knight_hacks_event_feedback_reward_event_id_knight_hacks_event_id_fk", + "tableFrom": "knight_hacks_event_feedback_reward", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_event_feedback_reward_member_id_knight_hacks_member_id_fk": { + "name": "knight_hacks_event_feedback_reward_member_id_knight_hacks_member_id_fk", + "tableFrom": "knight_hacks_event_feedback_reward", + "tableTo": "knight_hacks_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_event_feedback_reward_response_id_knight_hacks_form_response_id_fk": { + "name": "knight_hacks_event_feedback_reward_response_id_knight_hacks_form_response_id_fk", + "tableFrom": "knight_hacks_event_feedback_reward", + "tableTo": "knight_hacks_form_response", + "columnsFrom": ["response_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_event_feedback_reward_event_member_unique": { + "name": "knight_hacks_event_feedback_reward_event_member_unique", + "nullsNotDistinct": false, + "columns": ["event_id", "member_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_event_feedback_reward_points_check": { + "name": "knight_hacks_event_feedback_reward_points_check", + "value": "\"knight_hacks_event_feedback_reward\".\"points_awarded\" = 5" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_event_publication_work": { + "name": "knight_hacks_event_publication_work", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "publication_id": { + "name": "publication_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "hackathon_event_publication_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "target_enabled": { + "name": "target_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "event_revision": { + "name": "event_revision", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "publication_revision": { + "name": "publication_revision", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "event_publication_work_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempt_count": { + "name": "attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "lease_token": { + "name": "lease_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_event_publication_work_due_idx": { + "name": "knight_hacks_event_publication_work_due_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_publication_work_health_idx": { + "name": "knight_hacks_event_publication_work_health_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "provider", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_publication_work_lease_expiry_idx": { + "name": "knight_hacks_event_publication_work_lease_expiry_idx", + "columns": [ + { + "expression": "lease_expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_event_publication_work_scoped_publication_fk": { + "name": "knight_hacks_event_publication_work_scoped_publication_fk", + "tableFrom": "knight_hacks_event_publication_work", + "tableTo": "knight_hacks_hackathon_event_publication", + "columnsFrom": ["publication_id", "hackathon_id", "provider"], + "columnsTo": ["id", "hackathon_id", "provider"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_event_publication_work_scoped_event_fk": { + "name": "knight_hacks_event_publication_work_scoped_event_fk", + "tableFrom": "knight_hacks_event_publication_work", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_event_publication_work_event_provider_unique": { + "name": "knight_hacks_event_publication_work_event_provider_unique", + "nullsNotDistinct": false, + "columns": ["event_id", "provider"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_event_publication_work_attempt_count_check": { + "name": "knight_hacks_event_publication_work_attempt_count_check", + "value": "\"knight_hacks_event_publication_work\".\"attempt_count\" >= 0" + }, + "knight_hacks_event_publication_work_revisions_check": { + "name": "knight_hacks_event_publication_work_revisions_check", + "value": "\"knight_hacks_event_publication_work\".\"event_revision\" >= 1 AND \"knight_hacks_event_publication_work\".\"publication_revision\" >= 1" + }, + "knight_hacks_event_publication_work_lease_pair_check": { + "name": "knight_hacks_event_publication_work_lease_pair_check", + "value": "(\"knight_hacks_event_publication_work\".\"lease_token\" IS NULL) = (\"knight_hacks_event_publication_work\".\"lease_expires_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_event_tag": { + "name": "knight_hacks_event_tag", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "normalized_name": { + "name": "normalized_name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "default_points": { + "name": "default_points", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "emoji": { + "name": "emoji", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "announcement_channel_id": { + "name": "announcement_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "skip_next_week": { + "name": "skip_next_week", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "color": { + "name": "color", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_event_tag_club_normalized_name_unique": { + "name": "knight_hacks_event_tag_club_normalized_name_unique", + "columns": [ + { + "expression": "normalized_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_event_tag\".\"hackathon_id\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_tag_hackathon_normalized_name_unique": { + "name": "knight_hacks_event_tag_hackathon_normalized_name_unique", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "normalized_name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_event_tag\".\"hackathon_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_event_tag_hackathon_idx": { + "name": "knight_hacks_event_tag_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_event_tag_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_event_tag_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_event_tag", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_event_tag_default_points_check": { + "name": "knight_hacks_event_tag_default_points_check", + "value": "\"knight_hacks_event_tag\".\"default_points\" >= 0" + }, + "knight_hacks_event_tag_announcement_channel_check": { + "name": "knight_hacks_event_tag_announcement_channel_check", + "value": "\"knight_hacks_event_tag\".\"announcement_channel_id\" IS NULL OR \"knight_hacks_event_tag\".\"announcement_channel_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_event_tag_color_check": { + "name": "knight_hacks_event_tag_color_check", + "value": "\"knight_hacks_event_tag\".\"color\" ~ '^#[0-9A-Fa-f]{6}$'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_form_attachment": { + "name": "knight_hacks_form_attachment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "form_id": { + "name": "form_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "object_name": { + "name": "object_name", + "type": "varchar(512)", + "primaryKey": false, + "notNull": true + }, + "file_name": { + "name": "file_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "purpose": { + "name": "purpose", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'response'" + }, + "finalized_at": { + "name": "finalized_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_form_attachment_form_idx": { + "name": "knight_hacks_form_attachment_form_idx", + "columns": [ + { + "expression": "form_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_form_attachment_response_idx": { + "name": "knight_hacks_form_attachment_response_idx", + "columns": [ + { + "expression": "response_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_form_attachment_form_id_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_form_attachment_form_id_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_form_attachment", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_attachment_response_id_knight_hacks_form_response_id_fk": { + "name": "knight_hacks_form_attachment_response_id_knight_hacks_form_response_id_fk", + "tableFrom": "knight_hacks_form_attachment", + "tableTo": "knight_hacks_form_response", + "columnsFrom": ["response_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_attachment_owner_user_id_auth_user_id_fk": { + "name": "knight_hacks_form_attachment_owner_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_form_attachment", + "tableTo": "auth_user", + "columnsFrom": ["owner_user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_form_attachment_objectName_unique": { + "name": "knight_hacks_form_attachment_objectName_unique", + "nullsNotDistinct": false, + "columns": ["object_name"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_form_attachment_purpose_check": { + "name": "knight_hacks_form_attachment_purpose_check", + "value": "\"knight_hacks_form_attachment\".\"purpose\" IN ('banner', 'instruction', 'response')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_form_callback_configuration": { + "name": "knight_hacks_form_callback_configuration", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "form_id": { + "name": "form_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "callback_slug": { + "name": "callback_slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "mappings": { + "name": "mappings", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_callback_configuration_form_id_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_form_callback_configuration_form_id_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_form_callback_configuration", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_form_callback_configuration_form_slug_unique": { + "name": "knight_hacks_form_callback_configuration_form_slug_unique", + "nullsNotDistinct": false, + "columns": ["form_id", "callback_slug"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_callback_execution": { + "name": "knight_hacks_form_callback_execution", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "configuration_id": { + "name": "configuration_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "callback_slug": { + "name": "callback_slug", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "input": { + "name": "input", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "form_callback_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempts": { + "name": "attempts", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "available_at": { + "name": "available_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "lease_token": { + "name": "lease_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "succeeded_at": { + "name": "succeeded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_form_callback_execution_status_available_idx": { + "name": "knight_hacks_form_callback_execution_status_available_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "available_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_form_callback_execution_configuration_id_knight_hacks_form_callback_configuration_id_fk": { + "name": "knight_hacks_form_callback_execution_configuration_id_knight_hacks_form_callback_configuration_id_fk", + "tableFrom": "knight_hacks_form_callback_execution", + "tableTo": "knight_hacks_form_callback_configuration", + "columnsFrom": ["configuration_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_form_callback_execution_response_id_knight_hacks_form_response_id_fk": { + "name": "knight_hacks_form_callback_execution_response_id_knight_hacks_form_response_id_fk", + "tableFrom": "knight_hacks_form_callback_execution", + "tableTo": "knight_hacks_form_response", + "columnsFrom": ["response_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_response": { + "name": "knight_hacks_form_response", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "form": { + "name": "form", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "response_data": { + "name": "response_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "form_revision": { + "name": "form_revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "response_snapshot": { + "name": "response_snapshot", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'{}'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "edited_at": { + "name": "edited_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_form_response_form_created_idx": { + "name": "knight_hacks_form_response_form_created_idx", + "columns": [ + { + "expression": "form", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_form_response_user_created_idx": { + "name": "knight_hacks_form_response_user_created_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_form_response_form_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_form_response_form_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_form_response", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "knight_hacks_form_response_user_id_auth_user_id_fk": { + "name": "knight_hacks_form_response_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_form_response", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_response_roles": { + "name": "knight_hacks_form_response_roles", + "schema": "", + "columns": { + "form_id": { + "name": "form_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_response_roles_form_id_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_form_response_roles_form_id_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_form_response_roles", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_response_roles_role_id_auth_roles_id_fk": { + "name": "knight_hacks_form_response_roles_role_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_form_response_roles", + "tableTo": "auth_roles", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_form_response_roles_form_id_role_id_pk": { + "name": "knight_hacks_form_response_roles_form_id_role_id_pk", + "columns": ["form_id", "role_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_section_edit_role": { + "name": "knight_hacks_form_section_edit_role", + "schema": "", + "columns": { + "section_id": { + "name": "section_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_section_edit_role_section_id_knight_hacks_form_sections_id_fk": { + "name": "knight_hacks_form_section_edit_role_section_id_knight_hacks_form_sections_id_fk", + "tableFrom": "knight_hacks_form_section_edit_role", + "tableTo": "knight_hacks_form_sections", + "columnsFrom": ["section_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_section_edit_role_role_id_auth_roles_id_fk": { + "name": "knight_hacks_form_section_edit_role_role_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_form_section_edit_role", + "tableTo": "auth_roles", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_form_section_edit_role_section_id_role_id_pk": { + "name": "knight_hacks_form_section_edit_role_section_id_role_id_pk", + "columns": ["section_id", "role_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_section_roles": { + "name": "knight_hacks_form_section_roles", + "schema": "", + "columns": { + "section_id": { + "name": "section_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_section_roles_section_id_knight_hacks_form_sections_id_fk": { + "name": "knight_hacks_form_section_roles_section_id_knight_hacks_form_sections_id_fk", + "tableFrom": "knight_hacks_form_section_roles", + "tableTo": "knight_hacks_form_sections", + "columnsFrom": ["section_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_section_roles_role_id_auth_roles_id_fk": { + "name": "knight_hacks_form_section_roles_role_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_form_section_roles", + "tableTo": "auth_roles", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_form_section_roles_section_id_role_id_pk": { + "name": "knight_hacks_form_section_roles_section_id_role_id_pk", + "columns": ["section_id", "role_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_section_view_role": { + "name": "knight_hacks_form_section_view_role", + "schema": "", + "columns": { + "section_id": { + "name": "section_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_section_view_role_section_id_knight_hacks_form_sections_id_fk": { + "name": "knight_hacks_form_section_view_role_section_id_knight_hacks_form_sections_id_fk", + "tableFrom": "knight_hacks_form_section_view_role", + "tableTo": "knight_hacks_form_sections", + "columnsFrom": ["section_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_section_view_role_role_id_auth_roles_id_fk": { + "name": "knight_hacks_form_section_view_role_role_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_form_section_view_role", + "tableTo": "auth_roles", + "columnsFrom": ["role_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_form_section_view_role_section_id_role_id_pk": { + "name": "knight_hacks_form_section_view_role_section_id_role_id_pk", + "columns": ["section_id", "role_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_sections": { + "name": "knight_hacks_form_sections", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "order": { + "name": "order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_form_sections_name_unique": { + "name": "knight_hacks_form_sections_name_unique", + "nullsNotDistinct": false, + "columns": ["name"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_single_response_claim": { + "name": "knight_hacks_form_single_response_claim", + "schema": "", + "columns": { + "form_id": { + "name": "form_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "response_id": { + "name": "response_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_single_response_claim_form_id_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_form_single_response_claim_form_id_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_form_single_response_claim", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_single_response_claim_user_id_auth_user_id_fk": { + "name": "knight_hacks_form_single_response_claim_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_form_single_response_claim", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_form_single_response_claim_response_id_knight_hacks_form_response_id_fk": { + "name": "knight_hacks_form_single_response_claim_response_id_knight_hacks_form_response_id_fk", + "tableFrom": "knight_hacks_form_single_response_claim", + "tableTo": "knight_hacks_form_response", + "columnsFrom": ["response_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_form_single_response_claim_form_id_user_id_pk": { + "name": "knight_hacks_form_single_response_claim_form_id_user_id_pk", + "columns": ["form_id", "user_id"] + } + }, + "uniqueConstraints": { + "knight_hacks_form_single_response_claim_responseId_unique": { + "name": "knight_hacks_form_single_response_claim_responseId_unique", + "nullsNotDistinct": false, + "columns": ["response_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_form_schemas": { + "name": "knight_hacks_form_schemas", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "slug_name": { + "name": "slug_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "kind": { + "name": "kind", + "type": "form_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'general'" + }, + "state": { + "name": "state", + "type": "form_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "opens_at": { + "name": "opens_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "closes_at": { + "name": "closes_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "manually_closed": { + "name": "manually_closed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "response_mode": { + "name": "response_mode", + "type": "form_response_mode", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'single_locked'" + }, + "published_at": { + "name": "published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "dues_only": { + "name": "dues_only", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "allow_resubmission": { + "name": "allow_resubmission", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "allow_edit": { + "name": "allow_edit", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "form_data": { + "name": "form_data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "form_validator_json": { + "name": "form_validator_json", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "section": { + "name": "section", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "'General'" + }, + "section_id": { + "name": "section_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "is_closed": { + "name": "is_closed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_form_schemas_section_id_knight_hacks_form_sections_id_fk": { + "name": "knight_hacks_form_schemas_section_id_knight_hacks_form_sections_id_fk", + "tableFrom": "knight_hacks_form_schemas", + "tableTo": "knight_hacks_form_sections", + "columnsFrom": ["section_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_form_schemas_slugName_unique": { + "name": "knight_hacks_form_schemas_slugName_unique", + "nullsNotDistinct": false, + "columns": ["slug_name"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_guest_judge_session": { + "name": "knight_hacks_guest_judge_session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "access_link_id": { + "name": "access_link_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "judge_id": { + "name": "judge_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "token_hash": { + "name": "token_hash", + "type": "char(64)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "revoked_by_user_id": { + "name": "revoked_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "revocation_reason": { + "name": "revocation_reason", + "type": "varchar(80)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_guest_judge_session_access_link_idx": { + "name": "knight_hacks_guest_judge_session_access_link_idx", + "columns": [ + { + "expression": "access_link_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_guest_judge_session_revoked_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_guest_judge_session_revoked_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_guest_judge_session", + "tableTo": "auth_user", + "columnsFrom": ["revoked_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_guest_judge_session_access_link_scope_fk": { + "name": "knight_hacks_guest_judge_session_access_link_scope_fk", + "tableFrom": "knight_hacks_guest_judge_session", + "tableTo": "knight_hacks_judging_room_access_link", + "columnsFrom": ["access_link_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_guest_judge_session_judge_scope_fk": { + "name": "knight_hacks_guest_judge_session_judge_scope_fk", + "tableFrom": "knight_hacks_guest_judge_session", + "tableTo": "knight_hacks_judge", + "columnsFrom": ["judge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_guest_judge_session_token_hash_unique": { + "name": "knight_hacks_guest_judge_session_token_hash_unique", + "nullsNotDistinct": false, + "columns": ["token_hash"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon": { + "name": "knight_hacks_hackathon", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "theme": { + "name": "theme", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "timezone": { + "name": "timezone", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true, + "default": "'America/New_York'" + }, + "application_url": { + "name": "application_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "store_catalog_visible": { + "name": "store_catalog_visible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "store_open": { + "name": "store_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "store_location": { + "name": "store_location", + "type": "varchar(240)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "application_background_enabled": { + "name": "application_background_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "application_background_key": { + "name": "application_background_key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "email_template_enabled": { + "name": "email_template_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "email_template_key": { + "name": "email_template_key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "application_open": { + "name": "application_open", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "application_deadline": { + "name": "application_deadline", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "confirmation_deadline": { + "name": "confirmation_deadline", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "start_date": { + "name": "start_date", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "end_date": { + "name": "end_date", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "confirmation_capacity": { + "name": "confirmation_capacity", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "general_hacker_discord_role_id": { + "name": "general_hacker_discord_role_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "event_announcement_channel_id": { + "name": "event_announcement_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "issue_reports_channel_id": { + "name": "issue_reports_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "issue_reports_role_id": { + "name": "issue_reports_role_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_name_unique": { + "name": "knight_hacks_hackathon_name_unique", + "nullsNotDistinct": false, + "columns": ["name"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_issue_reports_channel_id_check": { + "name": "knight_hacks_hackathon_issue_reports_channel_id_check", + "value": "\"knight_hacks_hackathon\".\"issue_reports_channel_id\" IS NULL OR \"knight_hacks_hackathon\".\"issue_reports_channel_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_issue_reports_role_id_check": { + "name": "knight_hacks_hackathon_issue_reports_role_id_check", + "value": "\"knight_hacks_hackathon\".\"issue_reports_role_id\" IS NULL OR \"knight_hacks_hackathon\".\"issue_reports_role_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_event_announcement_channel_id_check": { + "name": "knight_hacks_hackathon_event_announcement_channel_id_check", + "value": "\"knight_hacks_hackathon\".\"event_announcement_channel_id\" IS NULL OR \"knight_hacks_hackathon\".\"event_announcement_channel_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_general_hacker_discord_role_id_check": { + "name": "knight_hacks_hackathon_general_hacker_discord_role_id_check", + "value": "\"knight_hacks_hackathon\".\"general_hacker_discord_role_id\" IS NULL OR \"knight_hacks_hackathon\".\"general_hacker_discord_role_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_confirmation_capacity_check": { + "name": "knight_hacks_hackathon_confirmation_capacity_check", + "value": "\"knight_hacks_hackathon\".\"confirmation_capacity\" IS NULL OR \"knight_hacks_hackathon\".\"confirmation_capacity\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_agreement_definition": { + "name": "knight_hacks_hackathon_agreement_definition", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "stage": { + "name": "stage", + "type": "hacker_agreement_stage", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "legal_text": { + "name": "legal_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hackathon_agreement_definition_active_unique": { + "name": "knight_hacks_hackathon_agreement_definition_active_unique", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "stage", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_hackathon_agreement_definition\".\"active\" = true", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hackathon_agreement_definition_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_agreement_definition_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_agreement_definition", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_agreement_definition_created_by_auth_user_id_fk": { + "name": "knight_hacks_hackathon_agreement_definition_created_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hackathon_agreement_definition", + "tableTo": "auth_user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_agreement_definition_version_unique": { + "name": "knight_hacks_hackathon_agreement_definition_version_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id", "stage", "key", "version"] + }, + "knight_hacks_hackathon_agreement_definition_id_hackathon_unique": { + "name": "knight_hacks_hackathon_agreement_definition_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_agreement_definition_content_check": { + "name": "knight_hacks_hackathon_agreement_definition_content_check", + "value": "\"knight_hacks_hackathon_agreement_definition\".\"legal_text\" IS NOT NULL OR \"knight_hacks_hackathon_agreement_definition\".\"url\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_class": { + "name": "knight_hacks_hackathon_class", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "discord_role_id": { + "name": "discord_role_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "varchar(7)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "knight_hacks_hackathon_class_hackathon_idx": { + "name": "knight_hacks_hackathon_class_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hackathon_class_one_vip_per_hackathon": { + "name": "knight_hacks_hackathon_class_one_vip_per_hackathon", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_hackathon_class\".\"kind\" = 'vip'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hackathon_class_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_class_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_class", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_class_id_hackathon_unique": { + "name": "knight_hacks_hackathon_class_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_class_discord_role_id_check": { + "name": "knight_hacks_hackathon_class_discord_role_id_check", + "value": "\"knight_hacks_hackathon_class\".\"discord_role_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_class_color_check": { + "name": "knight_hacks_hackathon_class_color_check", + "value": "\"knight_hacks_hackathon_class\".\"color\" ~ '^#[0-9a-fA-F]{6}$'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_event_publication": { + "name": "knight_hacks_hackathon_event_publication", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "provider": { + "name": "provider", + "type": "hackathon_event_publication_provider", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "desired_enabled": { + "name": "desired_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "requested_at": { + "name": "requested_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "requested_by": { + "name": "requested_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "last_reconciled_at": { + "name": "last_reconciled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_converged_at": { + "name": "last_converged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hackathon_event_publication_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_event_publication_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_event_publication", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_event_publication_requested_by_auth_user_id_fk": { + "name": "knight_hacks_hackathon_event_publication_requested_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hackathon_event_publication", + "tableTo": "auth_user", + "columnsFrom": ["requested_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_event_publication_provider_unique": { + "name": "knight_hacks_hackathon_event_publication_provider_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id", "provider"] + }, + "knight_hacks_hackathon_event_publication_id_scope_unique": { + "name": "knight_hacks_hackathon_event_publication_id_scope_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id", "provider"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_event_publication_revision_check": { + "name": "knight_hacks_hackathon_event_publication_revision_check", + "value": "\"knight_hacks_hackathon_event_publication\".\"revision\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_event_reminder_delivery": { + "name": "knight_hacks_hackathon_event_reminder_delivery", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event_start_at": { + "name": "event_start_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "reminder_key": { + "name": "reminder_key", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "destination_channel_id_snapshot": { + "name": "destination_channel_id_snapshot", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "role_id_snapshot": { + "name": "role_id_snapshot", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "discord_event_id_snapshot": { + "name": "discord_event_id_snapshot", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "content_snapshot": { + "name": "content_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "hackathon_event_reminder_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempt_count": { + "name": "attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "locked_at": { + "name": "locked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_hackathon_event_reminder_delivery_pending_idx": { + "name": "knight_hacks_hackathon_event_reminder_delivery_pending_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hackathon_event_reminder_scoped_event_fk": { + "name": "knight_hacks_hackathon_event_reminder_scoped_event_fk", + "tableFrom": "knight_hacks_hackathon_event_reminder_delivery", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_event_reminder_delivery_identity_unique": { + "name": "knight_hacks_hackathon_event_reminder_delivery_identity_unique", + "nullsNotDistinct": false, + "columns": ["event_id", "reminder_key"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_event_reminder_channel_id_check": { + "name": "knight_hacks_hackathon_event_reminder_channel_id_check", + "value": "\"knight_hacks_hackathon_event_reminder_delivery\".\"destination_channel_id_snapshot\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_event_reminder_role_id_check": { + "name": "knight_hacks_hackathon_event_reminder_role_id_check", + "value": "\"knight_hacks_hackathon_event_reminder_delivery\".\"role_id_snapshot\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hackathon_event_reminder_attempt_count_check": { + "name": "knight_hacks_hackathon_event_reminder_attempt_count_check", + "value": "\"knight_hacks_hackathon_event_reminder_delivery\".\"attempt_count\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_judging_configuration": { + "name": "knight_hacks_hackathon_judging_configuration", + "schema": "", + "columns": { + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "hacker_schedule_published": { + "name": "hacker_schedule_published", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "hacker_schedule_emergency": { + "name": "hacker_schedule_emergency", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "project_claims_started_at": { + "name": "project_claims_started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "project_claim_url": { + "name": "project_claim_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "challenge_groups_initialized_at": { + "name": "challenge_groups_initialized_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "project_inventory_locked_at": { + "name": "project_inventory_locked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "project_inventory_locked_by_user_id": { + "name": "project_inventory_locked_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "judging_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'draft'" + }, + "display_all_results_to_members": { + "name": "display_all_results_to_members", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "judging_comms_channel_id": { + "name": "judging_comms_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "opened_at": { + "name": "opened_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "closed_at": { + "name": "closed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hackathon_judging_configuration_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_judging_configuration_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_judging_configuration", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_judging_configuration_project_inventory_locked_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_hackathon_judging_configuration_project_inventory_locked_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hackathon_judging_configuration", + "tableTo": "auth_user", + "columnsFrom": ["project_inventory_locked_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_map_configuration": { + "name": "knight_hacks_hackathon_map_configuration", + "schema": "", + "columns": { + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "restrictions_enabled": { + "name": "restrictions_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "rooms": { + "name": "rooms", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hackathon_map_configuration_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_map_configuration_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_map_configuration", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_portal_authorization_code": { + "name": "knight_hacks_hackathon_portal_authorization_code", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "portal_client_id": { + "name": "portal_client_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "better_auth_session_id": { + "name": "better_auth_session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "code_hash": { + "name": "code_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "code_challenge": { + "name": "code_challenge", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "code_challenge_method": { + "name": "code_challenge_method", + "type": "varchar(8)", + "primaryKey": false, + "notNull": true, + "default": "'S256'" + }, + "redirect_uri": { + "name": "redirect_uri", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_hackathon_portal_authorization_code_expiry_idx": { + "name": "knight_hacks_hackathon_portal_authorization_code_expiry_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hackathon_portal_authorization_code_client_expiry_idx": { + "name": "knight_hacks_hackathon_portal_authorization_code_client_expiry_idx", + "columns": [ + { + "expression": "portal_client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hackathon_portal_authorization_code_user_id_auth_user_id_fk": { + "name": "knight_hacks_hackathon_portal_authorization_code_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_authorization_code", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_portal_authorization_code_better_auth_session_id_auth_session_id_fk": { + "name": "knight_hacks_hackathon_portal_authorization_code_better_auth_session_id_auth_session_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_authorization_code", + "tableTo": "auth_session", + "columnsFrom": ["better_auth_session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_portal_authorization_code_scoped_client_fk": { + "name": "knight_hacks_hackathon_portal_authorization_code_scoped_client_fk", + "tableFrom": "knight_hacks_hackathon_portal_authorization_code", + "tableTo": "knight_hacks_hackathon_portal_client", + "columnsFrom": ["portal_client_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_portal_authorization_code_hash_unique": { + "name": "knight_hacks_hackathon_portal_authorization_code_hash_unique", + "nullsNotDistinct": false, + "columns": ["code_hash"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_portal_authorization_code_hash_check": { + "name": "knight_hacks_hackathon_portal_authorization_code_hash_check", + "value": "\"knight_hacks_hackathon_portal_authorization_code\".\"code_hash\" ~ '^[0-9a-f]{64}$'" + }, + "knight_hacks_hackathon_portal_authorization_code_method_check": { + "name": "knight_hacks_hackathon_portal_authorization_code_method_check", + "value": "\"knight_hacks_hackathon_portal_authorization_code\".\"code_challenge_method\" = 'S256'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_portal_client": { + "name": "knight_hacks_hackathon_portal_client", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "production_origin": { + "name": "production_origin", + "type": "varchar(2048)", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hackathon_portal_client_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_portal_client_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_client", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_portal_client_created_by_auth_user_id_fk": { + "name": "knight_hacks_hackathon_portal_client_created_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_client", + "tableTo": "auth_user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_portal_client_client_id_unique": { + "name": "knight_hacks_hackathon_portal_client_client_id_unique", + "nullsNotDistinct": false, + "columns": ["client_id"] + }, + "knight_hacks_hackathon_portal_client_hackathon_unique": { + "name": "knight_hacks_hackathon_portal_client_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id"] + }, + "knight_hacks_hackathon_portal_client_origin_unique": { + "name": "knight_hacks_hackathon_portal_client_origin_unique", + "nullsNotDistinct": false, + "columns": ["production_origin"] + }, + "knight_hacks_hackathon_portal_client_id_hackathon_unique": { + "name": "knight_hacks_hackathon_portal_client_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_portal_client_origin_check": { + "name": "knight_hacks_hackathon_portal_client_origin_check", + "value": "\"knight_hacks_hackathon_portal_client\".\"production_origin\" ~ '^https://[a-z0-9-]+([.][a-z0-9-]+)*[.]knighthacks[.]org$'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_portal_session": { + "name": "knight_hacks_hackathon_portal_session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "portal_client_id": { + "name": "portal_client_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "better_auth_session_id": { + "name": "better_auth_session_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token_hash": { + "name": "access_token_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "refresh_token_hash": { + "name": "refresh_token_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "access_expires_at": { + "name": "access_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "refresh_expires_at": { + "name": "refresh_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "refresh_version": { + "name": "refresh_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_hackathon_portal_session_access_expiry_idx": { + "name": "knight_hacks_hackathon_portal_session_access_expiry_idx", + "columns": [ + { + "expression": "access_expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "revoked_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hackathon_portal_session_refresh_expiry_idx": { + "name": "knight_hacks_hackathon_portal_session_refresh_expiry_idx", + "columns": [ + { + "expression": "refresh_expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hackathon_portal_session_user_client_idx": { + "name": "knight_hacks_hackathon_portal_session_user_client_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "portal_client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hackathon_portal_session_user_id_auth_user_id_fk": { + "name": "knight_hacks_hackathon_portal_session_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_session", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_portal_session_better_auth_session_id_auth_session_id_fk": { + "name": "knight_hacks_hackathon_portal_session_better_auth_session_id_auth_session_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_session", + "tableTo": "auth_session", + "columnsFrom": ["better_auth_session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_portal_session_scoped_client_fk": { + "name": "knight_hacks_hackathon_portal_session_scoped_client_fk", + "tableFrom": "knight_hacks_hackathon_portal_session", + "tableTo": "knight_hacks_hackathon_portal_client", + "columnsFrom": ["portal_client_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_portal_session_access_hash_unique": { + "name": "knight_hacks_hackathon_portal_session_access_hash_unique", + "nullsNotDistinct": false, + "columns": ["access_token_hash"] + }, + "knight_hacks_hackathon_portal_session_refresh_hash_unique": { + "name": "knight_hacks_hackathon_portal_session_refresh_hash_unique", + "nullsNotDistinct": false, + "columns": ["refresh_token_hash"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_portal_session_access_hash_check": { + "name": "knight_hacks_hackathon_portal_session_access_hash_check", + "value": "\"knight_hacks_hackathon_portal_session\".\"access_token_hash\" ~ '^[0-9a-f]{64}$'" + }, + "knight_hacks_hackathon_portal_session_refresh_hash_check": { + "name": "knight_hacks_hackathon_portal_session_refresh_hash_check", + "value": "\"knight_hacks_hackathon_portal_session\".\"refresh_token_hash\" ~ '^[0-9a-f]{64}$'" + }, + "knight_hacks_hackathon_portal_session_refresh_version_check": { + "name": "knight_hacks_hackathon_portal_session_refresh_version_check", + "value": "\"knight_hacks_hackathon_portal_session\".\"refresh_version\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_portal_session_credential": { + "name": "knight_hacks_hackathon_portal_session_credential", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "portal_session_id": { + "name": "portal_session_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "token_kind": { + "name": "token_kind", + "type": "varchar(8)", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "rotated_at": { + "name": "rotated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_hackathon_portal_session_credential_session_idx": { + "name": "knight_hacks_hackathon_portal_session_credential_session_idx", + "columns": [ + { + "expression": "portal_session_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hackathon_portal_session_credential_portal_session_id_knight_hacks_hackathon_portal_session_id_fk": { + "name": "knight_hacks_hackathon_portal_session_credential_portal_session_id_knight_hacks_hackathon_portal_session_id_fk", + "tableFrom": "knight_hacks_hackathon_portal_session_credential", + "tableTo": "knight_hacks_hackathon_portal_session", + "columnsFrom": ["portal_session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_portal_session_credential_hash_unique": { + "name": "knight_hacks_hackathon_portal_session_credential_hash_unique", + "nullsNotDistinct": false, + "columns": ["token_hash"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_portal_session_credential_hash_check": { + "name": "knight_hacks_hackathon_portal_session_credential_hash_check", + "value": "\"knight_hacks_hackathon_portal_session_credential\".\"token_hash\" ~ '^[0-9a-f]{64}$'" + }, + "knight_hacks_hackathon_portal_session_credential_kind_check": { + "name": "knight_hacks_hackathon_portal_session_credential_kind_check", + "value": "\"knight_hacks_hackathon_portal_session_credential\".\"token_kind\" IN ('access', 'refresh')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_sponsor": { + "name": "knight_hacks_hackathon_sponsor", + "schema": "", + "columns": { + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "sponsor_id": { + "name": "sponsor_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "tier": { + "name": "tier", + "type": "sponsor_tier", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hackathon_sponsor_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_sponsor_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_sponsor", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_sponsor_sponsor_id_knight_hacks_sponsor_id_fk": { + "name": "knight_hacks_hackathon_sponsor_sponsor_id_knight_hacks_sponsor_id_fk", + "tableFrom": "knight_hacks_hackathon_sponsor", + "tableTo": "knight_hacks_sponsor", + "columnsFrom": ["sponsor_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_hackathon_status_email": { + "name": "knight_hacks_hackathon_status_email", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "template_id": { + "name": "template_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "subject": { + "name": "subject", + "type": "varchar(200)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hackathon_status_email_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hackathon_status_email_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hackathon_status_email", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hackathon_status_email_template_id_email_template_id_fk": { + "name": "knight_hacks_hackathon_status_email_template_id_email_template_id_fk", + "tableFrom": "knight_hacks_hackathon_status_email", + "tableTo": "email_template", + "columnsFrom": ["template_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hackathon_status_email_hackathon_status_unique": { + "name": "knight_hacks_hackathon_status_email_hackathon_status_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id", "status"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hackathon_status_email_status_check": { + "name": "knight_hacks_hackathon_status_email_status_check", + "value": "\"knight_hacks_hackathon_status_email\".\"status\" <> 'checkedin'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker": { + "name": "knight_hacks_hacker", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "gender": { + "name": "gender", + "type": "gender", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'Prefer not to answer'" + }, + "discord_user": { + "name": "discord_user", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "age": { + "name": "age", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'United States of America'" + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "phone_number": { + "name": "phone_number", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "school": { + "name": "school", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level_of_study": { + "name": "level_of_study", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "major": { + "name": "major", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Computer Science'" + }, + "race_or_ethnicity": { + "name": "race_or_ethnicity", + "type": "race_or_ethnicity", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'Prefer not to answer'" + }, + "shirt_size": { + "name": "shirt_size", + "type": "shirt_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "github_profile_url": { + "name": "github_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "linkedin_profile_url": { + "name": "linkedin_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "website_url": { + "name": "website_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resume_url": { + "name": "resume_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "dob": { + "name": "dob", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "grad_date": { + "name": "grad_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "survey_1": { + "name": "survey_1", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "survey_2": { + "name": "survey_2", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_first_time": { + "name": "is_first_time", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "food_allergies": { + "name": "food_allergies", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agrees_to_receive_emails_from_mlh": { + "name": "agrees_to_receive_emails_from_mlh", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "agrees_to_mlh_code_of_conduct": { + "name": "agrees_to_mlh_code_of_conduct", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "agrees_to_mlh_data_sharing": { + "name": "agrees_to_mlh_data_sharing", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "date_created": { + "name": "date_created", + "type": "date", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "time_created": { + "name": "time_created", + "type": "time", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hacker_user_id_auth_user_id_fk": { + "name": "knight_hacks_hacker_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_agreement_acceptance": { + "name": "knight_hacks_hacker_agreement_acceptance", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "attendee_id": { + "name": "attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "agreement_definition_id": { + "name": "agreement_definition_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "accepted": { + "name": "accepted", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "provenance": { + "name": "provenance", + "type": "hacker_agreement_provenance", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'explicit'" + }, + "accepted_at": { + "name": "accepted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "recorded_at": { + "name": "recorded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_hacker_agreement_acceptance_attendee_idx": { + "name": "knight_hacks_hacker_agreement_acceptance_attendee_idx", + "columns": [ + { + "expression": "attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_agreement_acceptance_scoped_attendee_fk": { + "name": "knight_hacks_hacker_agreement_acceptance_scoped_attendee_fk", + "tableFrom": "knight_hacks_hacker_agreement_acceptance", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_agreement_acceptance_scoped_definition_fk": { + "name": "knight_hacks_hacker_agreement_acceptance_scoped_definition_fk", + "tableFrom": "knight_hacks_hacker_agreement_acceptance", + "tableTo": "knight_hacks_hackathon_agreement_definition", + "columnsFrom": ["agreement_definition_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_agreement_acceptance_attendee_definition_unique": { + "name": "knight_hacks_hacker_agreement_acceptance_attendee_definition_unique", + "nullsNotDistinct": false, + "columns": ["attendee_id", "agreement_definition_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_agreement_acceptance_timestamp_check": { + "name": "knight_hacks_hacker_agreement_acceptance_timestamp_check", + "value": "(\"knight_hacks_hacker_agreement_acceptance\".\"accepted\" = true AND \"knight_hacks_hacker_agreement_acceptance\".\"accepted_at\" IS NOT NULL) OR (\"knight_hacks_hacker_agreement_acceptance\".\"accepted\" = false AND \"knight_hacks_hacker_agreement_acceptance\".\"accepted_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_attendee": { + "name": "knight_hacks_hacker_attendee", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hacker_id": { + "name": "hacker_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "profile_id": { + "name": "profile_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "profile_revision_id": { + "name": "profile_revision_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "time_applied": { + "name": "time_applied", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "time_confirmed": { + "name": "time_confirmed", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "points": { + "name": "points", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "class_id": { + "name": "class_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "is_vip": { + "name": "is_vip", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_first_time": { + "name": "is_first_time", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "survey1": { + "name": "survey1", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "survey2": { + "name": "survey2", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "checked_in_at": { + "name": "checked_in_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "checked_in_by": { + "name": "checked_in_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "class": { + "name": "class", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false, + "default": null + }, + "blacklisted_at": { + "name": "blacklisted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "blacklisted_by": { + "name": "blacklisted_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "blacklist_reason": { + "name": "blacklist_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_status_send_id": { + "name": "last_status_send_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hacker_attendee_class_idx": { + "name": "knight_hacks_hacker_attendee_class_idx", + "columns": [ + { + "expression": "class_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_hackathon_class_idx": { + "name": "knight_hacks_hacker_attendee_hackathon_class_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "class_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_checked_in_by_idx": { + "name": "knight_hacks_hacker_attendee_checked_in_by_idx", + "columns": [ + { + "expression": "checked_in_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_hackathon_checked_in_idx": { + "name": "knight_hacks_hacker_attendee_hackathon_checked_in_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "checked_in_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_profile_hackathon_unique": { + "name": "knight_hacks_hacker_attendee_profile_hackathon_unique", + "columns": [ + { + "expression": "profile_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_hacker_attendee\".\"profile_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_profile_idx": { + "name": "knight_hacks_hacker_attendee_profile_idx", + "columns": [ + { + "expression": "profile_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_profile_revision_idx": { + "name": "knight_hacks_hacker_attendee_profile_revision_idx", + "columns": [ + { + "expression": "profile_revision_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_hackathon_status_idx": { + "name": "knight_hacks_hacker_attendee_hackathon_status_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_blacklisted_by_idx": { + "name": "knight_hacks_hacker_attendee_blacklisted_by_idx", + "columns": [ + { + "expression": "blacklisted_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_attendee_last_status_send_idx": { + "name": "knight_hacks_hacker_attendee_last_status_send_idx", + "columns": [ + { + "expression": "last_status_send_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_attendee_hacker_id_knight_hacks_hacker_id_fk": { + "name": "knight_hacks_hacker_attendee_hacker_id_knight_hacks_hacker_id_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "knight_hacks_hacker", + "columnsFrom": ["hacker_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_profile_id_knight_hacks_hacker_profile_id_fk": { + "name": "knight_hacks_hacker_attendee_profile_id_knight_hacks_hacker_profile_id_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "knight_hacks_hacker_profile", + "columnsFrom": ["profile_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hacker_attendee_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_checked_in_by_auth_user_id_fk": { + "name": "knight_hacks_hacker_attendee_checked_in_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "auth_user", + "columnsFrom": ["checked_in_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_blacklisted_by_auth_user_id_fk": { + "name": "knight_hacks_hacker_attendee_blacklisted_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "auth_user", + "columnsFrom": ["blacklisted_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_last_status_send_id_email_send_id_fk": { + "name": "knight_hacks_hacker_attendee_last_status_send_id_email_send_id_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "email_send", + "columnsFrom": ["last_status_send_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_scoped_class_fk": { + "name": "knight_hacks_hacker_attendee_scoped_class_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "knight_hacks_hackathon_class", + "columnsFrom": ["class_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_hacker_attendee_scoped_profile_revision_fk": { + "name": "knight_hacks_hacker_attendee_scoped_profile_revision_fk", + "tableFrom": "knight_hacks_hacker_attendee", + "tableTo": "knight_hacks_hacker_profile_revision", + "columnsFrom": ["profile_revision_id", "profile_id"], + "columnsTo": ["id", "profile_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_attendee_hacker_hackathon_unique": { + "name": "knight_hacks_hacker_attendee_hacker_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["hacker_id", "hackathon_id"] + }, + "knight_hacks_hacker_attendee_id_hackathon_unique": { + "name": "knight_hacks_hacker_attendee_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_attendee_blacklist_reason_check": { + "name": "knight_hacks_hacker_attendee_blacklist_reason_check", + "value": "(\"knight_hacks_hacker_attendee\".\"blacklisted_at\" is null and \"knight_hacks_hacker_attendee\".\"blacklist_reason\" is null)\n or (\"knight_hacks_hacker_attendee\".\"blacklisted_at\" is not null and \"knight_hacks_hacker_attendee\".\"blacklist_reason\" is not null)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_check_in_attempt": { + "name": "knight_hacks_hacker_check_in_attempt", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hacker_attendee_id": { + "name": "hacker_attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "attendance_id": { + "name": "attendance_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "operator_id": { + "name": "operator_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "operator_display_name_snapshot": { + "name": "operator_display_name_snapshot", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "mode": { + "name": "mode", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "outcome": { + "name": "outcome", + "type": "hacker_check_in_outcome", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "event_purpose": { + "name": "event_purpose", + "type": "event_purpose", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "event_name_snapshot": { + "name": "event_name_snapshot", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "hacker_name_snapshot": { + "name": "hacker_name_snapshot", + "type": "varchar(511)", + "primaryKey": false, + "notNull": false + }, + "class_id": { + "name": "class_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "class_name_snapshot": { + "name": "class_name_snapshot", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "class_color_snapshot": { + "name": "class_color_snapshot", + "type": "varchar(7)", + "primaryKey": false, + "notNull": false + }, + "is_vip_snapshot": { + "name": "is_vip_snapshot", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "was_minor_at_attempt": { + "name": "was_minor_at_attempt", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "is_repeat_occurrence": { + "name": "is_repeat_occurrence", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "points_awarded": { + "name": "points_awarded", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "attempted_at": { + "name": "attempted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hacker_check_in_attempt_hackathon_history_idx": { + "name": "knight_hacks_hacker_check_in_attempt_hackathon_history_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "attempted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_check_in_attempt_attendee_history_idx": { + "name": "knight_hacks_hacker_check_in_attempt_attendee_history_idx", + "columns": [ + { + "expression": "hacker_attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "attempted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_check_in_attempt_expiring_idx": { + "name": "knight_hacks_hacker_check_in_attempt_expiring_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knight_hacks_hacker_check_in_attempt\".\"expires_at\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_check_in_attempt_operator_id_auth_user_id_fk": { + "name": "knight_hacks_hacker_check_in_attempt_operator_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_check_in_attempt", + "tableTo": "auth_user", + "columnsFrom": ["operator_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_check_in_attempt_scoped_attendee_fk": { + "name": "knight_hacks_hacker_check_in_attempt_scoped_attendee_fk", + "tableFrom": "knight_hacks_hacker_check_in_attempt", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["hacker_attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_check_in_attempt_scoped_attendance_fk": { + "name": "knight_hacks_hacker_check_in_attempt_scoped_attendance_fk", + "tableFrom": "knight_hacks_hacker_check_in_attempt", + "tableTo": "knight_hacks_hacker_event_attendee", + "columnsFrom": [ + "attendance_id", + "hackathon_id", + "event_id", + "hacker_attendee_id" + ], + "columnsTo": ["id", "hackathon_id", "event_id", "hacker_att_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_check_in_attempt_scoped_class_fk": { + "name": "knight_hacks_hacker_check_in_attempt_scoped_class_fk", + "tableFrom": "knight_hacks_hacker_check_in_attempt", + "tableTo": "knight_hacks_hackathon_class", + "columnsFrom": ["class_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_hacker_check_in_attempt_scoped_event_fk": { + "name": "knight_hacks_hacker_check_in_attempt_scoped_event_fk", + "tableFrom": "knight_hacks_hacker_check_in_attempt", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_check_in_attempt_attendanceId_unique": { + "name": "knight_hacks_hacker_check_in_attempt_attendanceId_unique", + "nullsNotDistinct": false, + "columns": ["attendance_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_check_in_attempt_mode_check": { + "name": "knight_hacks_hacker_check_in_attempt_mode_check", + "value": "\"knight_hacks_hacker_check_in_attempt\".\"mode\" IN ('scanner', 'manual')" + }, + "knight_hacks_hacker_check_in_attempt_class_color_check": { + "name": "knight_hacks_hacker_check_in_attempt_class_color_check", + "value": "\"knight_hacks_hacker_check_in_attempt\".\"class_color_snapshot\" IS NULL OR \"knight_hacks_hacker_check_in_attempt\".\"class_color_snapshot\" ~ '^#[0-9A-Fa-f]{6}$'" + }, + "knight_hacks_hacker_check_in_attempt_points_check": { + "name": "knight_hacks_hacker_check_in_attempt_points_check", + "value": "\"knight_hacks_hacker_check_in_attempt\".\"points_awarded\" >= 0" + }, + "knight_hacks_hacker_check_in_attempt_success_retention_check": { + "name": "knight_hacks_hacker_check_in_attempt_success_retention_check", + "value": "(\"knight_hacks_hacker_check_in_attempt\".\"outcome\" = 'checked_in' AND \"knight_hacks_hacker_check_in_attempt\".\"attendance_id\" IS NOT NULL AND \"knight_hacks_hacker_check_in_attempt\".\"expires_at\" IS NULL) OR (\"knight_hacks_hacker_check_in_attempt\".\"outcome\" <> 'checked_in' AND \"knight_hacks_hacker_check_in_attempt\".\"attendance_id\" IS NULL AND \"knight_hacks_hacker_check_in_attempt\".\"expires_at\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_check_in_pass": { + "name": "knight_hacks_hacker_check_in_pass", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "attendee_id": { + "name": "attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "issued_at": { + "name": "issued_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hacker_check_in_pass_active_attendee_unique": { + "name": "knight_hacks_hacker_check_in_pass_active_attendee_unique", + "columns": [ + { + "expression": "attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_hacker_check_in_pass\".\"revoked_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_check_in_pass_attendee_idx": { + "name": "knight_hacks_hacker_check_in_pass_attendee_idx", + "columns": [ + { + "expression": "attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_check_in_pass_scoped_attendee_fk": { + "name": "knight_hacks_hacker_check_in_pass_scoped_attendee_fk", + "tableFrom": "knight_hacks_hacker_check_in_pass", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_check_in_pass_token_hash_unique": { + "name": "knight_hacks_hacker_check_in_pass_token_hash_unique", + "nullsNotDistinct": false, + "columns": ["token_hash"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_check_in_pass_token_hash_check": { + "name": "knight_hacks_hacker_check_in_pass_token_hash_check", + "value": "\"knight_hacks_hacker_check_in_pass\".\"token_hash\" ~ '^[0-9a-f]{64}$'" + }, + "knight_hacks_hacker_check_in_pass_version_check": { + "name": "knight_hacks_hacker_check_in_pass_version_check", + "value": "\"knight_hacks_hacker_check_in_pass\".\"version\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_discord_role_grant": { + "name": "knight_hacks_hacker_discord_role_grant", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hacker_attendee_id": { + "name": "hacker_attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "source_attendance_id": { + "name": "source_attendance_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "source_event_id": { + "name": "source_event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "hacker_discord_role_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "desired_role_id": { + "name": "desired_role_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "hacker_discord_role_grant_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempt_count": { + "name": "attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_attempt_at": { + "name": "last_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "succeeded_at": { + "name": "succeeded_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "last_error": { + "name": "last_error", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "lease_token": { + "name": "lease_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_hacker_discord_role_grant_repair_queue_idx": { + "name": "knight_hacks_hacker_discord_role_grant_repair_queue_idx", + "columns": [ + { + "expression": "state", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lease_expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_discord_role_grant_scoped_attendee_fk": { + "name": "knight_hacks_hacker_discord_role_grant_scoped_attendee_fk", + "tableFrom": "knight_hacks_hacker_discord_role_grant", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["hacker_attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_discord_role_grant_scoped_attendance_fk": { + "name": "knight_hacks_hacker_discord_role_grant_scoped_attendance_fk", + "tableFrom": "knight_hacks_hacker_discord_role_grant", + "tableTo": "knight_hacks_hacker_event_attendee", + "columnsFrom": [ + "source_attendance_id", + "hackathon_id", + "source_event_id", + "hacker_attendee_id" + ], + "columnsTo": ["id", "hackathon_id", "event_id", "hacker_att_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_discord_role_grant_logical_unique": { + "name": "knight_hacks_hacker_discord_role_grant_logical_unique", + "nullsNotDistinct": false, + "columns": ["hacker_attendee_id", "kind"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_discord_role_grant_role_id_check": { + "name": "knight_hacks_hacker_discord_role_grant_role_id_check", + "value": "\"knight_hacks_hacker_discord_role_grant\".\"desired_role_id\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hacker_discord_role_grant_attempt_count_check": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_count_check", + "value": "\"knight_hacks_hacker_discord_role_grant\".\"attempt_count\" >= 0" + }, + "knight_hacks_hacker_discord_role_grant_lease_pair_check": { + "name": "knight_hacks_hacker_discord_role_grant_lease_pair_check", + "value": "(\"knight_hacks_hacker_discord_role_grant\".\"lease_token\" IS NULL) = (\"knight_hacks_hacker_discord_role_grant\".\"lease_expires_at\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_discord_role_grant_attempt": { + "name": "knight_hacks_hacker_discord_role_grant_attempt", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "grant_id": { + "name": "grant_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "attempt_token": { + "name": "attempt_token", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role_id_snapshot": { + "name": "role_id_snapshot", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "discord_user_id_snapshot": { + "name": "discord_user_id_snapshot", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true + }, + "attempted_by": { + "name": "attempted_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "outcome": { + "name": "outcome", + "type": "hacker_discord_role_attempt_outcome", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "error": { + "name": "error", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "finished_at": { + "name": "finished_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hacker_discord_role_grant_attempt_history_idx": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_history_idx", + "columns": [ + { + "expression": "grant_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "started_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_discord_role_grant_attempt_grant_id_knight_hacks_hacker_discord_role_grant_id_fk": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_grant_id_knight_hacks_hacker_discord_role_grant_id_fk", + "tableFrom": "knight_hacks_hacker_discord_role_grant_attempt", + "tableTo": "knight_hacks_hacker_discord_role_grant", + "columnsFrom": ["grant_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_discord_role_grant_attempt_attempted_by_auth_user_id_fk": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_attempted_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_discord_role_grant_attempt", + "tableTo": "auth_user", + "columnsFrom": ["attempted_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_discord_role_grant_attempt_attemptToken_unique": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_attemptToken_unique", + "nullsNotDistinct": false, + "columns": ["attempt_token"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_discord_role_grant_attempt_role_id_check": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_role_id_check", + "value": "\"knight_hacks_hacker_discord_role_grant_attempt\".\"role_id_snapshot\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hacker_discord_role_grant_attempt_user_id_check": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_user_id_check", + "value": "\"knight_hacks_hacker_discord_role_grant_attempt\".\"discord_user_id_snapshot\" ~ '^[0-9]{17,20}$'" + }, + "knight_hacks_hacker_discord_role_grant_attempt_completion_check": { + "name": "knight_hacks_hacker_discord_role_grant_attempt_completion_check", + "value": "(\"knight_hacks_hacker_discord_role_grant_attempt\".\"outcome\" = 'pending' AND \"knight_hacks_hacker_discord_role_grant_attempt\".\"finished_at\" IS NULL) OR (\"knight_hacks_hacker_discord_role_grant_attempt\".\"outcome\" <> 'pending' AND \"knight_hacks_hacker_discord_role_grant_attempt\".\"finished_at\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_event_attendee": { + "name": "knight_hacks_hacker_event_attendee", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hacker_att_id": { + "name": "hacker_att_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "event_id": { + "name": "event_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "checked_in_at": { + "name": "checked_in_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "checked_in_by": { + "name": "checked_in_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "points_awarded": { + "name": "points_awarded", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "is_initial_attendance": { + "name": "is_initial_attendance", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "voided_at": { + "name": "voided_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "voided_by": { + "name": "voided_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "void_reason": { + "name": "void_reason", + "type": "varchar(300)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hacker_event_attendee_event_attendee_history_idx": { + "name": "knight_hacks_hacker_event_attendee_event_attendee_history_idx", + "columns": [ + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "hacker_att_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "checked_in_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_event_attendee_attendee_event_history_idx": { + "name": "knight_hacks_hacker_event_attendee_attendee_event_history_idx", + "columns": [ + { + "expression": "hacker_att_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "checked_in_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_event_attendee_hackathon_history_idx": { + "name": "knight_hacks_hacker_event_attendee_hackathon_history_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "checked_in_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_event_attendee_checked_in_by_idx": { + "name": "knight_hacks_hacker_event_attendee_checked_in_by_idx", + "columns": [ + { + "expression": "checked_in_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_event_attendee_voided_by_idx": { + "name": "knight_hacks_hacker_event_attendee_voided_by_idx", + "columns": [ + { + "expression": "voided_by", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_hacker_event_attendee_one_active_initial": { + "name": "knight_hacks_hacker_event_attendee_one_active_initial", + "columns": [ + { + "expression": "event_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "hacker_att_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_hacker_event_attendee\".\"is_initial_attendance\" = true AND \"knight_hacks_hacker_event_attendee\".\"voided_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_event_attendee_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hacker_event_attendee_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hacker_event_attendee", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_event_attendee_checked_in_by_auth_user_id_fk": { + "name": "knight_hacks_hacker_event_attendee_checked_in_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_event_attendee", + "tableTo": "auth_user", + "columnsFrom": ["checked_in_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_event_attendee_voided_by_auth_user_id_fk": { + "name": "knight_hacks_hacker_event_attendee_voided_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_event_attendee", + "tableTo": "auth_user", + "columnsFrom": ["voided_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_event_attendee_scoped_attendee_fk": { + "name": "knight_hacks_hacker_event_attendee_scoped_attendee_fk", + "tableFrom": "knight_hacks_hacker_event_attendee", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["hacker_att_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_event_attendee_scoped_event_fk": { + "name": "knight_hacks_hacker_event_attendee_scoped_event_fk", + "tableFrom": "knight_hacks_hacker_event_attendee", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_event_attendee_attempt_scope_unique": { + "name": "knight_hacks_hacker_event_attendee_attempt_scope_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id", "event_id", "hacker_att_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_event_attendee_points_awarded_check": { + "name": "knight_hacks_hacker_event_attendee_points_awarded_check", + "value": "\"knight_hacks_hacker_event_attendee\".\"points_awarded\" IS NULL OR \"knight_hacks_hacker_event_attendee\".\"points_awarded\" >= 0" + }, + "knight_hacks_hacker_event_attendee_void_metadata_check": { + "name": "knight_hacks_hacker_event_attendee_void_metadata_check", + "value": "(\"knight_hacks_hacker_event_attendee\".\"voided_at\" IS NULL AND \"knight_hacks_hacker_event_attendee\".\"void_reason\" IS NULL) OR (\"knight_hacks_hacker_event_attendee\".\"voided_at\" IS NOT NULL AND \"knight_hacks_hacker_event_attendee\".\"void_reason\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_participant_command": { + "name": "knight_hacks_hacker_participant_command", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "operation": { + "name": "operation", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "idempotency_key": { + "name": "idempotency_key", + "type": "varchar(128)", + "primaryKey": false, + "notNull": true + }, + "payload_hash": { + "name": "payload_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "state": { + "name": "state", + "type": "hacker_participant_command_state", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'started'" + }, + "result": { + "name": "result", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "safe_error_code": { + "name": "safe_error_code", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "started_at": { + "name": "started_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "completed_at": { + "name": "completed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "knight_hacks_hacker_participant_command_expiry_idx": { + "name": "knight_hacks_hacker_participant_command_expiry_idx", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_participant_command_user_id_auth_user_id_fk": { + "name": "knight_hacks_hacker_participant_command_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_participant_command", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_participant_command_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hacker_participant_command_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hacker_participant_command", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_participant_command_identity_unique": { + "name": "knight_hacks_hacker_participant_command_identity_unique", + "nullsNotDistinct": false, + "columns": ["user_id", "hackathon_id", "operation", "idempotency_key"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_participant_command_payload_hash_check": { + "name": "knight_hacks_hacker_participant_command_payload_hash_check", + "value": "\"knight_hacks_hacker_participant_command\".\"payload_hash\" ~ '^[0-9a-f]{64}$'" + }, + "knight_hacks_hacker_participant_command_completion_check": { + "name": "knight_hacks_hacker_participant_command_completion_check", + "value": "(\"knight_hacks_hacker_participant_command\".\"state\" = 'started' AND \"knight_hacks_hacker_participant_command\".\"completed_at\" IS NULL) OR (\"knight_hacks_hacker_participant_command\".\"state\" <> 'started' AND \"knight_hacks_hacker_participant_command\".\"completed_at\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_profile": { + "name": "knight_hacks_hacker_profile", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "gender": { + "name": "gender", + "type": "gender", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "discord_user": { + "name": "discord_user", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "phone_number": { + "name": "phone_number", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "school": { + "name": "school", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level_of_study": { + "name": "level_of_study", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "major": { + "name": "major", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "race_or_ethnicity": { + "name": "race_or_ethnicity", + "type": "race_or_ethnicity", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "shirt_size": { + "name": "shirt_size", + "type": "shirt_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "github_profile_url": { + "name": "github_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "linkedin_profile_url": { + "name": "linkedin_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "website_url": { + "name": "website_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resume_url": { + "name": "resume_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "dob": { + "name": "dob", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "grad_date": { + "name": "grad_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "food_allergies": { + "name": "food_allergies", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_hacker_profile_user_id_auth_user_id_fk": { + "name": "knight_hacks_hacker_profile_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_profile", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_profile_user_unique": { + "name": "knight_hacks_hacker_profile_user_unique", + "nullsNotDistinct": false, + "columns": ["user_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_profile_revision_check": { + "name": "knight_hacks_hacker_profile_revision_check", + "value": "\"knight_hacks_hacker_profile\".\"revision\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_profile_revision": { + "name": "knight_hacks_hacker_profile_revision", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "profile_id": { + "name": "profile_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "legacy_hacker_id": { + "name": "legacy_hacker_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "gender": { + "name": "gender", + "type": "gender", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "discord_user": { + "name": "discord_user", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "country": { + "name": "country", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "phone_number": { + "name": "phone_number", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "school": { + "name": "school", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level_of_study": { + "name": "level_of_study", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "major": { + "name": "major", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "race_or_ethnicity": { + "name": "race_or_ethnicity", + "type": "race_or_ethnicity", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "shirt_size": { + "name": "shirt_size", + "type": "shirt_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "github_profile_url": { + "name": "github_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "linkedin_profile_url": { + "name": "linkedin_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "website_url": { + "name": "website_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resume_url": { + "name": "resume_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "dob": { + "name": "dob", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "grad_date": { + "name": "grad_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "food_allergies": { + "name": "food_allergies", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_by": { + "name": "created_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_hacker_profile_revision_profile_created_idx": { + "name": "knight_hacks_hacker_profile_revision_profile_created_idx", + "columns": [ + { + "expression": "profile_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_profile_revision_profile_id_knight_hacks_hacker_profile_id_fk": { + "name": "knight_hacks_hacker_profile_revision_profile_id_knight_hacks_hacker_profile_id_fk", + "tableFrom": "knight_hacks_hacker_profile_revision", + "tableTo": "knight_hacks_hacker_profile", + "columnsFrom": ["profile_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_hacker_profile_revision_legacy_hacker_id_knight_hacks_hacker_id_fk": { + "name": "knight_hacks_hacker_profile_revision_legacy_hacker_id_knight_hacks_hacker_id_fk", + "tableFrom": "knight_hacks_hacker_profile_revision", + "tableTo": "knight_hacks_hacker", + "columnsFrom": ["legacy_hacker_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_hacker_profile_revision_created_by_auth_user_id_fk": { + "name": "knight_hacks_hacker_profile_revision_created_by_auth_user_id_fk", + "tableFrom": "knight_hacks_hacker_profile_revision", + "tableTo": "auth_user", + "columnsFrom": ["created_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_hacker_profile_revision_legacyHackerId_unique": { + "name": "knight_hacks_hacker_profile_revision_legacyHackerId_unique", + "nullsNotDistinct": false, + "columns": ["legacy_hacker_id"] + }, + "knight_hacks_hacker_profile_revision_profile_version_unique": { + "name": "knight_hacks_hacker_profile_revision_profile_version_unique", + "nullsNotDistinct": false, + "columns": ["profile_id", "revision"] + }, + "knight_hacks_hacker_profile_revision_id_profile_unique": { + "name": "knight_hacks_hacker_profile_revision_id_profile_unique", + "nullsNotDistinct": false, + "columns": ["id", "profile_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_hacker_profile_revision_version_check": { + "name": "knight_hacks_hacker_profile_revision_version_check", + "value": "\"knight_hacks_hacker_profile_revision\".\"revision\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_team": { + "name": "knight_hacks_hacker_team", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "together": { + "name": "together", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "frozen_at": { + "name": "frozen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "class_id": { + "name": "class_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "hacker_team_hackathon_idx": { + "name": "hacker_team_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "hacker_team_class_idx": { + "name": "hacker_team_class_idx", + "columns": [ + { + "expression": "class_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_hacker_team_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_hacker_team_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_hacker_team", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "hacker_team_scoped_class_fk": { + "name": "hacker_team_scoped_class_fk", + "tableFrom": "knight_hacks_hacker_team", + "tableTo": "knight_hacks_hackathon_class", + "columnsFrom": ["class_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "hacker_team_id_hackathon_unique": { + "name": "hacker_team_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "hacker_team_name_required": { + "name": "hacker_team_name_required", + "value": "length(trim(\"knight_hacks_hacker_team\".\"name\")) > 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_hacker_team_member": { + "name": "knight_hacks_hacker_team_member", + "schema": "", + "columns": { + "attendee_id": { + "name": "attendee_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "hacker_team_member_team_idx": { + "name": "hacker_team_member_team_idx", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "hacker_team_member_hackathon_idx": { + "name": "hacker_team_member_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "hacker_team_one_owner": { + "name": "hacker_team_one_owner", + "columns": [ + { + "expression": "team_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_hacker_team_member\".\"role\" = 'owner'", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "hacker_team_member_scoped_team_fk": { + "name": "hacker_team_member_scoped_team_fk", + "tableFrom": "knight_hacks_hacker_team_member", + "tableTo": "knight_hacks_hacker_team", + "columnsFrom": ["team_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "hacker_team_member_scoped_attendee_fk": { + "name": "hacker_team_member_scoped_attendee_fk", + "tableFrom": "knight_hacks_hacker_team_member", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "hacker_team_member_role_valid": { + "name": "hacker_team_member_role_valid", + "value": "\"knight_hacks_hacker_team_member\".\"role\" in ('pending', 'member', 'owner')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_issue": { + "name": "knight_hacks_issue", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "status": { + "name": "status", + "type": "issue_status", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "links": { + "name": "links", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "event": { + "name": "event", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "discord_thread_id": { + "name": "discord_thread_id", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "date": { + "name": "date", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "due_at": { + "name": "due_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "priority": { + "name": "priority", + "type": "issue_priority", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "team": { + "name": "team", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "creator": { + "name": "creator", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "parent": { + "name": "parent", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "archived_by": { + "name": "archived_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "archive_batch_id": { + "name": "archive_batch_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "creation_key": { + "name": "creation_key", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "creation_hash": { + "name": "creation_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "issue_team_idx": { + "name": "issue_team_idx", + "columns": [ + { + "expression": "team", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_creator_idx": { + "name": "issue_creator_idx", + "columns": [ + { + "expression": "creator", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_status_idx": { + "name": "issue_status_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_date_idx": { + "name": "issue_date_idx", + "columns": [ + { + "expression": "date", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_due_at_idx": { + "name": "issue_due_at_idx", + "columns": [ + { + "expression": "due_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_archive_idx": { + "name": "issue_archive_idx", + "columns": [ + { + "expression": "archived_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "archive_batch_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_parent_idx": { + "name": "issue_parent_idx", + "columns": [ + { + "expression": "parent", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "issue_priority_idx": { + "name": "issue_priority_idx", + "columns": [ + { + "expression": "priority", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_issue_event_knight_hacks_event_id_fk": { + "name": "knight_hacks_issue_event_knight_hacks_event_id_fk", + "tableFrom": "knight_hacks_issue", + "tableTo": "knight_hacks_event", + "columnsFrom": ["event"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_issue_team_auth_roles_id_fk": { + "name": "knight_hacks_issue_team_auth_roles_id_fk", + "tableFrom": "knight_hacks_issue", + "tableTo": "auth_roles", + "columnsFrom": ["team"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_issue_creator_auth_user_id_fk": { + "name": "knight_hacks_issue_creator_auth_user_id_fk", + "tableFrom": "knight_hacks_issue", + "tableTo": "auth_user", + "columnsFrom": ["creator"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_issue_archived_by_auth_user_id_fk": { + "name": "knight_hacks_issue_archived_by_auth_user_id_fk", + "tableFrom": "knight_hacks_issue", + "tableTo": "auth_user", + "columnsFrom": ["archived_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "issue_parent_fk": { + "name": "issue_parent_fk", + "tableFrom": "knight_hacks_issue", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["parent"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_issue_creation_key_unique": { + "name": "knight_hacks_issue_creation_key_unique", + "nullsNotDistinct": false, + "columns": ["creation_key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_issue_attachment": { + "name": "knight_hacks_issue_attachment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "issue_id": { + "name": "issue_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "draft_key": { + "name": "draft_key", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "object_name": { + "name": "object_name", + "type": "varchar(512)", + "primaryKey": false, + "notNull": true + }, + "file_name": { + "name": "file_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "finalized_at": { + "name": "finalized_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_issue_attachment_issue_idx": { + "name": "knight_hacks_issue_attachment_issue_idx", + "columns": [ + { + "expression": "issue_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_issue_attachment_draft_idx": { + "name": "knight_hacks_issue_attachment_draft_idx", + "columns": [ + { + "expression": "draft_key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_issue_attachment_issue_id_knight_hacks_issue_id_fk": { + "name": "knight_hacks_issue_attachment_issue_id_knight_hacks_issue_id_fk", + "tableFrom": "knight_hacks_issue_attachment", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["issue_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_issue_attachment_team_id_auth_roles_id_fk": { + "name": "knight_hacks_issue_attachment_team_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_issue_attachment", + "tableTo": "auth_roles", + "columnsFrom": ["team_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_issue_attachment_owner_user_id_auth_user_id_fk": { + "name": "knight_hacks_issue_attachment_owner_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_issue_attachment", + "tableTo": "auth_user", + "columnsFrom": ["owner_user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_issue_attachment_objectName_unique": { + "name": "knight_hacks_issue_attachment_objectName_unique", + "nullsNotDistinct": false, + "columns": ["object_name"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_issue_attachment_owner_check": { + "name": "knight_hacks_issue_attachment_owner_check", + "value": "NOT (\"knight_hacks_issue_attachment\".\"issue_id\" IS NOT NULL AND \"knight_hacks_issue_attachment\".\"draft_key\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_issue_attachment_reference": { + "name": "knight_hacks_issue_attachment_reference", + "schema": "", + "columns": { + "attachment_id": { + "name": "attachment_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "issue_id": { + "name": "issue_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "issue_attachment_reference_issue_idx": { + "name": "issue_attachment_reference_issue_idx", + "columns": [ + { + "expression": "issue_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_issue_attachment_reference_attachment_id_knight_hacks_issue_attachment_id_fk": { + "name": "knight_hacks_issue_attachment_reference_attachment_id_knight_hacks_issue_attachment_id_fk", + "tableFrom": "knight_hacks_issue_attachment_reference", + "tableTo": "knight_hacks_issue_attachment", + "columnsFrom": ["attachment_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_issue_attachment_reference_issue_id_knight_hacks_issue_id_fk": { + "name": "knight_hacks_issue_attachment_reference_issue_id_knight_hacks_issue_id_fk", + "tableFrom": "knight_hacks_issue_attachment_reference", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["issue_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_issue_attachment_reference_attachment_id_issue_id_pk": { + "name": "knight_hacks_issue_attachment_reference_attachment_id_issue_id_pk", + "columns": ["attachment_id", "issue_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_issue_history": { + "name": "knight_hacks_issue_history", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "issue_id": { + "name": "issue_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_display_name": { + "name": "actor_display_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "changed_fields": { + "name": "changed_fields", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "before": { + "name": "before", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "after": { + "name": "after", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "issue_history_issue_created_idx": { + "name": "issue_history_issue_created_idx", + "columns": [ + { + "expression": "issue_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_issue_history_issue_id_knight_hacks_issue_id_fk": { + "name": "knight_hacks_issue_history_issue_id_knight_hacks_issue_id_fk", + "tableFrom": "knight_hacks_issue_history", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["issue_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_issue_history_actor_id_auth_user_id_fk": { + "name": "knight_hacks_issue_history_actor_id_auth_user_id_fk", + "tableFrom": "knight_hacks_issue_history", + "tableTo": "auth_user", + "columnsFrom": ["actor_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_issue_reminder_delivery": { + "name": "knight_hacks_issue_reminder_delivery", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "issue_id": { + "name": "issue_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "due_at": { + "name": "due_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "reminder_key": { + "name": "reminder_key", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "destination_snapshot": { + "name": "destination_snapshot", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "content_snapshot": { + "name": "content_snapshot", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "varchar(24)", + "primaryKey": false, + "notNull": true, + "default": "'pending'" + }, + "attempt_count": { + "name": "attempt_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "locked_at": { + "name": "locked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "delivered_at": { + "name": "delivered_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "next_attempt_at": { + "name": "next_attempt_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "issue_reminder_delivery_pending_idx": { + "name": "issue_reminder_delivery_pending_idx", + "columns": [ + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "next_attempt_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_issue_reminder_delivery_issue_id_knight_hacks_issue_id_fk": { + "name": "knight_hacks_issue_reminder_delivery_issue_id_knight_hacks_issue_id_fk", + "tableFrom": "knight_hacks_issue_reminder_delivery", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["issue_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "issue_reminder_delivery_identity_unique": { + "name": "issue_reminder_delivery_identity_unique", + "nullsNotDistinct": false, + "columns": ["issue_id", "due_at", "reminder_key"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_issues_to_teams_visibility": { + "name": "knight_hacks_issues_to_teams_visibility", + "schema": "", + "columns": { + "issue_id": { + "name": "issue_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "team_id": { + "name": "team_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_issues_to_teams_visibility_issue_id_knight_hacks_issue_id_fk": { + "name": "knight_hacks_issues_to_teams_visibility_issue_id_knight_hacks_issue_id_fk", + "tableFrom": "knight_hacks_issues_to_teams_visibility", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["issue_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_issues_to_teams_visibility_team_id_auth_roles_id_fk": { + "name": "knight_hacks_issues_to_teams_visibility_team_id_auth_roles_id_fk", + "tableFrom": "knight_hacks_issues_to_teams_visibility", + "tableTo": "auth_roles", + "columnsFrom": ["team_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_issues_to_teams_visibility_issue_id_team_id_pk": { + "name": "knight_hacks_issues_to_teams_visibility_issue_id_team_id_pk", + "columns": ["issue_id", "team_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_issues_to_users_assignment": { + "name": "knight_hacks_issues_to_users_assignment", + "schema": "", + "columns": { + "issue_id": { + "name": "issue_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_issues_to_users_assignment_issue_id_knight_hacks_issue_id_fk": { + "name": "knight_hacks_issues_to_users_assignment_issue_id_knight_hacks_issue_id_fk", + "tableFrom": "knight_hacks_issues_to_users_assignment", + "tableTo": "knight_hacks_issue", + "columnsFrom": ["issue_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_issues_to_users_assignment_user_id_auth_user_id_fk": { + "name": "knight_hacks_issues_to_users_assignment_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_issues_to_users_assignment", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_issues_to_users_assignment_issue_id_user_id_pk": { + "name": "knight_hacks_issues_to_users_assignment_issue_id_user_id_pk", + "columns": ["issue_id", "user_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_judge": { + "name": "knight_hacks_judge", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "judge_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "display_name": { + "name": "display_name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_judge_member_unique": { + "name": "knight_hacks_judge_member_unique", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judge\".\"user_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judge_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_judge_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_judge", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judge_user_id_auth_user_id_fk": { + "name": "knight_hacks_judge_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judge", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judge_id_hackathon_unique": { + "name": "knight_hacks_judge_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_judge_kind_identity_check": { + "name": "knight_hacks_judge_kind_identity_check", + "value": "\"knight_hacks_judge\".\"kind\" = 'member' OR (\"knight_hacks_judge\".\"kind\" = 'guest' AND \"knight_hacks_judge\".\"user_id\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judge_deliberation_entry": { + "name": "knight_hacks_judge_deliberation_entry", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "section_id": { + "name": "section_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_judge_deliberation_entry_section_scope_fk": { + "name": "knight_hacks_judge_deliberation_entry_section_scope_fk", + "tableFrom": "knight_hacks_judge_deliberation_entry", + "tableTo": "knight_hacks_judge_deliberation_section", + "columnsFrom": ["section_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judge_deliberation_entry_project_scope_fk": { + "name": "knight_hacks_judge_deliberation_entry_project_scope_fk", + "tableFrom": "knight_hacks_judge_deliberation_entry", + "tableTo": "knight_hacks_project", + "columnsFrom": ["project_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judge_deliberation_entry_section_project_unique": { + "name": "knight_hacks_judge_deliberation_entry_section_project_unique", + "nullsNotDistinct": false, + "columns": ["section_id", "project_id"] + }, + "knight_hacks_judge_deliberation_entry_section_order_unique": { + "name": "knight_hacks_judge_deliberation_entry_section_order_unique", + "nullsNotDistinct": false, + "columns": ["section_id", "display_order"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_judge_deliberation_entry_order_check": { + "name": "knight_hacks_judge_deliberation_entry_order_check", + "value": "\"knight_hacks_judge_deliberation_entry\".\"display_order\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judge_deliberation_section": { + "name": "knight_hacks_judge_deliberation_section", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "judge_id": { + "name": "judge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(80)", + "primaryKey": false, + "notNull": true + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_judge_deliberation_section_judge_scope_fk": { + "name": "knight_hacks_judge_deliberation_section_judge_scope_fk", + "tableFrom": "knight_hacks_judge_deliberation_section", + "tableTo": "knight_hacks_judge", + "columnsFrom": ["judge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judge_deliberation_section_judge_order_unique": { + "name": "knight_hacks_judge_deliberation_section_judge_order_unique", + "nullsNotDistinct": false, + "columns": ["judge_id", "display_order"] + }, + "knight_hacks_judge_deliberation_section_id_hackathon_unique": { + "name": "knight_hacks_judge_deliberation_section_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_judge_deliberation_section_order_check": { + "name": "knight_hacks_judge_deliberation_section_order_check", + "value": "\"knight_hacks_judge_deliberation_section\".\"display_order\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_announcement": { + "name": "knight_hacks_judging_announcement", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "room_id": { + "name": "room_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "message": { + "name": "message", + "type": "varchar(1000)", + "primaryKey": false, + "notNull": true + }, + "include_guests": { + "name": "include_guests", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_urgent": { + "name": "is_urgent", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "published_by_user_id": { + "name": "published_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "published_at": { + "name": "published_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "cleared_at": { + "name": "cleared_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "cleared_by_user_id": { + "name": "cleared_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_judging_announcement_current_global_unique": { + "name": "knight_hacks_judging_announcement_current_global_unique", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judging_announcement\".\"room_id\" IS NULL AND \"knight_hacks_judging_announcement\".\"cleared_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_judging_announcement_current_room_unique": { + "name": "knight_hacks_judging_announcement_current_room_unique", + "columns": [ + { + "expression": "room_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judging_announcement\".\"room_id\" IS NOT NULL AND \"knight_hacks_judging_announcement\".\"cleared_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_judging_announcement_current_lookup_idx": { + "name": "knight_hacks_judging_announcement_current_lookup_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "room_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "cleared_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judging_announcement_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_judging_announcement_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_judging_announcement", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judging_announcement_published_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_announcement_published_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_announcement", + "tableTo": "auth_user", + "columnsFrom": ["published_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_judging_announcement_cleared_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_announcement_cleared_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_announcement", + "tableTo": "auth_user", + "columnsFrom": ["cleared_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_judging_announcement_room_scope_fk": { + "name": "knight_hacks_judging_announcement_room_scope_fk", + "tableFrom": "knight_hacks_judging_announcement", + "tableTo": "knight_hacks_judging_room", + "columnsFrom": ["room_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_judging_announcement_message_not_blank_check": { + "name": "knight_hacks_judging_announcement_message_not_blank_check", + "value": "\"knight_hacks_judging_announcement\".\"message\" ~ '[^[:space:]]'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_appointment": { + "name": "knight_hacks_judging_appointment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "schedule_id": { + "name": "schedule_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "challenge_id": { + "name": "challenge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "room_id": { + "name": "room_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deadline_at": { + "name": "deadline_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_judging_appointment_project_idx": { + "name": "knight_hacks_judging_appointment_project_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "starts_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judging_appointment_schedule_fk": { + "name": "knight_hacks_judging_appointment_schedule_fk", + "tableFrom": "knight_hacks_judging_appointment", + "tableTo": "knight_hacks_judging_schedule", + "columnsFrom": ["schedule_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judging_appointment_room_fk": { + "name": "knight_hacks_judging_appointment_room_fk", + "tableFrom": "knight_hacks_judging_appointment", + "tableTo": "knight_hacks_judging_room", + "columnsFrom": ["room_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_judging_appointment_project_challenge_fk": { + "name": "knight_hacks_judging_appointment_project_challenge_fk", + "tableFrom": "knight_hacks_judging_appointment", + "tableTo": "knight_hacks_project_to_challenge", + "columnsFrom": ["project_id", "challenge_id", "hackathon_id"], + "columnsTo": ["project_id", "challenge_id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judging_appointment_task_unique": { + "name": "knight_hacks_judging_appointment_task_unique", + "nullsNotDistinct": false, + "columns": ["schedule_id", "project_id", "challenge_id"] + }, + "knight_hacks_judging_appointment_room_slot_unique": { + "name": "knight_hacks_judging_appointment_room_slot_unique", + "nullsNotDistinct": false, + "columns": ["schedule_id", "room_id", "starts_at"] + }, + "knight_hacks_judging_appointment_scope_unique": { + "name": "knight_hacks_judging_appointment_scope_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_judging_appointment_times_check": { + "name": "knight_hacks_judging_appointment_times_check", + "value": "\"knight_hacks_judging_appointment\".\"starts_at\" < \"knight_hacks_judging_appointment\".\"deadline_at\" AND \"knight_hacks_judging_appointment\".\"deadline_at\" <= \"knight_hacks_judging_appointment\".\"ends_at\"" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_building": { + "name": "knight_hacks_judging_building", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(80)", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_judging_building_name_unique": { + "name": "knight_hacks_judging_building_name_unique", + "columns": [ + { + "expression": "lower(btrim(\"name\"))", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_judging_building_name_check": { + "name": "knight_hacks_judging_building_name_check", + "value": "length(btrim(\"knight_hacks_judging_building\".\"name\")) > 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_room": { + "name": "knight_hacks_judging_room", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "challenge_id": { + "name": "challenge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "building_id": { + "name": "building_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "discord_thread_id": { + "name": "discord_thread_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "archived_at": { + "name": "archived_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "archived_by_user_id": { + "name": "archived_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_judging_room_active_name_unique": { + "name": "knight_hacks_judging_room_active_name_unique", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judging_room\".\"archived_at\" IS NULL AND \"knight_hacks_judging_room\".\"building_id\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_judging_room_active_location_unique": { + "name": "knight_hacks_judging_room_active_location_unique", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "building_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "lower(btrim(\"name\"))", + "asc": true, + "isExpression": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judging_room\".\"archived_at\" IS NULL AND \"knight_hacks_judging_room\".\"building_id\" IS NOT NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_judging_room_hackathon_idx": { + "name": "knight_hacks_judging_room_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "display_order", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judging_room_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_judging_room_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_judging_room", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judging_room_building_id_knight_hacks_judging_building_id_fk": { + "name": "knight_hacks_judging_room_building_id_knight_hacks_judging_building_id_fk", + "tableFrom": "knight_hacks_judging_room", + "tableTo": "knight_hacks_judging_building", + "columnsFrom": ["building_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_judging_room_archived_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_room_archived_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_room", + "tableTo": "auth_user", + "columnsFrom": ["archived_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_judging_room_challenge_scope_fk": { + "name": "knight_hacks_judging_room_challenge_scope_fk", + "tableFrom": "knight_hacks_judging_room", + "tableTo": "knight_hacks_project_challenge", + "columnsFrom": ["challenge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judging_room_id_hackathon_unique": { + "name": "knight_hacks_judging_room_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_room_access_link": { + "name": "knight_hacks_judging_room_access_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "room_id": { + "name": "room_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "revoked_at": { + "name": "revoked_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "revoked_by_user_id": { + "name": "revoked_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "revocation_reason": { + "name": "revocation_reason", + "type": "varchar(80)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_judging_room_access_link_active_room_unique": { + "name": "knight_hacks_judging_room_access_link_active_room_unique", + "columns": [ + { + "expression": "room_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judging_room_access_link\".\"revoked_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judging_room_access_link_created_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_room_access_link_created_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_room_access_link", + "tableTo": "auth_user", + "columnsFrom": ["created_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_judging_room_access_link_revoked_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_room_access_link_revoked_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_room_access_link", + "tableTo": "auth_user", + "columnsFrom": ["revoked_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_judging_room_access_link_room_scope_fk": { + "name": "knight_hacks_judging_room_access_link_room_scope_fk", + "tableFrom": "knight_hacks_judging_room_access_link", + "tableTo": "knight_hacks_judging_room", + "columnsFrom": ["room_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judging_room_access_link_id_hackathon_unique": { + "name": "knight_hacks_judging_room_access_link_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_room_presence": { + "name": "knight_hacks_judging_room_presence", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "room_id": { + "name": "room_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "judge_id": { + "name": "judge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "joined_at": { + "name": "joined_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "last_seen_at": { + "name": "last_seen_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "left_at": { + "name": "left_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "leave_reason": { + "name": "leave_reason", + "type": "varchar(80)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_judging_room_presence_active_judge_unique": { + "name": "knight_hacks_judging_room_presence_active_judge_unique", + "columns": [ + { + "expression": "judge_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "where": "\"knight_hacks_judging_room_presence\".\"left_at\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_judging_room_presence_room_idx": { + "name": "knight_hacks_judging_room_presence_room_idx", + "columns": [ + { + "expression": "room_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "left_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judging_room_presence_room_scope_fk": { + "name": "knight_hacks_judging_room_presence_room_scope_fk", + "tableFrom": "knight_hacks_judging_room_presence", + "tableTo": "knight_hacks_judging_room", + "columnsFrom": ["room_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judging_room_presence_judge_scope_fk": { + "name": "knight_hacks_judging_room_presence_judge_scope_fk", + "tableFrom": "knight_hacks_judging_room_presence", + "tableTo": "knight_hacks_judge", + "columnsFrom": ["judge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_rubric_item": { + "name": "knight_hacks_judging_rubric_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "judging_rubric_item_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar(500)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "required": { + "name": "required", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "member_visibility_policy": { + "name": "member_visibility_policy", + "type": "judging_response_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "guest_visibility_policy": { + "name": "guest_visibility_policy", + "type": "judging_response_visibility", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_judging_rubric_item_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_judging_rubric_item_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_judging_rubric_item", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judging_rubric_item_hackathon_order_unique": { + "name": "knight_hacks_judging_rubric_item_hackathon_order_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id", "display_order"] + }, + "knight_hacks_judging_rubric_item_id_hackathon_unique": { + "name": "knight_hacks_judging_rubric_item_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_judging_rubric_item_display_order_check": { + "name": "knight_hacks_judging_rubric_item_display_order_check", + "value": "\"knight_hacks_judging_rubric_item\".\"display_order\" >= 0" + }, + "knight_hacks_judging_rubric_item_visibility_check": { + "name": "knight_hacks_judging_rubric_item_visibility_check", + "value": "(\"knight_hacks_judging_rubric_item\".\"kind\" = 'rating' AND \"knight_hacks_judging_rubric_item\".\"required\" = true AND \"knight_hacks_judging_rubric_item\".\"member_visibility_policy\" IS NULL AND \"knight_hacks_judging_rubric_item\".\"guest_visibility_policy\" IS NULL) OR (\"knight_hacks_judging_rubric_item\".\"kind\" = 'short_response' AND \"knight_hacks_judging_rubric_item\".\"member_visibility_policy\" IS NOT NULL AND \"knight_hacks_judging_rubric_item\".\"guest_visibility_policy\" IS NOT NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_schedule": { + "name": "knight_hacks_judging_schedule", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "starts_at": { + "name": "starts_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "ends_at": { + "name": "ends_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "setup_minutes": { + "name": "setup_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "judging_minutes": { + "name": "judging_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "teardown_minutes": { + "name": "teardown_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "same_building_break_minutes": { + "name": "same_building_break_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "different_building_break_minutes": { + "name": "different_building_break_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "reduced_breaks_acknowledged_at": { + "name": "reduced_breaks_acknowledged_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "first_result_at": { + "name": "first_result_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "saved_by_user_id": { + "name": "saved_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_judging_schedule_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_judging_schedule_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_judging_schedule", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judging_schedule_saved_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_schedule_saved_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_schedule", + "tableTo": "auth_user", + "columnsFrom": ["saved_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_judging_schedule_hackathon_unique": { + "name": "knight_hacks_judging_schedule_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id"] + }, + "knight_hacks_judging_schedule_scope_unique": { + "name": "knight_hacks_judging_schedule_scope_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_judging_schedule_timing_check": { + "name": "knight_hacks_judging_schedule_timing_check", + "value": "\"knight_hacks_judging_schedule\".\"ends_at\" > \"knight_hacks_judging_schedule\".\"starts_at\" AND \"knight_hacks_judging_schedule\".\"setup_minutes\" >= 0 AND \"knight_hacks_judging_schedule\".\"judging_minutes\" > 0 AND \"knight_hacks_judging_schedule\".\"teardown_minutes\" >= 0 AND \"knight_hacks_judging_schedule\".\"same_building_break_minutes\" > 0 AND \"knight_hacks_judging_schedule\".\"different_building_break_minutes\" >= \"knight_hacks_judging_schedule\".\"same_building_break_minutes\"" + }, + "knight_hacks_judging_schedule_minute_check": { + "name": "knight_hacks_judging_schedule_minute_check", + "value": "extract(second from \"knight_hacks_judging_schedule\".\"starts_at\") = 0 AND extract(second from \"knight_hacks_judging_schedule\".\"ends_at\") = 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_judging_schedule_job": { + "name": "knight_hacks_judging_schedule_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "source_fingerprint": { + "name": "source_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "timing": { + "name": "timing", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "problem": { + "name": "problem", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "checkpoint": { + "name": "checkpoint", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "varchar(24)", + "primaryKey": false, + "notNull": true, + "default": "'searching'" + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "lease_token": { + "name": "lease_token", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "lease_expires_at": { + "name": "lease_expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_judging_schedule_job_hackathon_idx": { + "name": "knight_hacks_judging_schedule_job_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_judging_schedule_job_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_judging_schedule_job_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_judging_schedule_job", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_judging_schedule_job_created_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_judging_schedule_job_created_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_judging_schedule_job", + "tableTo": "auth_user", + "columnsFrom": ["created_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_member": { + "name": "knight_hacks_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "last_name": { + "name": "last_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "discord_user": { + "name": "discord_user", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "age": { + "name": "age", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "phone_number": { + "name": "phone_number", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "school": { + "name": "school", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "level_of_study": { + "name": "level_of_study", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "major": { + "name": "major", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'Computer Science'" + }, + "gender": { + "name": "gender", + "type": "gender", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'Prefer not to answer'" + }, + "race_or_ethnicity": { + "name": "race_or_ethnicity", + "type": "race_or_ethnicity", + "typeSchema": "public", + "primaryKey": false, + "notNull": true, + "default": "'Prefer not to answer'" + }, + "guild_profile_visible": { + "name": "guild_profile_visible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "guild_resume_visible": { + "name": "guild_resume_visible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "guild_opportunity_statuses": { + "name": "guild_opportunity_statuses", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "tagline": { + "name": "tagline", + "type": "varchar(80)", + "primaryKey": false, + "notNull": false + }, + "about": { + "name": "about", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "profile_picture_url": { + "name": "profile_picture_url", + "type": "varchar(512)", + "primaryKey": false, + "notNull": false + }, + "shirt_size": { + "name": "shirt_size", + "type": "shirt_size", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "github_profile_url": { + "name": "github_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "linkedin_profile_url": { + "name": "linkedin_profile_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "website_url": { + "name": "website_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "resume_url": { + "name": "resume_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "dob": { + "name": "dob", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "grad_date": { + "name": "grad_date", + "type": "date", + "primaryKey": false, + "notNull": true + }, + "alumni_confirmed_at": { + "name": "alumni_confirmed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "company": { + "name": "company", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "current_city_key": { + "name": "current_city_key", + "type": "varchar(8)", + "primaryKey": false, + "notNull": false + }, + "guild_location_visible": { + "name": "guild_location_visible", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "job_internship_digest_enabled": { + "name": "job_internship_digest_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "job_new_grad_digest_enabled": { + "name": "job_new_grad_digest_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "points": { + "name": "points", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "date_created": { + "name": "date_created", + "type": "date", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "time_created": { + "name": "time_created", + "type": "time", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_member_user_id_auth_user_id_fk": { + "name": "knight_hacks_member_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_member", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_member_email_unique": { + "name": "knight_hacks_member_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + }, + "knight_hacks_member_phoneNumber_unique": { + "name": "knight_hacks_member_phoneNumber_unique", + "nullsNotDistinct": false, + "columns": ["phone_number"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_member_valid_guild_opportunity_statuses": { + "name": "knight_hacks_member_valid_guild_opportunity_statuses", + "value": "\"knight_hacks_member\".\"guild_opportunity_statuses\" <@ ARRAY['internships', 'full-time', 'freelance-contract', 'project-collaboration', 'offering-mentorship', 'seeking-mentorship']::text[] AND cardinality(\"knight_hacks_member\".\"guild_opportunity_statuses\") <= 3" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_companies": { + "name": "knight_hacks_companies", + "schema": "", + "columns": { + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_point_store_item": { + "name": "knight_hacks_point_store_item", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar(2000)", + "primaryKey": false, + "notNull": true, + "default": "''" + }, + "price": { + "name": "price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "stock": { + "name": "stock", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "sold_out": { + "name": "sold_out", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "archived": { + "name": "archived", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image_object_name": { + "name": "image_object_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + } + }, + "indexes": { + "point_store_item_hackathon_idx": { + "name": "point_store_item_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_point_store_item_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_point_store_item_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_point_store_item", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "point_store_item_hackathon_unique": { + "name": "point_store_item_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "point_store_item_price_check": { + "name": "point_store_item_price_check", + "value": "\"knight_hacks_point_store_item\".\"price\" BETWEEN 0 AND 1000000" + }, + "point_store_item_stock_check": { + "name": "point_store_item_stock_check", + "value": "\"knight_hacks_point_store_item\".\"stock\" IS NULL OR \"knight_hacks_point_store_item\".\"stock\" BETWEEN 0 AND 1000000" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_point_store_purchase": { + "name": "knight_hacks_point_store_purchase", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "attendee_id": { + "name": "attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "item_id": { + "name": "item_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hacker_name": { + "name": "hacker_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "item_name": { + "name": "item_name", + "type": "varchar(120)", + "primaryKey": false, + "notNull": true + }, + "unit_price": { + "name": "unit_price", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "quantity": { + "name": "quantity", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "total": { + "name": "total", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "stock_tracked": { + "name": "stock_tracked", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "actor_id": { + "name": "actor_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "actor_name": { + "name": "actor_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "voided_at": { + "name": "voided_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "voided_by": { + "name": "voided_by", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "voided_by_name": { + "name": "voided_by_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "void_reason": { + "name": "void_reason", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "restocked": { + "name": "restocked", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": { + "point_store_purchase_history_idx": { + "name": "point_store_purchase_history_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "point_store_purchase_balance_idx": { + "name": "point_store_purchase_balance_idx", + "columns": [ + { + "expression": "attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_point_store_purchase_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_point_store_purchase_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_point_store_purchase", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_point_store_purchase_attendee_id_knight_hacks_hacker_attendee_id_fk": { + "name": "knight_hacks_point_store_purchase_attendee_id_knight_hacks_hacker_attendee_id_fk", + "tableFrom": "knight_hacks_point_store_purchase", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["attendee_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_point_store_purchase_actor_id_auth_user_id_fk": { + "name": "knight_hacks_point_store_purchase_actor_id_auth_user_id_fk", + "tableFrom": "knight_hacks_point_store_purchase", + "tableTo": "auth_user", + "columnsFrom": ["actor_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_point_store_purchase_voided_by_auth_user_id_fk": { + "name": "knight_hacks_point_store_purchase_voided_by_auth_user_id_fk", + "tableFrom": "knight_hacks_point_store_purchase", + "tableTo": "auth_user", + "columnsFrom": ["voided_by"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "point_store_purchase_item_fk": { + "name": "point_store_purchase_item_fk", + "tableFrom": "knight_hacks_point_store_purchase", + "tableTo": "knight_hacks_point_store_item", + "columnsFrom": ["item_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "point_store_purchase_amount_check": { + "name": "point_store_purchase_amount_check", + "value": "\"knight_hacks_point_store_purchase\".\"unit_price\" BETWEEN 0 AND 1000000 AND \"knight_hacks_point_store_purchase\".\"quantity\" BETWEEN 1 AND 1000 AND \"knight_hacks_point_store_purchase\".\"total\" = \"knight_hacks_point_store_purchase\".\"unit_price\" * \"knight_hacks_point_store_purchase\".\"quantity\"" + }, + "point_store_purchase_void_check": { + "name": "point_store_purchase_void_check", + "value": "(\"knight_hacks_point_store_purchase\".\"voided_at\" IS NULL AND NOT \"knight_hacks_point_store_purchase\".\"restocked\") OR \"knight_hacks_point_store_purchase\".\"voided_at\" IS NOT NULL" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_print_job": { + "name": "knight_hacks_print_job", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hacker_attendee_id": { + "name": "hacker_attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "varchar(2000)", + "primaryKey": false, + "notNull": true + }, + "category": { + "name": "category", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "category_reminder_attempted_at": { + "name": "category_reminder_attempted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "category_reminder_sent_at": { + "name": "category_reminder_sent_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'received'" + }, + "status_note": { + "name": "status_note", + "type": "varchar(500)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "status_changed_at": { + "name": "status_changed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "status_changed_by_user_id": { + "name": "status_changed_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "estimated_ready_at": { + "name": "estimated_ready_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_print_job_queue_idx": { + "name": "knight_hacks_print_job_queue_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "status", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_print_job_attendee_idx": { + "name": "knight_hacks_print_job_attendee_idx", + "columns": [ + { + "expression": "hacker_attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_print_job_status_changed_by_idx": { + "name": "knight_hacks_print_job_status_changed_by_idx", + "columns": [ + { + "expression": "status_changed_by_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_print_job_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_print_job_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_print_job", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_print_job_status_changed_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_print_job_status_changed_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_print_job", + "tableTo": "auth_user", + "columnsFrom": ["status_changed_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "knight_hacks_print_job_attendee_scope_fk": { + "name": "knight_hacks_print_job_attendee_scope_fk", + "tableFrom": "knight_hacks_print_job", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["hacker_attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_print_job_scoped_identity_unique": { + "name": "knight_hacks_print_job_scoped_identity_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id", "hacker_attendee_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_print_job_category_check": { + "name": "knight_hacks_print_job_category_check", + "value": "\"knight_hacks_print_job\".\"category\" IS NULL OR \"knight_hacks_print_job\".\"category\" IN ('project', 'personal')" + }, + "knight_hacks_print_job_status_check": { + "name": "knight_hacks_print_job_status_check", + "value": "\"knight_hacks_print_job\".\"status\" IN ('received', 'printing', 'needs_clarification', 'ready_for_pickup', 'picked_up', 'cancelled')" + }, + "knight_hacks_print_job_description_not_blank_check": { + "name": "knight_hacks_print_job_description_not_blank_check", + "value": "\"knight_hacks_print_job\".\"description\" ~ '[^[:space:]]'" + }, + "knight_hacks_print_job_clarification_note_check": { + "name": "knight_hacks_print_job_clarification_note_check", + "value": "\"knight_hacks_print_job\".\"status\" <> 'needs_clarification' OR (\"knight_hacks_print_job\".\"status_note\" IS NOT NULL AND \"knight_hacks_print_job\".\"status_note\" ~ '[^[:space:]]')" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_print_job_file": { + "name": "knight_hacks_print_job_file", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "print_job_id": { + "name": "print_job_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hacker_attendee_id": { + "name": "hacker_attendee_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "object_name": { + "name": "object_name", + "type": "varchar(512)", + "primaryKey": false, + "notNull": true + }, + "file_name": { + "name": "file_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "content_type": { + "name": "content_type", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_print_job_file_job_idx": { + "name": "knight_hacks_print_job_file_job_idx", + "columns": [ + { + "expression": "print_job_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_print_job_file_attendee_idx": { + "name": "knight_hacks_print_job_file_attendee_idx", + "columns": [ + { + "expression": "hacker_attendee_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_print_job_file_staged_idx": { + "name": "knight_hacks_print_job_file_staged_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "where": "\"knight_hacks_print_job_file\".\"print_job_id\" IS NULL", + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_print_job_file_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_print_job_file_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_print_job_file", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_print_job_file_attendee_scope_fk": { + "name": "knight_hacks_print_job_file_attendee_scope_fk", + "tableFrom": "knight_hacks_print_job_file", + "tableTo": "knight_hacks_hacker_attendee", + "columnsFrom": ["hacker_attendee_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_print_job_file_job_scope_fk": { + "name": "knight_hacks_print_job_file_job_scope_fk", + "tableFrom": "knight_hacks_print_job_file", + "tableTo": "knight_hacks_print_job", + "columnsFrom": ["print_job_id", "hackathon_id", "hacker_attendee_id"], + "columnsTo": ["id", "hackathon_id", "hacker_attendee_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_print_job_file_object_unique": { + "name": "knight_hacks_print_job_file_object_unique", + "nullsNotDistinct": false, + "columns": ["object_name"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_print_job_file_size_check": { + "name": "knight_hacks_print_job_file_size_check", + "value": "\"knight_hacks_print_job_file\".\"size\" > 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_printing_configuration": { + "name": "knight_hacks_printing_configuration", + "schema": "", + "columns": { + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "discord_channel_id": { + "name": "discord_channel_id", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "is_open": { + "name": "is_open", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "print_minutes": { + "name": "print_minutes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 60 + }, + "printer_count": { + "name": "printer_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_printing_configuration_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_printing_configuration_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_printing_configuration", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_printing_configuration_print_minutes_check": { + "name": "knight_hacks_printing_configuration_print_minutes_check", + "value": "\"knight_hacks_printing_configuration\".\"print_minutes\" BETWEEN 5 AND 600" + }, + "knight_hacks_printing_configuration_printer_count_check": { + "name": "knight_hacks_printing_configuration_printer_count_check", + "value": "\"knight_hacks_printing_configuration\".\"printer_count\" BETWEEN 1 AND 20" + }, + "knight_hacks_printing_configuration_channel_id_check": { + "name": "knight_hacks_printing_configuration_channel_id_check", + "value": "\"knight_hacks_printing_configuration\".\"discord_channel_id\" IS NULL OR \"knight_hacks_printing_configuration\".\"discord_channel_id\" ~ '^[0-9]{17,20}$'" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project": { + "name": "knight_hacks_project", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "submission_url": { + "name": "submission_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "demo_links": { + "name": "demo_links", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "video_url": { + "name": "video_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "technologies": { + "name": "technologies", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "universities": { + "name": "universities", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "prize_categories": { + "name": "prize_categories", + "type": "text[]", + "primaryKey": false, + "notNull": true, + "default": "ARRAY[]::text[]" + }, + "participant_count": { + "name": "participant_count", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "project_created_at": { + "name": "project_created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "submitted_at": { + "name": "submitted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true + }, + "deleted_at": { + "name": "deleted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "deleted_by_user_id": { + "name": "deleted_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_project_hackathon_idx": { + "name": "knight_hacks_project_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_project_hackathon_deleted_idx": { + "name": "knight_hacks_project_hackathon_deleted_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deleted_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_project_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_project_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_project", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_project_deleted_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_project_deleted_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_project", + "tableTo": "auth_user", + "columnsFrom": ["deleted_by_user_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_project_hackathon_submission_url_unique": { + "name": "knight_hacks_project_hackathon_submission_url_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id", "submission_url"] + }, + "knight_hacks_project_id_hackathon_unique": { + "name": "knight_hacks_project_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_project_participant_count_check": { + "name": "knight_hacks_project_participant_count_check", + "value": "\"knight_hacks_project\".\"participant_count\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project_challenge": { + "name": "knight_hacks_project_challenge", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "label": { + "name": "label", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "parent_id": { + "name": "parent_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "is_group": { + "name": "is_group", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "import_label_prefix": { + "name": "import_label_prefix", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "is_general": { + "name": "is_general", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_scheduled": { + "name": "is_scheduled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "is_remote": { + "name": "is_remote", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_project_challenge_hackathon_idx": { + "name": "knight_hacks_project_challenge_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_project_challenge_hackathon_id_knight_hacks_hackathon_id_fk": { + "name": "knight_hacks_project_challenge_hackathon_id_knight_hacks_hackathon_id_fk", + "tableFrom": "knight_hacks_project_challenge", + "tableTo": "knight_hacks_hackathon", + "columnsFrom": ["hackathon_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "project_challenge_parent_scope_fk": { + "name": "project_challenge_parent_scope_fk", + "tableFrom": "knight_hacks_project_challenge", + "tableTo": "knight_hacks_project_challenge", + "columnsFrom": ["parent_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_project_challenge_hackathon_label_unique": { + "name": "knight_hacks_project_challenge_hackathon_label_unique", + "nullsNotDistinct": false, + "columns": ["hackathon_id", "label", "is_group"] + }, + "knight_hacks_project_challenge_id_hackathon_unique": { + "name": "knight_hacks_project_challenge_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": { + "project_challenge_root_general": { + "name": "project_challenge_root_general", + "value": "NOT \"knight_hacks_project_challenge\".\"is_general\" OR \"knight_hacks_project_challenge\".\"parent_id\" IS NULL" + }, + "project_challenge_not_self": { + "name": "project_challenge_not_self", + "value": "\"knight_hacks_project_challenge\".\"parent_id\" IS NULL OR \"knight_hacks_project_challenge\".\"parent_id\" <> \"knight_hacks_project_challenge\".\"id\"" + }, + "project_challenge_mode_check": { + "name": "project_challenge_mode_check", + "value": "NOT (\"knight_hacks_project_challenge\".\"is_scheduled\" AND \"knight_hacks_project_challenge\".\"is_remote\")" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project_claim": { + "name": "knight_hacks_project_claim", + "schema": "", + "columns": { + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": true, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_project_claim_user_id_auth_user_id_fk": { + "name": "knight_hacks_project_claim_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_project_claim", + "tableTo": "auth_user", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "project_claim_member_scope_fk": { + "name": "project_claim_member_scope_fk", + "tableFrom": "knight_hacks_project_claim", + "tableTo": "knight_hacks_project_member", + "columnsFrom": ["member_id", "project_id"], + "columnsTo": ["id", "project_id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "project_claim_project_scope_fk": { + "name": "project_claim_project_scope_fk", + "tableFrom": "knight_hacks_project_claim", + "tableTo": "knight_hacks_project", + "columnsFrom": ["project_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "project_claim_user_event_unique": { + "name": "project_claim_user_event_unique", + "nullsNotDistinct": false, + "columns": ["user_id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_project_claim_link": { + "name": "knight_hacks_project_claim_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "member_id": { + "name": "member_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "consumed_by_user_id": { + "name": "consumed_by_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "consumed_at": { + "name": "consumed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "sent_at": { + "name": "sent_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_project_claim_link_member_id_knight_hacks_project_member_id_fk": { + "name": "knight_hacks_project_claim_link_member_id_knight_hacks_project_member_id_fk", + "tableFrom": "knight_hacks_project_claim_link", + "tableTo": "knight_hacks_project_member", + "columnsFrom": ["member_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_project_claim_link_consumed_by_user_id_auth_user_id_fk": { + "name": "knight_hacks_project_claim_link_consumed_by_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_project_claim_link", + "tableTo": "auth_user", + "columnsFrom": ["consumed_by_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "project_claim_link_member_unique": { + "name": "project_claim_link_member_unique", + "nullsNotDistinct": false, + "columns": ["member_id"] + }, + "project_claim_link_token_unique": { + "name": "project_claim_link_token_unique", + "nullsNotDistinct": false, + "columns": ["token"] + } + }, + "policies": {}, + "checkConstraints": { + "project_claim_link_consumed_check": { + "name": "project_claim_link_consumed_check", + "value": "(\"knight_hacks_project_claim_link\".\"consumed_at\" IS NULL AND \"knight_hacks_project_claim_link\".\"consumed_by_user_id\" IS NULL AND \"knight_hacks_project_claim_link\".\"token\" IS NOT NULL) OR (\"knight_hacks_project_claim_link\".\"consumed_at\" IS NOT NULL AND \"knight_hacks_project_claim_link\".\"consumed_by_user_id\" IS NOT NULL AND \"knight_hacks_project_claim_link\".\"token\" IS NULL)" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project_evaluation": { + "name": "knight_hacks_project_evaluation", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "challenge_id": { + "name": "challenge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "judge_id": { + "name": "judge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "is_complete": { + "name": "is_complete", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "appointment_id": { + "name": "appointment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "auto_submitted_at": { + "name": "auto_submitted_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_project_evaluation_project_challenge_idx": { + "name": "knight_hacks_project_evaluation_project_challenge_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "challenge_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_project_evaluation_judge_idx": { + "name": "knight_hacks_project_evaluation_judge_idx", + "columns": [ + { + "expression": "judge_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "updated_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_project_evaluation_appointment_fk": { + "name": "knight_hacks_project_evaluation_appointment_fk", + "tableFrom": "knight_hacks_project_evaluation", + "tableTo": "knight_hacks_judging_appointment", + "columnsFrom": ["appointment_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_project_evaluation_project_challenge_scope_fk": { + "name": "knight_hacks_project_evaluation_project_challenge_scope_fk", + "tableFrom": "knight_hacks_project_evaluation", + "tableTo": "knight_hacks_project_to_challenge", + "columnsFrom": ["project_id", "challenge_id", "hackathon_id"], + "columnsTo": ["project_id", "challenge_id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + }, + "knight_hacks_project_evaluation_judge_scope_fk": { + "name": "knight_hacks_project_evaluation_judge_scope_fk", + "tableFrom": "knight_hacks_project_evaluation", + "tableTo": "knight_hacks_judge", + "columnsFrom": ["judge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_project_evaluation_judge_project_challenge_unique": { + "name": "knight_hacks_project_evaluation_judge_project_challenge_unique", + "nullsNotDistinct": false, + "columns": ["judge_id", "project_id", "challenge_id"] + }, + "knight_hacks_project_evaluation_id_hackathon_unique": { + "name": "knight_hacks_project_evaluation_id_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_project_evaluation_draft": { + "name": "knight_hacks_project_evaluation_draft", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "challenge_id": { + "name": "challenge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "judge_id": { + "name": "judge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "appointment_id": { + "name": "appointment_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "evaluation_id": { + "name": "evaluation_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "base_evaluation_revision": { + "name": "base_evaluation_revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "ratings": { + "name": "ratings", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "responses": { + "name": "responses", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "deadline_at": { + "name": "deadline_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "reconciliation_failed_at": { + "name": "reconciliation_failed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "reconciliation_error_code": { + "name": "reconciliation_error_code", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "knight_hacks_evaluation_draft_due_idx": { + "name": "knight_hacks_evaluation_draft_due_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "deadline_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_project_evaluation_draft_evaluation_id_knight_hacks_project_evaluation_id_fk": { + "name": "knight_hacks_project_evaluation_draft_evaluation_id_knight_hacks_project_evaluation_id_fk", + "tableFrom": "knight_hacks_project_evaluation_draft", + "tableTo": "knight_hacks_project_evaluation", + "columnsFrom": ["evaluation_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_evaluation_draft_appointment_fk": { + "name": "knight_hacks_evaluation_draft_appointment_fk", + "tableFrom": "knight_hacks_project_evaluation_draft", + "tableTo": "knight_hacks_judging_appointment", + "columnsFrom": ["appointment_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_evaluation_draft_project_fk": { + "name": "knight_hacks_evaluation_draft_project_fk", + "tableFrom": "knight_hacks_project_evaluation_draft", + "tableTo": "knight_hacks_project_to_challenge", + "columnsFrom": ["project_id", "challenge_id", "hackathon_id"], + "columnsTo": ["project_id", "challenge_id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_evaluation_draft_judge_fk": { + "name": "knight_hacks_evaluation_draft_judge_fk", + "tableFrom": "knight_hacks_project_evaluation_draft", + "tableTo": "knight_hacks_judge", + "columnsFrom": ["judge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_evaluation_draft_author_unique": { + "name": "knight_hacks_evaluation_draft_author_unique", + "nullsNotDistinct": false, + "columns": ["judge_id", "project_id", "challenge_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_project_evaluation_rating": { + "name": "knight_hacks_project_evaluation_rating", + "schema": "", + "columns": { + "evaluation_id": { + "name": "evaluation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "rubric_item_id": { + "name": "rubric_item_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_project_evaluation_rating_evaluation_scope_fk": { + "name": "knight_hacks_project_evaluation_rating_evaluation_scope_fk", + "tableFrom": "knight_hacks_project_evaluation_rating", + "tableTo": "knight_hacks_project_evaluation", + "columnsFrom": ["evaluation_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_project_evaluation_rating_rubric_scope_fk": { + "name": "knight_hacks_project_evaluation_rating_rubric_scope_fk", + "tableFrom": "knight_hacks_project_evaluation_rating", + "tableTo": "knight_hacks_judging_rubric_item", + "columnsFrom": ["rubric_item_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_project_evaluation_rating_evaluation_id_rubric_item_id_pk": { + "name": "knight_hacks_project_evaluation_rating_evaluation_id_rubric_item_id_pk", + "columns": ["evaluation_id", "rubric_item_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": { + "knight_hacks_project_evaluation_rating_value_check": { + "name": "knight_hacks_project_evaluation_rating_value_check", + "value": "\"knight_hacks_project_evaluation_rating\".\"value\" BETWEEN 1 AND 5" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project_evaluation_response": { + "name": "knight_hacks_project_evaluation_response", + "schema": "", + "columns": { + "evaluation_id": { + "name": "evaluation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "rubric_item_id": { + "name": "rubric_item_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_public": { + "name": "is_public", + "type": "boolean", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_project_evaluation_response_evaluation_scope_fk": { + "name": "knight_hacks_project_evaluation_response_evaluation_scope_fk", + "tableFrom": "knight_hacks_project_evaluation_response", + "tableTo": "knight_hacks_project_evaluation", + "columnsFrom": ["evaluation_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_project_evaluation_response_rubric_scope_fk": { + "name": "knight_hacks_project_evaluation_response_rubric_scope_fk", + "tableFrom": "knight_hacks_project_evaluation_response", + "tableTo": "knight_hacks_judging_rubric_item", + "columnsFrom": ["rubric_item_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_project_evaluation_response_evaluation_id_rubric_item_id_pk": { + "name": "knight_hacks_project_evaluation_response_evaluation_id_rubric_item_id_pk", + "columns": ["evaluation_id", "rubric_item_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_project_evaluation_revision": { + "name": "knight_hacks_project_evaluation_revision", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "evaluation_id": { + "name": "evaluation_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "actor_kind": { + "name": "actor_kind", + "type": "judge_kind", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + }, + "rating_answers": { + "name": "rating_answers", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "response_answers": { + "name": "response_answers", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_project_evaluation_revision_evaluation_scope_fk": { + "name": "knight_hacks_project_evaluation_revision_evaluation_scope_fk", + "tableFrom": "knight_hacks_project_evaluation_revision", + "tableTo": "knight_hacks_project_evaluation", + "columnsFrom": ["evaluation_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_project_evaluation_revision_unique": { + "name": "knight_hacks_project_evaluation_revision_unique", + "nullsNotDistinct": false, + "columns": ["evaluation_id", "revision"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_project_evaluation_revision_revision_check": { + "name": "knight_hacks_project_evaluation_revision_revision_check", + "value": "\"knight_hacks_project_evaluation_revision\".\"revision\" >= 1" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project_member": { + "name": "knight_hacks_project_member", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "varchar(320)", + "primaryKey": false, + "notNull": true + }, + "display_order": { + "name": "display_order", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "invited_user_id": { + "name": "invited_user_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "knight_hacks_project_member_project_idx": { + "name": "knight_hacks_project_member_project_idx", + "columns": [ + { + "expression": "project_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_project_member_project_id_knight_hacks_project_id_fk": { + "name": "knight_hacks_project_member_project_id_knight_hacks_project_id_fk", + "tableFrom": "knight_hacks_project_member", + "tableTo": "knight_hacks_project", + "columnsFrom": ["project_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_project_member_invited_user_id_auth_user_id_fk": { + "name": "knight_hacks_project_member_invited_user_id_auth_user_id_fk", + "tableFrom": "knight_hacks_project_member", + "tableTo": "auth_user", + "columnsFrom": ["invited_user_id"], + "columnsTo": ["id"], + "onDelete": "restrict", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "project_member_id_project_unique": { + "name": "project_member_id_project_unique", + "nullsNotDistinct": false, + "columns": ["id", "project_id"] + }, + "knight_hacks_project_member_project_order_unique": { + "name": "knight_hacks_project_member_project_order_unique", + "nullsNotDistinct": false, + "columns": ["project_id", "display_order"] + } + }, + "policies": {}, + "checkConstraints": { + "knight_hacks_project_member_display_order_check": { + "name": "knight_hacks_project_member_display_order_check", + "value": "\"knight_hacks_project_member\".\"display_order\" >= 0" + } + }, + "isRLSEnabled": false + }, + "public.knight_hacks_project_to_challenge": { + "name": "knight_hacks_project_to_challenge", + "schema": "", + "columns": { + "project_id": { + "name": "project_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "challenge_id": { + "name": "challenge_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "hackathon_id": { + "name": "hackathon_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "is_opt_in": { + "name": "is_opt_in", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": { + "knight_hacks_project_to_challenge_challenge_idx": { + "name": "knight_hacks_project_to_challenge_challenge_idx", + "columns": [ + { + "expression": "challenge_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "knight_hacks_project_to_challenge_hackathon_idx": { + "name": "knight_hacks_project_to_challenge_hackathon_idx", + "columns": [ + { + "expression": "hackathon_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "knight_hacks_project_to_challenge_project_scope_fk": { + "name": "knight_hacks_project_to_challenge_project_scope_fk", + "tableFrom": "knight_hacks_project_to_challenge", + "tableTo": "knight_hacks_project", + "columnsFrom": ["project_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knight_hacks_project_to_challenge_challenge_scope_fk": { + "name": "knight_hacks_project_to_challenge_challenge_scope_fk", + "tableFrom": "knight_hacks_project_to_challenge", + "tableTo": "knight_hacks_project_challenge", + "columnsFrom": ["challenge_id", "hackathon_id"], + "columnsTo": ["id", "hackathon_id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knight_hacks_project_to_challenge_project_id_challenge_id_pk": { + "name": "knight_hacks_project_to_challenge_project_id_challenge_id_pk", + "columns": ["project_id", "challenge_id"] + } + }, + "uniqueConstraints": { + "knight_hacks_project_to_challenge_project_challenge_hackathon_unique": { + "name": "knight_hacks_project_to_challenge_project_challenge_hackathon_unique", + "nullsNotDistinct": false, + "columns": ["project_id", "challenge_id", "hackathon_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_sponsor": { + "name": "knight_hacks_sponsor", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "logo_url": { + "name": "logo_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "website_url": { + "name": "website_url", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_template": { + "name": "knight_hacks_template", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "normalized_name": { + "name": "normalized_name", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "body": { + "name": "body", + "type": "jsonb", + "primaryKey": false, + "notNull": true + }, + "disabled_at": { + "name": "disabled_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "disabled_reason": { + "name": "disabled_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "knight_hacks_template_normalized_name_unique": { + "name": "knight_hacks_template_normalized_name_unique", + "nullsNotDistinct": false, + "columns": ["normalized_name"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knight_hacks_trpc_form_connection": { + "name": "knight_hacks_trpc_form_connection", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "form": { + "name": "form", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "proc": { + "name": "proc", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "connections": { + "name": "connections", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "knight_hacks_trpc_form_connection_form_knight_hacks_form_schemas_id_fk": { + "name": "knight_hacks_trpc_form_connection_form_knight_hacks_form_schemas_id_fk", + "tableFrom": "knight_hacks_trpc_form_connection", + "tableTo": "knight_hacks_form_schemas", + "columnsFrom": ["form"], + "columnsTo": ["id"], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.job_alert_target_kind": { + "name": "job_alert_target_kind", + "schema": "public", + "values": ["company", "location"] + }, + "public.job_application_stage": { + "name": "job_application_stage", + "schema": "public", + "values": [ + "saved", + "applied", + "online_assessment", + "recruiter_screen", + "interviewing", + "final_round", + "offer", + "rejected", + "withdrawn" + ] + }, + "public.job_application_visibility": { + "name": "job_application_visibility", + "schema": "public", + "values": ["community", "private"] + }, + "public.job_category": { + "name": "job_category", + "schema": "public", + "values": [ + "swe", + "data_ai", + "pm", + "it_security", + "quant", + "analyst", + "hardware", + "design", + "other" + ] + }, + "public.job_delivery_state": { + "name": "job_delivery_state", + "schema": "public", + "values": ["pending", "sending", "sent", "uncertain", "suppressed"] + }, + "public.job_location_kind": { + "name": "job_location_kind", + "schema": "public", + "values": ["city", "state", "remote_us", "unknown"] + }, + "public.job_track": { + "name": "job_track", + "schema": "public", + "values": ["internship", "new_grad"] + }, + "public.job_work_arrangement": { + "name": "job_work_arrangement", + "schema": "public", + "values": ["onsite", "hybrid", "remote"] + }, + "public.alumni_bulletin_state": { + "name": "alumni_bulletin_state", + "schema": "public", + "values": ["draft", "published", "archived"] + }, + "public.company_review_state": { + "name": "company_review_state", + "schema": "public", + "values": ["pending", "approved", "rejected", "merged"] + }, + "public.employment_experience_type": { + "name": "employment_experience_type", + "schema": "public", + "values": [ + "internship", + "full_time", + "part_time", + "co_op", + "contract", + "fellowship", + "self_employed", + "other" + ] + }, + "public.employment_state": { + "name": "employment_state", + "schema": "public", + "values": ["current", "past", "unknown"] + }, + "public.event_discord_entity_type": { + "name": "event_discord_entity_type", + "schema": "public", + "values": ["external", "voice", "stage"] + }, + "public.event_google_destination": { + "name": "event_google_destination", + "schema": "public", + "values": ["public", "internal"] + }, + "public.event_publication_work_state": { + "name": "event_publication_work_state", + "schema": "public", + "values": ["pending", "processing", "succeeded", "failed", "blocked"] + }, + "public.event_purpose": { + "name": "event_purpose", + "schema": "public", + "values": ["event", "primary_check_in"] + }, + "public.event_sync_state": { + "name": "event_sync_state", + "schema": "public", + "values": ["disabled", "pending", "synced", "error", "unknown"] + }, + "public.form_callback_status": { + "name": "form_callback_status", + "schema": "public", + "values": ["pending", "running", "succeeded", "failed", "cancelled"] + }, + "public.form_kind": { + "name": "form_kind", + "schema": "public", + "values": ["general", "event_feedback", "system"] + }, + "public.form_response_mode": { + "name": "form_response_mode", + "schema": "public", + "values": ["single_locked", "single_editable", "multiple_locked"] + }, + "public.form_state": { + "name": "form_state", + "schema": "public", + "values": ["draft", "published", "archived"] + }, + "public.gender": { + "name": "gender", + "schema": "public", + "values": [ + "Man", + "Woman", + "Non-binary", + "Prefer to self-describe", + "Prefer not to answer" + ] + }, + "public.hackathon_application_state": { + "name": "hackathon_application_state", + "schema": "public", + "values": [ + "withdrawn", + "pending", + "accepted", + "waitlisted", + "checkedin", + "confirmed", + "denied" + ] + }, + "public.hackathon_event_publication_provider": { + "name": "hackathon_event_publication_provider", + "schema": "public", + "values": ["discord", "google"] + }, + "public.hackathon_event_reminder_state": { + "name": "hackathon_event_reminder_state", + "schema": "public", + "values": ["pending", "delivering", "delivered", "failed", "unknown"] + }, + "public.hacker_agreement_provenance": { + "name": "hacker_agreement_provenance", + "schema": "public", + "values": ["explicit", "legacy_unversioned"] + }, + "public.hacker_agreement_stage": { + "name": "hacker_agreement_stage", + "schema": "public", + "values": ["application", "confirmation"] + }, + "public.hacker_check_in_outcome": { + "name": "hacker_check_in_outcome", + "schema": "public", + "values": [ + "checked_in", + "already_checked_in", + "invalid_qr", + "hacker_not_found", + "wrong_status", + "not_checked_in", + "wrong_class", + "not_ready" + ] + }, + "public.hacker_discord_role_attempt_outcome": { + "name": "hacker_discord_role_attempt_outcome", + "schema": "public", + "values": ["pending", "succeeded", "failed", "unknown"] + }, + "public.hacker_discord_role_grant_state": { + "name": "hacker_discord_role_grant_state", + "schema": "public", + "values": ["pending", "succeeded", "failed", "unknown"] + }, + "public.hacker_discord_role_kind": { + "name": "hacker_discord_role_kind", + "schema": "public", + "values": ["general", "class", "vip"] + }, + "public.hacker_participant_command_state": { + "name": "hacker_participant_command_state", + "schema": "public", + "values": ["started", "completed"] + }, + "public.issue_priority": { + "name": "issue_priority", + "schema": "public", + "values": ["Lowest", "Low", "Medium", "High", "Highest"] + }, + "public.issue_status": { + "name": "issue_status", + "schema": "public", + "values": ["Backlog", "Planning", "In Progress", "Finished"] + }, + "public.judge_kind": { + "name": "judge_kind", + "schema": "public", + "values": ["member", "guest"] + }, + "public.judging_response_visibility": { + "name": "judging_response_visibility", + "schema": "public", + "values": ["public", "public_optional", "private"] + }, + "public.judging_rubric_item_kind": { + "name": "judging_rubric_item_kind", + "schema": "public", + "values": ["rating", "short_response"] + }, + "public.judging_state": { + "name": "judging_state", + "schema": "public", + "values": ["draft", "open", "closed"] + }, + "public.race_or_ethnicity": { + "name": "race_or_ethnicity", + "schema": "public", + "values": [ + "White", + "Black or African American", + "Hispanic / Latino / Spanish Origin", + "Asian", + "Native Hawaiian or Other Pacific Islander", + "Native American or Alaskan Native", + "Middle Eastern", + "Prefer not to answer", + "Other" + ] + }, + "public.shirt_size": { + "name": "shirt_size", + "schema": "public", + "values": ["XS", "S", "M", "L", "XL", "2XL", "3XL"] + }, + "public.sponsor_tier": { + "name": "sponsor_tier", + "schema": "public", + "values": ["gold", "silver", "bronze", "other"] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json index 2775869b7..60dcbee1b 100644 --- a/packages/db/drizzle/meta/_journal.json +++ b/packages/db/drizzle/meta/_journal.json @@ -449,6 +449,13 @@ "when": 1791641041552, "tag": "0063_first_jean_grey", "breakpoints": true + }, + { + "idx": 64, + "version": "7", + "when": 1793758379130, + "tag": "0064_career_job_storage", + "breakpoints": true } ] } diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts index 5c73e1601..c8ca1940d 100644 --- a/packages/db/src/client.ts +++ b/packages/db/src/client.ts @@ -8,6 +8,7 @@ import * as authSchema from "./schemas/auth"; import * as clubTeamSchema from "./schemas/club-team"; import * as discordSchema from "./schemas/discord"; import * as discordConfigSchema from "./schemas/discord-config"; +import * as jobBoardSchema from "./schemas/job-board"; import * as knightHacksSchema from "./schemas/knight-hacks"; import * as relations from "./schemas/relations"; @@ -24,6 +25,7 @@ type KnightHacksSchema = typeof knightHacksSchema; type RelationsSchema = typeof relations; type DatabaseSchema = AuditSchema & + typeof jobBoardSchema & AuthSchema & ClubTeamSchema & DiscordSchema & @@ -39,6 +41,7 @@ const schema = { ...clubTeamSchema, ...discordSchema, ...discordConfigSchema, + ...jobBoardSchema, ...knightHacksSchema, ...relations, }; diff --git a/packages/db/src/schemas/job-board.ts b/packages/db/src/schemas/job-board.ts new file mode 100644 index 000000000..88e3c9239 --- /dev/null +++ b/packages/db/src/schemas/job-board.ts @@ -0,0 +1,420 @@ +import { sql } from "drizzle-orm"; +import { + check, + index, + pgEnum, + pgTableCreator, + unique, +} from "drizzle-orm/pg-core"; + +import { JOB_BOARD } from "@forge/consts"; + +import { Company, Member } from "./knight-hacks"; + +const createTable = pgTableCreator((name) => `knight_hacks_${name}`); + +// Hash full identifiers to stay below PostgreSQL's ~2.7 KB B-tree entry limit. +// Doubling backslashes before decode(..., 'escape') preserves literal UTF-8 bytes; +// a ::bytea cast instead interprets escape sequences and can conflate distinct keys. +// convert_to is STABLE, so PostgreSQL rejects it in generated columns. This +// expression uses only IMMUTABLE functions, as stored generated columns require. +const identityHash = (column: string) => + sql`encode(sha256(decode(replace(${sql.identifier(column)}, chr(92), chr(92) || chr(92)), 'escape')), 'hex')`; +export const jobTrackEnum = pgEnum("job_track", JOB_BOARD.JOB_TRACKS); +export const jobCategoryEnum = pgEnum("job_category", JOB_BOARD.JOB_CATEGORIES); +export const jobLocationKindEnum = pgEnum( + "job_location_kind", + JOB_BOARD.JOB_LOCATION_KINDS, +); +export const jobWorkArrangementEnum = pgEnum( + "job_work_arrangement", + JOB_BOARD.JOB_WORK_ARRANGEMENTS, +); +export const jobDeliveryStateEnum = pgEnum( + "job_delivery_state", + JOB_BOARD.JOB_DELIVERY_STATES, +); +export const jobApplicationStageEnum = pgEnum( + "job_application_stage", + JOB_BOARD.APPLICATION_STAGES, +); +export const jobApplicationVisibilityEnum = pgEnum( + "job_application_visibility", + JOB_BOARD.APPLICATION_VISIBILITIES, +); +export const jobAlertTargetKindEnum = pgEnum( + "job_alert_target_kind", + JOB_BOARD.ALERT_TARGET_KINDS, +); + +/** Provider is a code-owned adapter key; boardKey is officer-managed data. */ +export const JobSource = createTable( + "job_source", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + provider: t.varchar({ length: 64 }).notNull(), + boardKey: t.text().notNull(), + boardKeyHash: t + .text() + .notNull() + .generatedAlwaysAs(identityHash("board_key")), + label: t.varchar({ length: 200 }).notNull(), + companyId: t.uuid().references(() => Company.id, { onDelete: "set null" }), + enabled: t.boolean().notNull().default(false), + pollIntervalSeconds: t.integer().notNull().default(900), + nextPollAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + lastAttemptAt: t.timestamp({ withTimezone: true }), + lastSuccessAt: t.timestamp({ withTimezone: true }), + baselineCompletedAt: t.timestamp({ withTimezone: true }), + etag: t.text(), + lastModified: t.text(), + lastError: t.text(), + claimToken: t.uuid(), + leaseExpiresAt: t.timestamp({ withTimezone: true }), + createdAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + updatedAt: t + .timestamp({ withTimezone: true }) + .notNull() + .defaultNow() + .$onUpdate(() => new Date()), + }), + (table) => ({ + identity: unique("knight_hacks_job_source_provider_board_unique").on( + table.provider, + table.boardKeyHash, + ), + schedule: index("knight_hacks_job_source_schedule_idx").on( + table.enabled, + table.nextPollAt, + ), + company: index("knight_hacks_job_source_company_idx").on(table.companyId), + values: check( + "knight_hacks_job_source_values_check", + sql`${table.provider} ~ '^[a-z][a-z0-9_]*$' AND ${table.boardKey} ~ '[^[:space:]]' AND ${table.label} ~ '[^[:space:]]' AND ${table.pollIntervalSeconds} > 0`, + ), + lease: check( + "knight_hacks_job_source_lease_check", + sql`(${table.claimToken} IS NULL) = (${table.leaseExpiresAt} IS NULL)`, + ), + }), +); + +export const Job = createTable( + "job", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + // API computes a normalized employer requisition identity or application URL. + // Observations retain other source identities; title alone is never this key. + identityKey: t.text().notNull(), + identityHash: t + .text() + .notNull() + .generatedAlwaysAs(identityHash("identity_key")), + companyId: t.uuid().references(() => Company.id, { onDelete: "set null" }), + companyLabel: t.varchar({ length: 200 }).notNull(), + companyKey: t.varchar({ length: 120 }).notNull(), + title: t.text().notNull(), + track: jobTrackEnum().notNull(), + category: jobCategoryEnum(), + applyUrl: t.text().notNull(), + description: t.text(), + compensation: t.text(), + workArrangement: jobWorkArrangementEnum(), + postedAt: t.timestamp({ withTimezone: true }), + firstSeenAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + lastSeenAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + active: t.boolean().notNull().default(true), + inactiveAt: t.timestamp({ withTimezone: true }), + // Suppressed by default: schema rollout and initial inventories cannot post. + deliveryState: jobDeliveryStateEnum().notNull().default("suppressed"), + deliveryTrack: jobTrackEnum(), + discordChannelId: t.varchar({ length: 20 }), + discordMessageId: t.varchar({ length: 20 }), + deliveredAt: t.timestamp({ withTimezone: true }), + deliveryClaimToken: t.uuid(), + deliveryLeaseExpiresAt: t.timestamp({ withTimezone: true }), + deliveryNextAttemptAt: t.timestamp({ withTimezone: true }), + deliveryAttempts: t.integer().notNull().default(0), + deliveryError: t.text(), + }), + (table) => ({ + identity: unique("knight_hacks_job_identity_unique").on(table.identityHash), + message: unique("knight_hacks_job_discord_message_unique").on( + table.discordMessageId, + ), + company: index("knight_hacks_job_company_idx").on(table.companyId), + companySearch: index("knight_hacks_job_company_search_idx").on( + table.companyKey, + table.track, + ), + search: index("knight_hacks_job_search_idx").on( + table.active, + table.track, + table.firstSeenAt, + ), + posted: index("knight_hacks_job_posted_idx").on( + table.active, + table.postedAt, + ), + delivery: index("knight_hacks_job_delivery_idx").on( + table.deliveryState, + table.deliveryNextAttemptAt, + ), + digest: index("knight_hacks_job_digest_idx").on( + table.discordChannelId, + table.deliveredAt, + ), + values: check( + "knight_hacks_job_values_check", + sql`${table.identityKey} ~ '[^[:space:]]' AND ${table.companyLabel} ~ '[^[:space:]]' AND ${table.companyKey} ~ '[^[:space:]]' AND ${table.title} ~ '[^[:space:]]' AND ${table.applyUrl} ~ '^https?://' AND ${table.deliveryAttempts} >= 0`, + ), + dates: check( + "knight_hacks_job_dates_check", + sql`${table.lastSeenAt} >= ${table.firstSeenAt} AND (${table.active} = (${table.inactiveAt} IS NULL))`, + ), + channel: check( + "knight_hacks_job_channel_check", + sql`${table.discordChannelId} IS NULL OR ${table.discordChannelId} ~ '^[0-9]{17,20}$'`, + ), + messageId: check( + "knight_hacks_job_message_check", + sql`${table.discordMessageId} IS NULL OR ${table.discordMessageId} ~ '^[0-9]{17,20}$'`, + ), + lease: check( + "knight_hacks_job_lease_check", + sql`(${table.deliveryClaimToken} IS NULL) = (${table.deliveryLeaseExpiresAt} IS NULL)`, + ), + destination: check( + "knight_hacks_job_destination_check", + sql`${table.deliveryState} = 'suppressed' OR (${table.discordChannelId} IS NOT NULL AND ${table.deliveryTrack} IS NOT NULL)`, + ), + receipt: check( + "knight_hacks_job_receipt_check", + sql`(${table.deliveryState} = 'sent') = (${table.discordMessageId} IS NOT NULL AND ${table.deliveredAt} IS NOT NULL) AND (${table.discordMessageId} IS NULL) = (${table.deliveredAt} IS NULL)`, + ), + sending: check( + "knight_hacks_job_sending_check", + sql`${table.deliveryState} <> 'sending' OR ${table.deliveryClaimToken} IS NOT NULL`, + ), + }), +); + +export const JobObservation = createTable( + "job_observation", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + sourceId: t + .uuid() + .notNull() + .references(() => JobSource.id, { onDelete: "restrict" }), + jobId: t + .uuid() + .notNull() + .references(() => Job.id, { onDelete: "restrict" }), + externalId: t.text().notNull(), + externalIdHash: t + .text() + .notNull() + .generatedAlwaysAs(identityHash("external_id")), + sourceUrl: t.text(), + sourceData: t.jsonb().$type>(), + postedAt: t.timestamp({ withTimezone: true }), + firstSeenAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + lastSeenAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + inactiveAt: t.timestamp({ withTimezone: true }), + }), + (table) => ({ + identity: unique("knight_hacks_job_observation_source_external_unique").on( + table.sourceId, + table.externalIdHash, + ), + job: index("knight_hacks_job_observation_job_idx").on(table.jobId), + lastSeen: index("knight_hacks_job_observation_seen_idx").on( + table.sourceId, + table.lastSeenAt, + ), + values: check( + "knight_hacks_job_observation_values_check", + sql`${table.externalId} ~ '[^[:space:]]' AND ${table.lastSeenAt} >= ${table.firstSeenAt}`, + ), + }), +); + +export const JobLocation = createTable( + "job_location", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + jobId: t + .uuid() + .notNull() + .references(() => Job.id, { onDelete: "cascade" }), + sourceText: t.text().notNull(), + kind: jobLocationKindEnum().notNull(), + cityKey: t.varchar({ length: 8 }), + state: t.varchar({ length: 2 }), + }), + (table) => ({ + job: index("knight_hacks_job_location_job_idx").on(table.jobId), + city: index("knight_hacks_job_location_city_idx").on( + table.cityKey, + table.jobId, + ), + state: index("knight_hacks_job_location_state_idx").on( + table.state, + table.jobId, + ), + kind: index("knight_hacks_job_location_kind_idx").on( + table.kind, + table.jobId, + ), + values: check( + "knight_hacks_job_location_values_check", + sql`${table.sourceText} ~ '[^[:space:]]' AND (${table.state} IS NULL OR ${table.state} ~ '^[A-Z]{2}$') AND (${table.cityKey} IS NULL OR ${table.cityKey} ~ '^[0-9]{2}-[0-9]{5}$')`, + ), + shape: check( + "knight_hacks_job_location_shape_check", + sql`(${table.kind} = 'city' AND ${table.cityKey} IS NOT NULL AND ${table.state} IS NOT NULL) OR (${table.kind} = 'state' AND ${table.state} IS NOT NULL AND ${table.cityKey} IS NULL) OR (${table.kind} IN ('remote_us', 'unknown') AND ${table.cityKey} IS NULL AND ${table.state} IS NULL)`, + ), + }), +); + +/** One normalized company/location target per member and track. */ +export const JobAlertPreference = createTable( + "job_alert_preference", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + memberId: t + .uuid() + .notNull() + .references(() => Member.id, { onDelete: "cascade" }), + track: jobTrackEnum().notNull(), + kind: jobAlertTargetKindEnum().notNull(), + targetKey: t.varchar({ length: 120 }).notNull(), + customValue: t.varchar({ length: JOB_BOARD.MAX_ALERT_CUSTOM_VALUE_LENGTH }), + createdAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + }), + (table) => ({ + identity: unique("knight_hacks_job_alert_member_target_unique").on( + table.memberId, + table.track, + table.kind, + table.targetKey, + ), + matching: index("knight_hacks_job_alert_matching_idx").on( + table.kind, + table.targetKey, + table.track, + ), + values: check( + "knight_hacks_job_alert_values_check", + sql`${table.targetKey} ~ '[^[:space:]]' AND (${table.customValue} IS NULL OR ${table.customValue} ~ '[^[:space:]]')`, + ), + }), +); + +export const JobApplication = createTable( + "job_application", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + memberId: t + .uuid() + .notNull() + .references(() => Member.id, { onDelete: "cascade" }), + jobId: t + .uuid() + .notNull() + .references(() => Job.id, { onDelete: "restrict" }), + stage: jobApplicationStageEnum().notNull().default("saved"), + round: t.integer(), + visibility: jobApplicationVisibilityEnum() + .notNull() + .default(JOB_BOARD.DEFAULT_APPLICATION_VISIBILITY), + privateNotes: t.varchar({ length: JOB_BOARD.MAX_APPLICATION_NOTES_LENGTH }), + createdAt: t.timestamp({ withTimezone: true }).notNull().defaultNow(), + updatedAt: t + .timestamp({ withTimezone: true }) + .notNull() + .defaultNow() + .$onUpdate(() => new Date()), + }), + (table) => ({ + identity: unique("knight_hacks_job_application_member_job_unique").on( + table.memberId, + table.jobId, + ), + community: index("knight_hacks_job_application_community_idx").on( + table.jobId, + table.visibility, + table.stage, + ), + round: check( + "knight_hacks_job_application_round_check", + sql`${table.round} IS NULL OR (${table.stage} = 'interviewing' AND ${table.round} BETWEEN 1 AND ${sql.raw(String(JOB_BOARD.MAX_APPLICATION_ROUND))})`, + ), + }), +); + +/** One shared summary per track/schedule, not a message per subscribed member. */ +export const JobDigest = createTable( + "job_digest", + (t) => ({ + id: t.uuid().primaryKey().defaultRandom(), + track: jobTrackEnum().notNull(), + scheduledAt: t.timestamp({ withTimezone: true }).notNull(), + windowStart: t.timestamp({ withTimezone: true }).notNull(), + windowEnd: t.timestamp({ withTimezone: true }).notNull(), + discordChannelId: t.varchar({ length: 20 }).notNull(), + discordMessageId: t.varchar({ length: 20 }), + deliveryState: jobDeliveryStateEnum().notNull().default("pending"), + deliveredAt: t.timestamp({ withTimezone: true }), + claimToken: t.uuid(), + leaseExpiresAt: t.timestamp({ withTimezone: true }), + nextAttemptAt: t.timestamp({ withTimezone: true }), + attempts: t.integer().notNull().default(0), + lastError: t.text(), + }), + (table) => ({ + schedule: unique("knight_hacks_job_digest_schedule_unique").on( + table.track, + table.scheduledAt, + ), + message: unique("knight_hacks_job_digest_message_unique").on( + table.discordMessageId, + ), + pending: index("knight_hacks_job_digest_pending_idx").on( + table.deliveryState, + table.nextAttemptAt, + ), + values: check( + "knight_hacks_job_digest_values_check", + sql`${table.windowStart} < ${table.windowEnd} AND ${table.windowEnd} <= ${table.scheduledAt} AND ${table.attempts} >= 0 AND ${table.discordChannelId} ~ '^[0-9]{17,20}$' AND (${table.discordMessageId} IS NULL OR ${table.discordMessageId} ~ '^[0-9]{17,20}$')`, + ), + lease: check( + "knight_hacks_job_digest_lease_check", + sql`(${table.claimToken} IS NULL) = (${table.leaseExpiresAt} IS NULL)`, + ), + receipt: check( + "knight_hacks_job_digest_receipt_check", + sql`(${table.deliveryState} = 'sent') = (${table.discordMessageId} IS NOT NULL AND ${table.deliveredAt} IS NOT NULL) AND (${table.discordMessageId} IS NULL) = (${table.deliveredAt} IS NULL)`, + ), + sending: check( + "knight_hacks_job_digest_sending_check", + sql`${table.deliveryState} <> 'sending' OR ${table.claimToken} IS NOT NULL`, + ), + }), +); + +export type InsertJob = typeof Job.$inferInsert; +export type SelectJob = typeof Job.$inferSelect; +export type InsertJobSource = typeof JobSource.$inferInsert; +export type SelectJobSource = typeof JobSource.$inferSelect; +export type InsertJobObservation = typeof JobObservation.$inferInsert; +export type SelectJobObservation = typeof JobObservation.$inferSelect; +export type InsertJobLocation = typeof JobLocation.$inferInsert; +export type SelectJobLocation = typeof JobLocation.$inferSelect; +export type InsertJobAlertPreference = typeof JobAlertPreference.$inferInsert; +export type SelectJobAlertPreference = typeof JobAlertPreference.$inferSelect; +export type InsertJobApplication = typeof JobApplication.$inferInsert; +export type SelectJobApplication = typeof JobApplication.$inferSelect; +export type InsertJobDigest = typeof JobDigest.$inferInsert; +export type SelectJobDigest = typeof JobDigest.$inferSelect; diff --git a/packages/db/src/schemas/knight-hacks.ts b/packages/db/src/schemas/knight-hacks.ts index 65f418d66..a42794e9f 100644 --- a/packages/db/src/schemas/knight-hacks.ts +++ b/packages/db/src/schemas/knight-hacks.ts @@ -402,6 +402,8 @@ export const Member = createTable( company: t.varchar({ length: 255 }), currentCityKey: t.varchar({ length: 8 }), guildLocationVisible: t.boolean().notNull().default(true), + jobInternshipDigestEnabled: t.boolean().notNull().default(false), + jobNewGradDigestEnabled: t.boolean().notNull().default(false), points: t.integer().notNull().default(0), dateCreated: t.date().notNull().defaultNow(), timeCreated: t.time().notNull().defaultNow(), diff --git a/packages/db/src/schemas/relations.ts b/packages/db/src/schemas/relations.ts index b559464f9..6ad0832e3 100644 --- a/packages/db/src/schemas/relations.ts +++ b/packages/db/src/schemas/relations.ts @@ -1,6 +1,14 @@ import { relations } from "drizzle-orm"; import { Account, Permissions, Roles, Session, User } from "./auth"; +import { + Job, + JobAlertPreference, + JobApplication, + JobLocation, + JobObservation, + JobSource, +} from "./job-board"; import { AlumniBulletinPost, Company, @@ -43,6 +51,51 @@ import { ProjectToChallenge, } from "./knight-hacks"; +export const JobRelations = relations(Job, ({ one, many }) => ({ + company: one(Company, { fields: [Job.companyId], references: [Company.id] }), + observations: many(JobObservation), + locations: many(JobLocation), + applications: many(JobApplication), +})); + +export const JobSourceRelations = relations(JobSource, ({ one, many }) => ({ + company: one(Company, { + fields: [JobSource.companyId], + references: [Company.id], + }), + observations: many(JobObservation), +})); + +export const JobObservationRelations = relations(JobObservation, ({ one }) => ({ + job: one(Job, { fields: [JobObservation.jobId], references: [Job.id] }), + source: one(JobSource, { + fields: [JobObservation.sourceId], + references: [JobSource.id], + }), +})); + +export const JobLocationRelations = relations(JobLocation, ({ one }) => ({ + job: one(Job, { fields: [JobLocation.jobId], references: [Job.id] }), +})); + +export const JobApplicationRelations = relations(JobApplication, ({ one }) => ({ + job: one(Job, { fields: [JobApplication.jobId], references: [Job.id] }), + member: one(Member, { + fields: [JobApplication.memberId], + references: [Member.id], + }), +})); + +export const JobAlertPreferenceRelations = relations( + JobAlertPreference, + ({ one }) => ({ + member: one(Member, { + fields: [JobAlertPreference.memberId], + references: [Member.id], + }), + }), +); + export const UserRelations = relations(User, ({ many, one }) => ({ accounts: many(Account), sessions: many(Session), @@ -148,12 +201,16 @@ export const AccountRelations = relations(Account, ({ one }) => ({ })); export const MemberRelations = relations(Member, ({ many, one }) => ({ + jobApplications: many(JobApplication), + jobAlertPreferences: many(JobAlertPreference), user: one(User, { fields: [Member.userId], references: [User.id] }), eventAttendance: many(EventAttendee), employment: many(Employment), })); export const CompanyRelations = relations(Company, ({ many, one }) => ({ + jobs: many(Job), + jobSources: many(JobSource), createdBy: one(User, { fields: [Company.createdByUserId], references: [User.id], diff --git a/packages/db/src/tests/job-board-migration.test.ts b/packages/db/src/tests/job-board-migration.test.ts new file mode 100644 index 000000000..cb072bd15 --- /dev/null +++ b/packages/db/src/tests/job-board-migration.test.ts @@ -0,0 +1,452 @@ +import { createHash, randomBytes, randomUUID } from "node:crypto"; +import { readFile } from "node:fs/promises"; +import { drizzle } from "drizzle-orm/node-postgres"; +import { Pool } from "pg"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; + +import type { DisposableDatabase } from "../testing"; +import * as jobs from "../schemas/job-board"; +import * as relations from "../schemas/relations"; +import { canRunDatabaseTests, provisionDisposableDatabase } from "../testing"; + +const migrationUrl = new URL( + "../../drizzle/0064_career_job_storage.sql", + import.meta.url, +); + +describe("Career job migration scope", () => { + it("adds exactly seven tables and two false-default member preferences", async () => { + const migration = await readFile(migrationUrl, "utf8"); + expect(migration.match(/CREATE TABLE/g)).toHaveLength(7); + expect(migration).not.toMatch( + /DROP |DELETE FROM|TRUNCATE|UPDATE "knight_hacks_company"/, + ); + expect(migration).toContain( + 'ADD COLUMN "job_internship_digest_enabled" boolean DEFAULT false NOT NULL', + ); + expect(migration).toContain( + 'ADD COLUMN "job_new_grad_digest_enabled" boolean DEFAULT false NOT NULL', + ); + }); +}); + +describe.runIf(canRunDatabaseTests())( + "Career storage on disposable PostgreSQL", + () => { + let database: DisposableDatabase; + let pool: Pool; + const memberId = randomUUID(); + const userId = randomUUID(); + + beforeAll(async () => { + database = await provisionDisposableDatabase("forge_job_storage"); + pool = new Pool({ connectionString: database.url }); + await pool.query( + `INSERT INTO auth_user (id, discord_user_id, name) VALUES ($1, '123456789012345678', 'Job test')`, + [userId], + ); + await pool.query( + `INSERT INTO knight_hacks_member + (id, user_id, first_name, last_name, discord_user, age, email, school, level_of_study, shirt_size, dob, grad_date) + VALUES ($1, $2, 'Career', 'Test', 'job-test', 20, 'career@example.test', 'UCF', 'Undergraduate', 'M', '2006-01-01', '2027-05-01')`, + [memberId, userId], + ); + }, 120_000); + + afterAll(async () => { + await pool.end(); + await database.drop(); + }); + + async function job() { + const db = drizzle({ client: pool, casing: "snake_case" }); + const [row] = await db + .insert(jobs.Job) + .values({ + identityKey: `test:${randomUUID()}`, + companyLabel: "Acme", + companyKey: "acme", + title: "SWE Intern", + track: "internship", + applyUrl: "https://example.test/job", + }) + .returning(); + if (!row) throw new Error("Job fixture was not inserted"); + return row; + } + + it("upgrades existing members and companies without changing their data", async () => { + // Reconstruct the pre-feature shape only inside this disposable database + // transaction, then replay the additive migration against populated tables. + const client = database.client; + await client.query("BEGIN"); + try { + await client.query(`DROP TABLE knight_hacks_job_application, knight_hacks_job_alert_preference, + knight_hacks_job_location, knight_hacks_job_observation, knight_hacks_job_digest, + knight_hacks_job, knight_hacks_job_source; + DROP TYPE job_track, job_category, job_location_kind, job_work_arrangement, + job_delivery_state, job_application_stage, job_application_visibility, job_alert_target_kind; + ALTER TABLE knight_hacks_member DROP COLUMN job_internship_digest_enabled, + DROP COLUMN job_new_grad_digest_enabled;`); + const companyId = randomUUID(); + await client.query( + `INSERT INTO knight_hacks_company (id, display_name, normalized_display_name, review_state) + VALUES ($1, 'Existing employer', 'existing employer', 'pending')`, + [companyId], + ); + const before = await client.query( + "SELECT to_jsonb(m) AS data FROM knight_hacks_member m WHERE id = $1", + [memberId], + ); + const companyBefore = await client.query( + "SELECT to_jsonb(c) AS data FROM knight_hacks_company c WHERE id = $1", + [companyId], + ); + for (const statement of (await readFile(migrationUrl, "utf8")).split( + "--> statement-breakpoint", + )) { + if (statement.trim()) await client.query(statement); + } + const after = await client.query( + `SELECT to_jsonb(m) - 'job_internship_digest_enabled' - 'job_new_grad_digest_enabled' AS data FROM knight_hacks_member m WHERE id = $1`, + [memberId], + ); + const companyAfter = await client.query( + "SELECT to_jsonb(c) AS data FROM knight_hacks_company c WHERE id = $1", + [companyId], + ); + expect(after.rows).toEqual(before.rows); + expect(companyAfter.rows).toEqual(companyBefore.rows); + const flags = await client.query( + "SELECT job_internship_digest_enabled, job_new_grad_digest_enabled FROM knight_hacks_member WHERE id = $1", + [memberId], + ); + expect(flags.rows).toEqual([ + { + job_internship_digest_enabled: false, + job_new_grad_digest_enabled: false, + }, + ]); + } finally { + await client.query("ROLLBACK"); + } + }); + + it("preserves long identifiers and supports typed fingerprint upserts", async () => { + const db = drizzle({ client: pool, casing: "snake_case" }); + const raw = `${randomBytes(4000).toString("hex")}λ中文\\123\\x1234\n`; + const hash = createHash("sha256").update(raw).digest("hex"); + const values = { + identityKey: raw, + companyLabel: "Acme", + companyKey: "acme", + title: "Intern", + track: "internship" as const, + applyUrl: "https://example.test/job", + }; + const [first] = await db.insert(jobs.Job).values(values).returning(); + expect(first).toMatchObject({ identityKey: raw, identityHash: hash }); + const [updated] = await db + .insert(jobs.Job) + .values(values) + .onConflictDoUpdate({ + target: jobs.Job.identityHash, + set: { title: "Updated" }, + }) + .returning(); + expect(updated).toMatchObject({ id: first?.id, title: "Updated" }); + const [distinct] = await db + .insert(jobs.Job) + .values({ ...values, identityKey: `${raw}different` }) + .returning(); + expect(distinct?.id).not.toBe(first?.id); + + const sourceValues = { + provider: "greenhouse", + boardKey: raw, + label: "Acme", + }; + const [source] = await db + .insert(jobs.JobSource) + .values(sourceValues) + .returning(); + if (!source || !first) throw new Error("Missing identifier fixtures"); + expect(source).toMatchObject({ boardKey: raw, boardKeyHash: hash }); + const [sameSource] = await db + .insert(jobs.JobSource) + .values(sourceValues) + .onConflictDoUpdate({ + target: [jobs.JobSource.provider, jobs.JobSource.boardKeyHash], + set: { label: "Updated" }, + }) + .returning(); + expect(sameSource?.id).toBe(source.id); + const observationValues = { + sourceId: source.id, + externalId: raw, + jobId: first.id, + }; + const [observation] = await db + .insert(jobs.JobObservation) + .values(observationValues) + .returning(); + expect(observation).toMatchObject({ + externalId: raw, + externalIdHash: hash, + }); + const [sameObservation] = await db + .insert(jobs.JobObservation) + .values(observationValues) + .onConflictDoUpdate({ + target: [ + jobs.JobObservation.sourceId, + jobs.JobObservation.externalIdHash, + ], + set: { jobId: first.id }, + }) + .returning(); + expect(sameObservation?.id).toBe(observation?.id); + }); + + it("defaults delivery to suppressed and digest opt-ins to false", async () => { + expect((await job()).deliveryState).toBe("suppressed"); + const { rows } = await pool.query<{ + job_internship_digest_enabled: boolean; + job_new_grad_digest_enabled: boolean; + }>( + "SELECT job_internship_digest_enabled, job_new_grad_digest_enabled FROM knight_hacks_member WHERE id = $1", + [memberId], + ); + expect(rows).toEqual([ + { + job_internship_digest_enabled: false, + job_new_grad_digest_enabled: false, + }, + ]); + }); + + it("serializes competing canonical identities and source observations", async () => { + const identity = `race:${randomUUID()}`; + const insert = () => + pool.query( + `INSERT INTO knight_hacks_job (identity_key, company_label, company_key, title, track, apply_url) + VALUES ($1, 'Acme', 'acme', 'Intern', 'internship', 'https://example.test/job') RETURNING id`, + [identity], + ); + const attempts = await Promise.allSettled([insert(), insert()]); + expect( + attempts.filter((result) => result.status === "fulfilled"), + ).toHaveLength(1); + const rejected = attempts.find((result) => result.status === "rejected"); + expect(rejected).toMatchObject({ + status: "rejected", + reason: { code: "23505" }, + }); + const listing = await job(); + const sourceId = randomUUID(); + await pool.query( + `INSERT INTO knight_hacks_job_source (id, provider, board_key, label) VALUES ($1::uuid, 'greenhouse', $1::text, 'Acme')`, + [sourceId], + ); + const observe = () => + pool.query( + `INSERT INTO knight_hacks_job_observation (job_id, source_id, external_id) VALUES ($1, $2, '123')`, + [listing.id, sourceId], + ); + const observations = await Promise.allSettled([observe(), observe()]); + expect( + observations.filter((result) => result.status === "fulfilled"), + ).toHaveLength(1); + expect( + observations.find((result) => result.status === "rejected"), + ).toMatchObject({ reason: { code: "23505" } }); + const secondSourceId = randomUUID(); + await pool.query( + `INSERT INTO knight_hacks_job_source (id, provider, board_key, label) VALUES ($1::uuid, 'jobright', $1::text, 'Jobright')`, + [secondSourceId], + ); + await pool.query( + `INSERT INTO knight_hacks_job_observation (job_id, source_id, external_id) VALUES ($1, $2, '123')`, + [listing.id, secondSourceId], + ); + const db = drizzle({ + client: pool, + schema: { ...jobs, ...relations }, + casing: "snake_case", + }); + const found = await db.query.Job.findFirst({ + where: (table, { eq }) => eq(table.id, listing.id), + with: { observations: true }, + }); + expect(found?.observations).toHaveLength(2); + }); + + it("stores several locations without duplicating a job and rejects contradictory shapes", async () => { + const listing = await job(); + for (const [kind, city, state, text] of [ + ["city", "12-53000", "FL", "Orlando, FL"], + ["state", null, "WA", "Washington"], + ["remote_us", null, null, "Remote - United States"], + ["unknown", null, null, "Various locations"], + ]) { + await pool.query( + `INSERT INTO knight_hacks_job_location (job_id, kind, city_key, state, source_text) VALUES ($1,$2,$3,$4,$5)`, + [listing.id, kind, city, state, text], + ); + } + const { rows } = await pool.query<{ source_text: string }>( + "SELECT source_text FROM knight_hacks_job_location WHERE job_id = $1", + [listing.id], + ); + expect(rows).toHaveLength(4); + expect(rows).toContainEqual({ source_text: "Various locations" }); + await expect( + pool.query( + `INSERT INTO knight_hacks_job_location (job_id, kind, city_key, state, source_text) VALUES ($1, 'remote_us', '12-53000', 'FL', 'Remote')`, + [listing.id], + ), + ).rejects.toMatchObject({ code: "23514" }); + await expect( + pool.query( + `INSERT INTO knight_hacks_job_location (job_id, kind, city_key, state, source_text) VALUES ($1, 'city', 'bad', 'FL', 'Orlando')`, + [listing.id], + ), + ).rejects.toMatchObject({ code: "23514" }); + }); + + it("keeps application history and enforces one application and valid rounds", async () => { + const listing = await job(); + const insert = (stage: string, round: number | null) => + pool.query( + `INSERT INTO knight_hacks_job_application (member_id, job_id, stage, round) VALUES ($1,$2,$3,$4)`, + [memberId, listing.id, stage, round], + ); + await expect(insert("applied", 1)).rejects.toMatchObject({ + code: "23514", + }); + await expect(insert("interviewing", 11)).rejects.toMatchObject({ + code: "23514", + }); + await insert("interviewing", 2); + await expect(insert("saved", null)).rejects.toMatchObject({ + code: "23505", + }); + await pool.query( + "UPDATE knight_hacks_job SET active = false, inactive_at = now() WHERE id = $1", + [listing.id], + ); + await expect( + pool.query("DELETE FROM knight_hacks_job WHERE id = $1", [listing.id]), + ).rejects.toMatchObject({ + constraint: + "knight_hacks_job_application_job_id_knight_hacks_job_id_fk", + }); + const { rows } = await pool.query<{ round: number }>( + "SELECT round FROM knight_hacks_job_application WHERE job_id = $1", + [listing.id], + ); + expect(rows).toEqual([{ round: 2 }]); + }); + + it("requires coherent job claims, destinations and receipts", async () => { + const listing = await job(); + await pool.query( + `UPDATE knight_hacks_job SET discord_channel_id = '123456789012345678', delivery_track = 'internship' WHERE id = $1`, + [listing.id], + ); + await expect( + pool.query( + "UPDATE knight_hacks_job SET delivery_state = 'sent' WHERE id = $1", + [listing.id], + ), + ).rejects.toMatchObject({ constraint: "knight_hacks_job_receipt_check" }); + await expect( + pool.query( + `UPDATE knight_hacks_job SET delivery_state = 'sent', discord_message_id = '223456789012345678' WHERE id = $1`, + [listing.id], + ), + ).rejects.toMatchObject({ constraint: "knight_hacks_job_receipt_check" }); + await expect( + pool.query( + "UPDATE knight_hacks_job SET delivery_state = 'sent', delivered_at = now() WHERE id = $1", + [listing.id], + ), + ).rejects.toMatchObject({ constraint: "knight_hacks_job_receipt_check" }); + await expect( + pool.query( + "UPDATE knight_hacks_job SET discord_channel_id = 'invalid' WHERE id = $1", + [listing.id], + ), + ).rejects.toMatchObject({ code: "23514" }); + await expect( + pool.query( + `UPDATE knight_hacks_job SET delivery_state = 'sending', discord_channel_id = '123456789012345678', delivery_track = 'internship' WHERE id = $1`, + [listing.id], + ), + ).rejects.toMatchObject({ code: "23514" }); + await pool.query( + `UPDATE knight_hacks_job SET delivery_state = 'sending', discord_channel_id = '123456789012345678', delivery_track = 'internship', delivery_claim_token = $2, delivery_lease_expires_at = now() + interval '1 minute' WHERE id = $1`, + [listing.id, randomUUID()], + ); + await pool.query( + `UPDATE knight_hacks_job SET delivery_state = 'sent', discord_message_id = '223456789012345678', delivered_at = now(), delivery_claim_token = null, delivery_lease_expires_at = null WHERE id = $1`, + [listing.id], + ); + }); + + it("deduplicates digest schedules across channel changes and checks windows and receipts", async () => { + const scheduled = new Date("2026-11-03T21:00:00Z"); + const insert = (channel: string) => + pool.query( + `INSERT INTO knight_hacks_job_digest (track, scheduled_at, window_start, window_end, discord_channel_id) + VALUES ('internship', $1, $1::timestamptz - interval '1 day', $1, $2) RETURNING id`, + [scheduled, channel], + ); + await insert("123456789012345678"); + await expect(insert("323456789012345678")).rejects.toMatchObject({ + code: "23505", + }); + await expect( + pool.query( + "UPDATE knight_hacks_job_digest SET window_start = window_end", + ), + ).rejects.toMatchObject({ code: "23514" }); + await expect( + pool.query( + "UPDATE knight_hacks_job_digest SET window_end = scheduled_at + interval '1 day'", + ), + ).rejects.toMatchObject({ code: "23514" }); + await expect( + pool.query( + "UPDATE knight_hacks_job_digest SET delivery_state = 'sent'", + ), + ).rejects.toMatchObject({ code: "23514" }); + }); + + it("deduplicates target preferences and cascades personal records on member deletion", async () => { + const insert = (track: string) => + pool.query( + `INSERT INTO knight_hacks_job_alert_preference (member_id, track, kind, target_key) VALUES ($1, $2, 'company', 'acme')`, + [memberId, track], + ); + await insert("internship"); + await insert("new_grad"); + await expect(insert("internship")).rejects.toMatchObject({ + code: "23505", + }); + await pool.query("DELETE FROM knight_hacks_member WHERE id = $1", [ + memberId, + ]); + const preferences = await pool.query( + "SELECT id FROM knight_hacks_job_alert_preference WHERE member_id = $1", + [memberId], + ); + const applications = await pool.query( + "SELECT id FROM knight_hacks_job_application WHERE member_id = $1", + [memberId], + ); + expect(preferences.rows).toHaveLength(0); + expect(applications.rows).toHaveLength(0); + }); + }, +); diff --git a/packages/db/src/tests/migration-lineage.test.ts b/packages/db/src/tests/migration-lineage.test.ts index 8c7286d8c..daef5fc35 100644 --- a/packages/db/src/tests/migration-lineage.test.ts +++ b/packages/db/src/tests/migration-lineage.test.ts @@ -106,7 +106,7 @@ describe("canonical production migration lineage", () => { await readFile(new URL("_journal.json", metadataDirectory), "utf8"), ) as { entries: JournalEntry[] }; - expect(journal.entries).toHaveLength(64); + expect(journal.entries).toHaveLength(65); expect(journal.entries[10]).toMatchObject({ idx: 10, tag: "0010_wooden_supreme_intelligence", @@ -117,8 +117,8 @@ describe("canonical production migration lineage", () => { tag: "0059_needy_menace", }); expect(journal.entries.at(-1)).toMatchObject({ - idx: 63, - tag: "0063_first_jean_grey", + idx: 64, + tag: "0064_career_job_storage", }); for (const [position, entry] of journal.entries.entries()) { From 4b88ae09f3d93e6f69aaf7672eb80336d3a23ecf Mon Sep 17 00:00:00 2001 From: kevin li Date: Tue, 3 Nov 2026 21:45:58 -0500 Subject: [PATCH 2/2] [#647] Address CodeRabbit doc feedback Co-authored-by: Claude --- .forge/features/career-job-storage/srd.md | 3 ++- .forge/features/career-job-storage/status.md | 12 ++++----- docs/DATABASE-USAGE.md | 26 ++++++++++---------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.forge/features/career-job-storage/srd.md b/.forge/features/career-job-storage/srd.md index a8249fd09..b0a0e4b77 100644 --- a/.forge/features/career-job-storage/srd.md +++ b/.forge/features/career-job-storage/srd.md @@ -1,6 +1,7 @@ # Career Job Storage SRD -Status: Implementing the design approved in the November 3 conversation. +Status: Implementing the design agreed in the local November 3 conversation. The +#633 GitHub design review is still outstanding. References: #647, parent #633, vocabulary #646 / PR #658. ## Ownership and access diff --git a/.forge/features/career-job-storage/status.md b/.forge/features/career-job-storage/status.md index f1b136b34..17bdc90e1 100644 --- a/.forge/features/career-job-storage/status.md +++ b/.forge/features/career-job-storage/status.md @@ -63,9 +63,10 @@ src/tests/job-board.test.ts`: 30 passed. named uniqueness/check constraints and search/delivery indexes are implemented. - Design and follow-up runtime/access contracts are in srd.md. No current app sends jobs, syncs digest roles, or accepts source settings through this change. -- Migration is local and uncommitted; no production/shared database was migrated. -- Root formatting and historical checksum remain checkout limitations. No commit - or push was made, and GitHub review in #633 is still outstanding. +- Migration is committed and pushed in PR #666; no production/shared database was + migrated. +- Root formatting and historical checksum remain checkout limitations. GitHub + review in #633 is still outstanding. ## Linux contribution review @@ -145,7 +146,6 @@ migration and idempotent rerun; targeted formatting/lint, DB typecheck, and no Drizzle schema drift. The user additionally confirmed that root lint, root typecheck, DB tests, and db:generate ran after the squash. The local 0010 lineage check has a CRLF-only failure; the isolated LF lineage suite passed. -User authorized committing and pushing this branch. PR text will be drafted for -review only; posting requires an explicit request. Dev-lead schema approval is -still outstanding. Optional follow-ups: delivery_track digest index coverage and +Committed as one commit rebased onto main and opened as PR #666. Dev-lead schema +approval is still outstanding. Optional follow-ups: delivery_track digest index coverage and an automated schema-drift regression test. diff --git a/docs/DATABASE-USAGE.md b/docs/DATABASE-USAGE.md index 6c86efcb6..25c354db0 100644 --- a/docs/DATABASE-USAGE.md +++ b/docs/DATABASE-USAGE.md @@ -210,6 +210,19 @@ Do not return raw application rows: private notes are always private, including when application visibility is community. No end-user row authorization is implied by these foreign keys. +### Identifier fingerprints + +`Job.identityHash`, `JobSource.boardKeyHash` and `JobObservation.externalIdHash` are +stored, database-generated SHA-256 hex fingerprints of the original UTF-8 keys. +Unique constraints target the fingerprint, with provider/sourceId where applicable, +so long URLs and provider identifiers do not exceed PostgreSQL B-tree limits. +The original values remain intact. Future writers must use these columns as +Drizzle conflict targets and verify the original key matches before updating a +conflicting row; a mismatched key is an error, never permission to overwrite. +Indexed lookups should compute the same SHA-256 fingerprint and compare the raw +key as well. No ingestion/upsert service is implemented in this database-only work. +Migration 0064 creates the fingerprint columns and their unique constraints directly. + ## Undocumented columns If a task needs a table or column not explained here, inspect existing usage first. If the intended semantics are still not clear from code, ask a clarifying question before setting a new precedent. @@ -223,16 +236,3 @@ Team mutations and check-in share the hackathon allocation advisory lock. The fi Organizer status changes away from confirmed/checked-in, application withdrawal, and deletion remove membership in the same transaction, promote a random remaining member if the owner leaves, and delete an empty team. Composite foreign keys keep attendees, teams, and the stored class within one hackathon. Both team tables are excluded from sanitized development backups. Legacy bulk status check-in rejects hackers with teams or pending requests; the Hackathon Check-in workspace performs their class assignment. The attendee membership foreign key uses `NO ACTION` so account cascades cannot silently orphan teams. Account deletion asks the user to leave teams/cancel requests first, with organizer removal available when their Teams page is locked. - -### Identifier fingerprints - -Job.identityHash, JobSource.boardKeyHash and JobObservation.externalIdHash are -stored, database-generated SHA-256 hex fingerprints of the original UTF-8 keys. -Unique constraints target the fingerprint, with provider/sourceId where applicable, -so long URLs and provider identifiers do not exceed PostgreSQL B-tree limits. -The original values remain intact. Future writers must use these columns as -Drizzle conflict targets and verify the original key matches before updating a -conflicting row; a mismatched key is an error, never permission to overwrite. -Indexed lookups should compute the same SHA-256 fingerprint and compare the raw -key as well. No ingestion/upsert service is implemented in this database-only work. -Migration 0064 creates the fingerprint columns and their unique constraints directly.