Files
t5de-hub/packages/db/drizzle/meta/0012_snapshot.json
T
dhkatz 7299e10b08
Release / release (push) Successful in 3s
CI / test (push) Successful in 17m26s
CI / image (apps/api/Dockerfile, t5de-hub-api) (push) Successful in 6s
CI / image (apps/web/Dockerfile, t5de-hub-web) (push) Successful in 15s
feat: cases (reports, reviews, requests, appeals) and notifications (#9)
Phase 3, part 1 (`docs/design.md`, "Next"): cases and notifications. File blocks, API tokens and two-factor sign-in come as separate PRs.

**Cases**
- One queue (Console → Cases) for everything someone has to decide. Each case has:
  - a thread of notes, where internal notes are visible only to those deciding
  - an assignee (moderators assign cases to moderators)
  - a decision, Resolve or Decline, with a written resolution that the person who opened it sees
- **Reports:** anyone signed in can report a product or catalog from its page (the API also takes rooms and people).
  - Limits: 10 an hour, one open report per person and thing, and you can't report yourself.
  - Reports about a product go to the teams of the catalogs hosting it, as well as to moderators.
  - Only the reporter and moderators know who reported. The audit entry for a report isn't tagged with what it's about, so a product's creator can't find out from their audit log either.
- **Rating reviews:** a creator lowering a rating from adult to general now opens a review instead of being refused. The rest of the edit still saves. Resolving the review lowers the rating, recorded in the product's history.
- **Removal requests:** a catalog's team can ask moderators to remove a product it hosts, everywhere. Resolving it removes the product.
- **Deletion requests:** a catalog's owner asks for deletion from the catalog's console page, and a moderator decides, as agreed. Resolving it marks the catalog `deleted`: its key stops working, nothing is available from it, and its changes feed says so.
- **Appeals:**
  - From the audit log, the person an action affected can appeal it, once: their product removed, delisted or edited by someone else; their catalog suspended or rejected; a ban from a catalog or a declined request to join.
  - Another moderator decides. An admin may decide an appeal of their own action, and the audit log flags it.
  - Resolving records the decision; the moderator then undoes the action where it's done. For that, there's now a Restore for removed products (Console → Products, for moderators); the design mentioned one, but it was never built.
- The console shows a "Cases" tab, and a to-do with the number of open cases the person could decide.

**Notifications**
- A bell in the header with the unread count, and a notifications page with "Mark all as read".
- Each is also sent to the person's proxies over the realtime connection (`{"type": "notification"}`), so the client can show them later.
- They cover:
  - a moderator edited or locked your product, or undid a change (with the reason)
  - your product was removed or restored
  - your case was decided
  - someone replied on your case
  - a catalog decided your membership

**Also changed**
- A product's creator and moderators can now see it when it's adult, even without an adult account. Before, a creator who made their own product adult couldn't open its page any more, and neither could moderators. Getting and wearing adult products still need an adult account.

**Not done yet** (in `docs/console.md`): email notifications (the hub sends no email yet), canned reasons, private moderator notes on people and products, and second approval for the most destructive actions.

**Migration** `0012_cases`: the `moderation_case`, `case_note` and `notification` tables. (`case` is a reserved word in SQL, hence the table's name.)

**Checks**
- 51 API tests pass. The 7 in the new `cases.test.ts` cover:
  - who sees and decides each kind of case, and that the reporter stays private
  - rate limits and duplicate reports
  - the thread and internal notes, and assigning
  - what deciding each kind of case does
  - appeals by the person affected only, decided by another moderator
  - restoring a removed product
  - the notifications
- Type checks pass.
- On a local hub I went through every flow with the website's own forms: report from a product page; the catalog owner's note and decision; assigning, an internal note and a decision as admin; removal by a moderator, the creator's appeal from the audit log, the admin's decision and Restore; a creator's rating review and the decision lowering the rating; a deletion request and its decline; the notifications, the bell's count, and Mark all as read.
- Fixed along the way:
  - The catalog's team could see who reported.
  - A missing Resolve/Decline choice was treated as Decline; now it's refused.
  - The Unassign button sent the typed name instead of nothing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Phase 3, part 1 (`docs/design.md`, "Next"): cases and notifications. File blocks, API tokens and two-factor sign-in come as separate PRs.

**Cases**
- One queue (Console → Cases) for everything someone has to decide. Each case has:
  - a thread of notes, where internal notes are visible only to those deciding
  - an assignee (moderators assign cases to moderators)
  - a decision, Resolve or Decline, with a written resolution that the person who opened it sees
- **Reports:** anyone signed in can report a product or catalog from its page (the API also takes rooms and people).
  - Limits: 10 an hour, one open report per person and thing, and you can't report yourself.
  - Reports about a product go to the teams of the catalogs hosting it, as well as to moderators.
  - Only the reporter and moderators know who reported. The audit entry for a report isn't tagged with what it's about, so a product's creator can't find out from their audit log either.
- **Rating reviews:** a creator lowering a rating from adult to general now opens a review instead of being refused. The rest of the edit still saves. Resolving the review lowers the rating, recorded in the product's history.
- **Removal requests:** a catalog's team can ask moderators to remove a product it hosts, everywhere. Resolving it removes the product.
- **Deletion requests:** a catalog's owner asks for deletion from the catalog's console page, and a moderator decides, as agreed. Resolving it marks the catalog `deleted`: its key stops working, nothing is available from it, and its changes feed says so.
- **Appeals:**
  - From the audit log, the person an action affected can appeal it, once: their product removed, delisted or edited by someone else; their catalog suspended or rejected; a ban from a catalog or a declined request to join.
  - Another moderator decides. An admin may decide an appeal of their own action, and the audit log flags it.
  - Resolving records the decision; the moderator then undoes the action where it's done. For that, there's now a Restore for removed products (Console → Products, for moderators); the design mentioned one, but it was never built.
- The console shows a "Cases" tab, and a to-do with the number of open cases the person could decide.

**Notifications**
- A bell in the header with the unread count, and a notifications page with "Mark all as read".
- Each is also sent to the person's proxies over the realtime connection (`{"type": "notification"}`), so the client can show them later.
- They cover:
  - a moderator edited or locked your product, or undid a change (with the reason)
  - your product was removed or restored
  - your case was decided
  - someone replied on your case
  - a catalog decided your membership

**Also changed**
- A product's creator and moderators can now see it when it's adult, even without an adult account. Before, a creator who made their own product adult couldn't open its page any more, and neither could moderators. Getting and wearing adult products still need an adult account.

**Not done yet** (in `docs/console.md`): email notifications (the hub sends no email yet), canned reasons, private moderator notes on people and products, and second approval for the most destructive actions.

**Migration** `0012_cases`: the `moderation_case`, `case_note` and `notification` tables. (`case` is a reserved word in SQL, hence the table's name.)

**Checks**
- 51 API tests pass. The 7 in the new `cases.test.ts` cover:
  - who sees and decides each kind of case, and that the reporter stays private
  - rate limits and duplicate reports
  - the thread and internal notes, and assigning
  - what deciding each kind of case does
  - appeals by the person affected only, decided by another moderator
  - restoring a removed product
  - the notifications
- Type checks pass.
- On a local hub I went through every flow with the website's own forms: report from a product page; the catalog owner's note and decision; assigning, an internal note and a decision as admin; removal by a moderator, the creator's appeal from the audit log, the admin's decision and Restore; a creator's rating review and the decision lowering the rating; a deletion request and its decline; the notifications, the bell's count, and Mark all as read.
- Fixed along the way:
  - The catalog's team could see who reported.
  - A missing Resolve/Decline choice was treated as Decline; now it's refused.
  - The Unassign button sent the typed name instead of nothing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: dhkatz <[email protected]>
2026-11-05 22:14:08 +00:00

3319 lines
82 KiB
JSON

{
"id": "00353b8d-c368-4030-ae98-f1d4aa560b01",
"prevId": "0b410a02-49ab-42cc-82e6-45b3bd265602",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.account": {
"name": "account",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider_id": {
"name": "provider_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token_expires_at": {
"name": "access_token_expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"refresh_token_expires_at": {
"name": "refresh_token_expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp 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": {
"account_user": {
"name": "account_user",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"account_user_id_user_id_fk": {
"name": "account_user_id_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.age_check": {
"name": "age_check",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"imvu_id": {
"name": "imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"provider": {
"name": "provider",
"type": "text",
"primaryKey": false,
"notNull": true
},
"method": {
"name": "method",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true
},
"over_eighteen": {
"name": "over_eighteen",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"provider_ref": {
"name": "provider_ref",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"checked_at": {
"name": "checked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"age_check_user": {
"name": "age_check_user",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"age_check_imvu": {
"name": "age_check_imvu",
"columns": [
{
"expression": "imvu_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"age_check_provider_ref": {
"name": "age_check_provider_ref",
"columns": [
{
"expression": "provider",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "provider_ref",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"age_check_user_id_user_id_fk": {
"name": "age_check_user_id_user_id_fk",
"tableFrom": "age_check",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.audit": {
"name": "audit",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"at": {
"name": "at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"actor_id": {
"name": "actor_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"action": {
"name": "action",
"type": "text",
"primaryKey": false,
"notNull": true
},
"target": {
"name": "target",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"detail": {
"name": "detail",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
},
"tags": {
"name": "tags",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
}
},
"indexes": {
"audit_at": {
"name": "audit_at",
"columns": [
{
"expression": "at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"audit_tags": {
"name": "audit_tags",
"columns": [
{
"expression": "tags",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {
"audit_actor_id_user_id_fk": {
"name": "audit_actor_id_user_id_fk",
"tableFrom": "audit",
"tableTo": "user",
"columnsFrom": [
"actor_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.case_note": {
"name": "case_note",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"case_id": {
"name": "case_id",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"by_id": {
"name": "by_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"body": {
"name": "body",
"type": "text",
"primaryKey": false,
"notNull": true
},
"internal": {
"name": "internal",
"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": {
"case_note_case": {
"name": "case_note_case",
"columns": [
{
"expression": "case_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"case_note_case_id_moderation_case_id_fk": {
"name": "case_note_case_id_moderation_case_id_fk",
"tableFrom": "case_note",
"tableTo": "moderation_case",
"columnsFrom": [
"case_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"case_note_by_id_user_id_fk": {
"name": "case_note_by_id_user_id_fk",
"tableFrom": "case_note",
"tableTo": "user",
"columnsFrom": [
"by_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.catalog": {
"name": "catalog",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"owner_id": {
"name": "owner_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"url": {
"name": "url",
"type": "text",
"primaryKey": false,
"notNull": true
},
"contact": {
"name": "contact",
"type": "text",
"primaryKey": false,
"notNull": true
},
"visibility": {
"name": "visibility",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'public'"
},
"membership": {
"name": "membership",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'open'"
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"status_reason": {
"name": "status_reason",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"max_rating": {
"name": "max_rating",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'adult'"
},
"uploads": {
"name": "uploads",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'anyone'"
},
"mirrors": {
"name": "mirrors",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'approve'"
},
"key_hash": {
"name": "key_hash",
"type": "text",
"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": {
"catalog_url": {
"name": "catalog_url",
"columns": [
{
"expression": "url",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"catalog_owner_id_user_id_fk": {
"name": "catalog_owner_id_user_id_fk",
"tableFrom": "catalog",
"tableTo": "user",
"columnsFrom": [
"owner_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.catalog_change": {
"name": "catalog_change",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"catalog_id": {
"name": "catalog_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"catalog_change_catalog": {
"name": "catalog_change_catalog",
"columns": [
{
"expression": "catalog_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"catalog_change_catalog_id_catalog_id_fk": {
"name": "catalog_change_catalog_id_catalog_id_fk",
"tableFrom": "catalog_change",
"tableTo": "catalog",
"columnsFrom": [
"catalog_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.catalog_invite": {
"name": "catalog_invite",
"schema": "",
"columns": {
"code": {
"name": "code",
"type": "text",
"primaryKey": true,
"notNull": true
},
"catalog_id": {
"name": "catalog_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_by": {
"name": "created_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"max_uses": {
"name": "max_uses",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"uses": {
"name": "uses",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"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
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"catalog_invite_catalog": {
"name": "catalog_invite_catalog",
"columns": [
{
"expression": "catalog_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"catalog_invite_catalog_id_catalog_id_fk": {
"name": "catalog_invite_catalog_id_catalog_id_fk",
"tableFrom": "catalog_invite",
"tableTo": "catalog",
"columnsFrom": [
"catalog_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"catalog_invite_created_by_user_id_fk": {
"name": "catalog_invite_created_by_user_id_fk",
"tableFrom": "catalog_invite",
"tableTo": "user",
"columnsFrom": [
"created_by"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.catalog_member": {
"name": "catalog_member",
"schema": "",
"columns": {
"catalog_id": {
"name": "catalog_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true
},
"invite": {
"name": "invite",
"type": "text",
"primaryKey": false,
"notNull": false
},
"decided_by": {
"name": "decided_by",
"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": {
"catalog_member_user": {
"name": "catalog_member_user",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"catalog_member_catalog_id_catalog_id_fk": {
"name": "catalog_member_catalog_id_catalog_id_fk",
"tableFrom": "catalog_member",
"tableTo": "catalog",
"columnsFrom": [
"catalog_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"catalog_member_user_id_user_id_fk": {
"name": "catalog_member_user_id_user_id_fk",
"tableFrom": "catalog_member",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"catalog_member_decided_by_user_id_fk": {
"name": "catalog_member_decided_by_user_id_fk",
"tableFrom": "catalog_member",
"tableTo": "user",
"columnsFrom": [
"decided_by"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"catalog_member_catalog_id_user_id_pk": {
"name": "catalog_member_catalog_id_user_id_pk",
"columns": [
"catalog_id",
"user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.device_code": {
"name": "device_code",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"device_code": {
"name": "device_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_code": {
"name": "user_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true
},
"last_polled_at": {
"name": "last_polled_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"polling_interval": {
"name": "polling_interval",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"client_id": {
"name": "client_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"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": {
"device_code_user_id_user_id_fk": {
"name": "device_code_user_id_user_id_fk",
"tableFrom": "device_code",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosted_room": {
"name": "hosted_room",
"schema": "",
"columns": {
"n": {
"name": "n",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"owner_id": {
"name": "owner_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"owner_imvu_id": {
"name": "owner_imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"room_pid": {
"name": "room_pid",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"rating": {
"name": "rating",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'general'"
},
"max_users": {
"name": "max_users",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 10
},
"scene": {
"name": "scene",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'[]'::jsonb"
},
"scene_hash": {
"name": "scene_hash",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"closed": {
"name": "closed",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"privacy": {
"name": "privacy",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'public'"
},
"moderators": {
"name": "moderators",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'[]'::jsonb"
},
"image_hash": {
"name": "image_hash",
"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": {
"hosted_room_owner": {
"name": "hosted_room_owner",
"columns": [
{
"expression": "owner_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"hosted_room_created": {
"name": "hosted_room_created",
"columns": [
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"hosted_room_owner_id_user_id_fk": {
"name": "hosted_room_owner_id_user_id_fk",
"tableFrom": "hosted_room",
"tableTo": "user",
"columnsFrom": [
"owner_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosted_room_ban": {
"name": "hosted_room_ban",
"schema": "",
"columns": {
"n": {
"name": "n",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"imvu_id": {
"name": "imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"by_imvu_id": {
"name": "by_imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"until": {
"name": "until",
"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": {
"hosted_room_ban_n_hosted_room_n_fk": {
"name": "hosted_room_ban_n_hosted_room_n_fk",
"tableFrom": "hosted_room_ban",
"tableTo": "hosted_room",
"columnsFrom": [
"n"
],
"columnsTo": [
"n"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"hosted_room_ban_n_imvu_id_pk": {
"name": "hosted_room_ban_n_imvu_id_pk",
"columns": [
"n",
"imvu_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosted_room_favorite": {
"name": "hosted_room_favorite",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"n": {
"name": "n",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"hosted_room_favorite_user_id_user_id_fk": {
"name": "hosted_room_favorite_user_id_user_id_fk",
"tableFrom": "hosted_room_favorite",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"hosted_room_favorite_n_hosted_room_n_fk": {
"name": "hosted_room_favorite_n_hosted_room_n_fk",
"tableFrom": "hosted_room_favorite",
"tableTo": "hosted_room",
"columnsFrom": [
"n"
],
"columnsTo": [
"n"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"hosted_room_favorite_user_id_n_pk": {
"name": "hosted_room_favorite_user_id_n_pk",
"columns": [
"user_id",
"n"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosted_room_image": {
"name": "hosted_room_image",
"schema": "",
"columns": {
"n": {
"name": "n",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"content_type": {
"name": "content_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"data": {
"name": "data",
"type": "bytea",
"primaryKey": false,
"notNull": true
},
"hash": {
"name": "hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"hosted_room_image_n_hosted_room_n_fk": {
"name": "hosted_room_image_n_hosted_room_n_fk",
"tableFrom": "hosted_room_image",
"tableTo": "hosted_room",
"columnsFrom": [
"n"
],
"columnsTo": [
"n"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosted_room_rating": {
"name": "hosted_room_rating",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"n": {
"name": "n",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"score": {
"name": "score",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"hosted_room_rating_room": {
"name": "hosted_room_rating_room",
"columns": [
{
"expression": "n",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"hosted_room_rating_user_id_user_id_fk": {
"name": "hosted_room_rating_user_id_user_id_fk",
"tableFrom": "hosted_room_rating",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"hosted_room_rating_n_hosted_room_n_fk": {
"name": "hosted_room_rating_n_hosted_room_n_fk",
"tableFrom": "hosted_room_rating",
"tableTo": "hosted_room",
"columnsFrom": [
"n"
],
"columnsTo": [
"n"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"hosted_room_rating_user_id_n_pk": {
"name": "hosted_room_rating_user_id_n_pk",
"columns": [
"user_id",
"n"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosted_room_visit": {
"name": "hosted_room_visit",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"n": {
"name": "n",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"imvu_id": {
"name": "imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"at": {
"name": "at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"hosted_room_visit_at": {
"name": "hosted_room_visit_at",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"hosted_room_visit_user_id_user_id_fk": {
"name": "hosted_room_visit_user_id_user_id_fk",
"tableFrom": "hosted_room_visit",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"hosted_room_visit_n_hosted_room_n_fk": {
"name": "hosted_room_visit_n_hosted_room_n_fk",
"tableFrom": "hosted_room_visit",
"tableTo": "hosted_room",
"columnsFrom": [
"n"
],
"columnsTo": [
"n"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"hosted_room_visit_user_id_n_pk": {
"name": "hosted_room_visit_user_id_n_pk",
"columns": [
"user_id",
"n"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hosting": {
"name": "hosting",
"schema": "",
"columns": {
"catalog_id": {
"name": "catalog_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"number": {
"name": "number",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"hosting_product": {
"name": "hosting_product",
"columns": [
{
"expression": "product_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"hosting_catalog_id_catalog_id_fk": {
"name": "hosting_catalog_id_catalog_id_fk",
"tableFrom": "hosting",
"tableTo": "catalog",
"columnsFrom": [
"catalog_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"hosting_catalog_id_product_id_number_pk": {
"name": "hosting_catalog_id_product_id_number_pk",
"columns": [
"catalog_id",
"product_id",
"number"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.hub_setting": {
"name": "hub_setting",
"schema": "",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true
},
"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.imvu_link": {
"name": "imvu_link",
"schema": "",
"columns": {
"imvu_id": {
"name": "imvu_id",
"type": "bigint",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"pairwise_id": {
"name": "pairwise_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"linked_at": {
"name": "linked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"show_badge": {
"name": "show_badge",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"show_presence": {
"name": "show_presence",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"list_rooms": {
"name": "list_rooms",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
}
},
"indexes": {
"imvu_link_user": {
"name": "imvu_link_user",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"imvu_link_user_id_user_id_fk": {
"name": "imvu_link_user_id_user_id_fk",
"tableFrom": "imvu_link",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"imvu_link_pairwise_id_unique": {
"name": "imvu_link_pairwise_id_unique",
"nullsNotDistinct": false,
"columns": [
"pairwise_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.jwks": {
"name": "jwks",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"public_key": {
"name": "public_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"private_key": {
"name": "private_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"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": false
},
"alg": {
"name": "alg",
"type": "text",
"primaryKey": false,
"notNull": false
},
"crv": {
"name": "crv",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.library": {
"name": "library",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"stay_on": {
"name": "stay_on",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"added_at": {
"name": "added_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"library_user_id_user_id_fk": {
"name": "library_user_id_user_id_fk",
"tableFrom": "library",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"library_product_id_product_id_fk": {
"name": "library_product_id_product_id_fk",
"tableFrom": "library",
"tableTo": "product",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"library_user_id_product_id_pk": {
"name": "library_user_id_product_id_pk",
"columns": [
"user_id",
"product_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.link_challenge": {
"name": "link_challenge",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"imvu_id": {
"name": "imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true
},
"code": {
"name": "code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"link_challenge_user_id_user_id_fk": {
"name": "link_challenge_user_id_user_id_fk",
"tableFrom": "link_challenge",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"link_challenge_user_id_imvu_id_pk": {
"name": "link_challenge_user_id_imvu_id_pk",
"columns": [
"user_id",
"imvu_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.moderation_case": {
"name": "moderation_case",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"kind": {
"name": "kind",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'open'"
},
"tags": {
"name": "tags",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
},
"opened_by": {
"name": "opened_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"assignee": {
"name": "assignee",
"type": "text",
"primaryKey": false,
"notNull": false
},
"reason": {
"name": "reason",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
},
"resolution": {
"name": "resolution",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"decided_by": {
"name": "decided_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"decided_at": {
"name": "decided_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": {
"moderation_case_status": {
"name": "moderation_case_status",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"moderation_case_opened_by": {
"name": "moderation_case_opened_by",
"columns": [
{
"expression": "opened_by",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"moderation_case_tags": {
"name": "moderation_case_tags",
"columns": [
{
"expression": "tags",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {
"moderation_case_opened_by_user_id_fk": {
"name": "moderation_case_opened_by_user_id_fk",
"tableFrom": "moderation_case",
"tableTo": "user",
"columnsFrom": [
"opened_by"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"moderation_case_assignee_user_id_fk": {
"name": "moderation_case_assignee_user_id_fk",
"tableFrom": "moderation_case",
"tableTo": "user",
"columnsFrom": [
"assignee"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"moderation_case_decided_by_user_id_fk": {
"name": "moderation_case_decided_by_user_id_fk",
"tableFrom": "moderation_case",
"tableTo": "user",
"columnsFrom": [
"decided_by"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.notification": {
"name": "notification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"tags": {
"name": "tags",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"read_at": {
"name": "read_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"notification_user": {
"name": "notification_user",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"notification_user_id_user_id_fk": {
"name": "notification_user_id_user_id_fk",
"tableFrom": "notification",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.product": {
"name": "product",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"creator_id": {
"name": "creator_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"rating": {
"name": "rating",
"type": "text",
"primaryKey": false,
"notNull": true
},
"latest": {
"name": "latest",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'published'"
},
"published_at": {
"name": "published_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"listed": {
"name": "listed",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"tags": {
"name": "tags",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'[]'::jsonb"
},
"category": {
"name": "category",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"locked": {
"name": "locked",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'[]'::jsonb"
},
"deleted_at": {
"name": "deleted_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"removed_at": {
"name": "removed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"removed_reason": {
"name": "removed_reason",
"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": {
"product_creator": {
"name": "product_creator",
"columns": [
{
"expression": "creator_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"product_created": {
"name": "product_created",
"columns": [
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"product_tags": {
"name": "product_tags",
"columns": [
{
"expression": "tags",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "gin",
"with": {}
}
},
"foreignKeys": {
"product_creator_id_user_id_fk": {
"name": "product_creator_id_user_id_fk",
"tableFrom": "product",
"tableTo": "user",
"columnsFrom": [
"creator_id"
],
"columnsTo": [
"id"
],
"onDelete": "restrict",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.product_info_change": {
"name": "product_info_change",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"by_id": {
"name": "by_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"kind": {
"name": "kind",
"type": "text",
"primaryKey": false,
"notNull": true
},
"changes": {
"name": "changes",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"reason": {
"name": "reason",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"revert_of": {
"name": "revert_of",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"product_info_change_product": {
"name": "product_info_change_product",
"columns": [
{
"expression": "product_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"product_info_change_product_id_product_id_fk": {
"name": "product_info_change_product_id_product_id_fk",
"tableFrom": "product_info_change",
"tableTo": "product",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"product_info_change_by_id_user_id_fk": {
"name": "product_info_change_by_id_user_id_fk",
"tableFrom": "product_info_change",
"tableTo": "user",
"columnsFrom": [
"by_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.product_revision": {
"name": "product_revision",
"schema": "",
"columns": {
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"number": {
"name": "number",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"files": {
"name": "files",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"rating": {
"name": "rating",
"type": "text",
"primaryKey": false,
"notNull": true
},
"parent": {
"name": "parent",
"type": "bigint",
"primaryKey": false,
"notNull": true,
"default": 0
},
"parent_info": {
"name": "parent_info",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"uploaded_by": {
"name": "uploaded_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"retracted": {
"name": "retracted",
"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": {},
"foreignKeys": {
"product_revision_product_id_product_id_fk": {
"name": "product_revision_product_id_product_id_fk",
"tableFrom": "product_revision",
"tableTo": "product",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"product_revision_uploaded_by_user_id_fk": {
"name": "product_revision_uploaded_by_user_id_fk",
"tableFrom": "product_revision",
"tableTo": "user",
"columnsFrom": [
"uploaded_by"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"product_revision_product_id_number_pk": {
"name": "product_revision_product_id_number_pk",
"columns": [
"product_id",
"number"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.role_assignment": {
"name": "role_assignment",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true
},
"scope_type": {
"name": "scope_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"scope_id": {
"name": "scope_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"granted_by": {
"name": "granted_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"role_assignment_scope": {
"name": "role_assignment_scope",
"columns": [
{
"expression": "scope_type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "scope_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"role_assignment_user_id_user_id_fk": {
"name": "role_assignment_user_id_user_id_fk",
"tableFrom": "role_assignment",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"role_assignment_granted_by_user_id_fk": {
"name": "role_assignment_granted_by_user_id_fk",
"tableFrom": "role_assignment",
"tableTo": "user",
"columnsFrom": [
"granted_by"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"role_assignment_user_id_role_scope_type_scope_id_pk": {
"name": "role_assignment_user_id_role_scope_type_scope_id_pk",
"columns": [
"user_id",
"role",
"scope_type",
"scope_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.room": {
"name": "room",
"schema": "",
"columns": {
"instance_id": {
"name": "instance_id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"owner_imvu_id": {
"name": "owner_imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"image_url": {
"name": "image_url",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"privacy": {
"name": "privacy",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"content_rating": {
"name": "content_rating",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"access_pass": {
"name": "access_pass",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"occupancy": {
"name": "occupancy",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"capacity": {
"name": "capacity",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"expired": {
"name": "expired",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"checked_at": {
"name": "checked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"seen_at": {
"name": "seen_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"room_owner": {
"name": "room_owner",
"columns": [
{
"expression": "owner_imvu_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.room_decoration": {
"name": "room_decoration",
"schema": "",
"columns": {
"instance_id": {
"name": "instance_id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"owner_imvu_id": {
"name": "owner_imvu_id",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"contents": {
"name": "contents",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"room_decoration_owner": {
"name": "room_decoration_owner",
"columns": [
{
"expression": "owner_imvu_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.session": {
"name": "session",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"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()"
},
"ip_address": {
"name": "ip_address",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"impersonated_by": {
"name": "impersonated_by",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"session_user": {
"name": "session_user",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"session_user_id_user_id_fk": {
"name": "session_user_id_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"session_token_unique": {
"name": "session_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.signing_key": {
"name": "signing_key",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"public_key": {
"name": "public_key",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"private_key": {
"name": "private_key",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user": {
"name": "user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email_verified": {
"name": "email_verified",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"image": {
"name": "image",
"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()"
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": false
},
"display_username": {
"name": "display_username",
"type": "text",
"primaryKey": false,
"notNull": false
},
"role": {
"name": "role",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"banned": {
"name": "banned",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"ban_reason": {
"name": "ban_reason",
"type": "text",
"primaryKey": false,
"notNull": false
},
"ban_expires": {
"name": "ban_expires",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"link_cap": {
"name": "link_cap",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 10
},
"approved": {
"name": "approved",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
}
},
"indexes": {
"user_username_lower": {
"name": "user_username_lower",
"columns": [
{
"expression": "lower(\"username\")",
"asc": true,
"isExpression": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"user_email_unique": {
"name": "user_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
},
"user_username_unique": {
"name": "user_username_unique",
"nullsNotDistinct": false,
"columns": [
"username"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.verification": {
"name": "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 with time zone",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"verification_identifier": {
"name": "verification_identifier",
"columns": [
{
"expression": "identifier",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}