Fas 2 steg 2: Inventory Trust Engine - decay-profiler och cache-jobb

This commit is contained in:
Sven (AAMOS AI)
2026-08-06 23:25:32 +07:00
parent 8ae4bf6ec3
commit bcf932d2ff
17 changed files with 18296 additions and 61 deletions
+16
View File
@@ -2,6 +2,7 @@ import { createHash, randomBytes, randomUUID } from "node:crypto";
import { and, eq } from "drizzle-orm";
import type { Database } from "@app/database";
import { schema } from "@app/database";
import type { DecayProfile } from "@app/inventory-engine";
import type { EventType } from "@app/shared-types";
import type { NewDomainEvent } from "@app/events";
import { errors } from "./errors.js";
@@ -145,3 +146,18 @@ export async function audit(
export function newCorrelationId(): string {
return randomUUID();
}
/** Hämta den aktiva trust-decay-profilen. Cachas i praktiken av databasen;
* funktionen returnerar alltid en giltig profil (default fallback). */
export async function getActiveDecayProfile(db: Database): Promise<DecayProfile> {
const [profile] = await db
.select({ halfLifeDays: schema.inventoryDecayProfiles.halfLifeDays, staleAfterDays: schema.inventoryDecayProfiles.staleAfterDays })
.from(schema.inventoryDecayProfiles)
.where(eq(schema.inventoryDecayProfiles.active, true))
.orderBy(schema.inventoryDecayProfiles.createdAt)
.limit(1);
return {
halfLifeDays: profile?.halfLifeDays ?? 7,
staleAfterDays: profile?.staleAfterDays ?? 30,
};
}
+37 -6
View File
@@ -10,7 +10,7 @@ import {
} from "@app/validation";
import { classifyExpiry, findDuplicateCandidates, normalizeDelta, computeTrust } from "@app/inventory-engine";
import { errors, parse } from "../lib/errors.js";
import { emitEvent, requireActiveHousehold, requireMembership } from "../lib/helpers.js";
import { emitEvent, getActiveDecayProfile, requireActiveHousehold, requireMembership } from "../lib/helpers.js";
/**
* Food Twin lagret (spec §8). Transaktionsbaserat: varje förändring skrivs
@@ -22,6 +22,7 @@ export async function inventoryRoutes(app: FastifyInstance) {
app.get("/v1/inventory", auth, async (req) => {
const query = parse(inventoryQuerySchema, req.query);
const householdId = await requireActiveHousehold(app.db, req.userId);
const decayProfile = await getActiveDecayProfile(app.db);
const conditions = [
eq(schema.inventoryItems.householdId, householdId),
@@ -73,11 +74,24 @@ export async function inventoryRoutes(app: FastifyInstance) {
storageLocationType: r.locationType,
shelfLifeGuidance: r.shelfLife,
});
const trust = computeTrust(
{
confidence: r.item.confidence,
verifiedByUser: r.item.verifiedByUser,
lastVerifiedAt: r.item.lastVerifiedAt,
quantity: r.item.quantity,
updatedAt: r.item.updatedAt,
},
new Date(),
decayProfile,
);
return {
...r.item,
locationName: r.locationName,
locationType: r.locationType,
expiry,
trustState: trust.state,
trustScore: trust.score,
};
});
@@ -90,6 +104,7 @@ export async function inventoryRoutes(app: FastifyInstance) {
/** Varor som bör användas snart driver "använd först" (spec §4.4, §40). */
app.get("/v1/inventory/expiring", auth, async (req) => {
const householdId = await requireActiveHousehold(app.db, req.userId);
const decayProfile = await getActiveDecayProfile(app.db);
const rows = await app.db
.select({
item: schema.inventoryItems,
@@ -114,9 +129,8 @@ export async function inventoryRoutes(app: FastifyInstance) {
);
const withExpiry = rows
.map((r) => ({
...r.item,
expiry: classifyExpiry({
.map((r) => {
const expiry = classifyExpiry({
bestBeforeDate: r.item.bestBeforeDate,
useByDate: r.item.useByDate,
openedAt: r.item.openedAt,
@@ -125,8 +139,25 @@ export async function inventoryRoutes(app: FastifyInstance) {
purchasedAt: r.item.purchasedAt,
storageLocationType: r.locationType,
shelfLifeGuidance: r.shelfLife,
}),
}))
});
const trust = computeTrust(
{
confidence: r.item.confidence,
verifiedByUser: r.item.verifiedByUser,
lastVerifiedAt: r.item.lastVerifiedAt,
quantity: r.item.quantity,
updatedAt: r.item.updatedAt,
},
new Date(),
decayProfile,
);
return {
...r.item,
expiry,
trustState: trust.state,
trustScore: trust.score,
};
})
.filter(
(i) =>
i.expiry.status === "expiring" ||
+108
View File
@@ -0,0 +1,108 @@
import "./setup-env.js";
import { describe, expect, it, beforeAll, afterAll } from "vitest";
import { eq, inArray } from "drizzle-orm";
import { buildServer } from "../src/server.js";
import { loadConfig } from "../src/config.js";
import { createDatabase, closeDatabase, schema } from "@app/database";
describe("inventory trust read-time computation", () => {
const testDb = createDatabase(process.env.TEST_DATABASE_URL!);
const config = loadConfig();
let app: Awaited<ReturnType<typeof buildServer>>;
let accessToken: string;
let householdId: string;
let locationId: string;
const userEmail = "trust-read@example.invalid";
async function cleanup() {
const existing = await testDb.db
.select({ id: schema.users.id })
.from(schema.users)
.where(inArray(schema.users.email, [userEmail]));
for (const u of existing) {
await testDb.db.delete(schema.inventoryTransactions).where(eq(schema.inventoryTransactions.actorUserId, u.id));
const owned = await testDb.db
.select({ id: schema.households.id })
.from(schema.households)
.innerJoin(schema.householdMembers, eq(schema.householdMembers.householdId, schema.households.id))
.where(eq(schema.householdMembers.userId, u.id));
for (const h of owned) {
await testDb.db.delete(schema.inventoryItems).where(eq(schema.inventoryItems.householdId, h.id));
await testDb.db.delete(schema.storageLocations).where(eq(schema.storageLocations.householdId, h.id));
await testDb.db.delete(schema.households).where(eq(schema.households.id, h.id));
}
await testDb.db.delete(schema.householdMembers).where(eq(schema.householdMembers.userId, u.id));
await testDb.db.delete(schema.userPreferences).where(eq(schema.userPreferences.userId, u.id));
await testDb.db.delete(schema.users).where(eq(schema.users.id, u.id));
}
}
beforeAll(async () => {
await cleanup();
app = await buildServer(config);
await app.ready();
const res = await app.inject({
method: "POST",
url: "/v1/auth/register",
payload: { email: userEmail, password: "Password123!", displayName: "Trust" },
});
const body = JSON.parse(res.body) as { accessToken: string };
accessToken = body.accessToken;
const quick = await app.inject({
method: "POST",
url: "/v1/onboarding/quick-start",
headers: { authorization: `Bearer ${accessToken}` },
payload: { goals: ["cook_more"], precisionMode: "simple" },
});
const quickBody = JSON.parse(quick.body) as { householdId: string };
householdId = quickBody.householdId;
const [location] = await testDb.db
.select()
.from(schema.storageLocations)
.where(eq(schema.storageLocations.householdId, householdId))
.limit(1);
locationId = location!.id;
});
afterAll(async () => {
await cleanup();
await closeDatabase();
await app.close();
});
it("reports decaying/stale for items with old lastVerifiedAt without a write", async () => {
const fortyDaysAgo = new Date(Date.now() - 40 * 86_400_000);
const [item] = await testDb.db
.insert(schema.inventoryItems)
.values({
householdId,
displayName: "Gammal mjölk",
quantity: 1,
unit: "LITER",
storageLocationId: locationId,
source: "manual_search",
confidence: 0.6,
verifiedByUser: true,
lastVerifiedAt: fortyDaysAgo,
updatedAt: fortyDaysAgo,
})
.returning();
const res = await app.inject({
method: "GET",
url: "/v1/inventory",
headers: { authorization: `Bearer ${accessToken}` },
});
expect(res.statusCode).toBe(200);
const body = JSON.parse(res.body) as { items: Array<{ id: string; trustState: string; trustScore: number }> };
const found = body.items.find((i) => i.id === item!.id);
expect(found).toBeTruthy();
expect(["decaying", "stale"]).toContain(found!.trustState);
expect(found!.trustScore).toBeLessThan(60);
});
});
+12
View File
@@ -16,6 +16,7 @@ import {
processStoreNotification,
processSubscriptionSweep,
processTrainingExport,
processTrustDecay,
} from "./processors/maintenance.js";
import {
@@ -110,6 +111,12 @@ const worker = new Worker(
return;
}
case "UPDATE_TRUST_STATES": {
const updated = await processTrustDecay(ctx);
if (updated > 0) log(`Trust decay: ${updated} items uppdaterade`);
return;
}
// Deterministiska/planerade jobb som inte kräver egen processor ännu
case "NORMALIZE_PRODUCTS":
case "DEDUPLICATE_INVENTORY":
@@ -201,6 +208,11 @@ async function registerRepeatableJobs() {
{ every: 30_000 },
{ name: "PUBLISH_OUTBOX", data: { jobType: "PUBLISH_OUTBOX" }, opts: baseOpts },
);
await queue.upsertJobScheduler(
"scheduler-trust",
{ every: 300_000 },
{ name: "UPDATE_TRUST_STATES", data: { jobType: "UPDATE_TRUST_STATES" }, opts: baseOpts },
);
await queue.upsertJobScheduler(
"scheduler-expiry",
{ pattern: "0 7 * * *", tz: "Europe/Stockholm" },
+53 -1
View File
@@ -1,6 +1,6 @@
import { and, eq, gt, inArray, isNull, lte, sql } from "drizzle-orm";
import { schema } from "@app/database";
import { classifyExpiry } from "@app/inventory-engine";
import { classifyExpiry, computeTrust } from "@app/inventory-engine";
import { deriveMemoryUpdates } from "@app/memory-client";
import { getLocaleContext } from "../locale.js";
import type { WorkerContext } from "../context.js";
@@ -31,6 +31,58 @@ export async function processOutbox(ctx: WorkerContext): Promise<number> {
return pending.length;
}
/**
* UPDATE_TRUST_STATES (Fas 2 §5.2): uppdatera cache-kolumnen inventory_items.trust_state
* utifrån aktiv decay-profil. Körs periodiskt. Decay påverkar endast förtroende,
* aldrig ätbarhet (mjölkprincipen D-035).
*/
export async function processTrustDecay(ctx: WorkerContext): Promise<number> {
const [profile] = await ctx.db
.select({
halfLifeDays: schema.inventoryDecayProfiles.halfLifeDays,
staleAfterDays: schema.inventoryDecayProfiles.staleAfterDays,
})
.from(schema.inventoryDecayProfiles)
.where(eq(schema.inventoryDecayProfiles.active, true))
.orderBy(schema.inventoryDecayProfiles.createdAt)
.limit(1);
const decayProfile = {
halfLifeDays: profile?.halfLifeDays ?? 7,
staleAfterDays: profile?.staleAfterDays ?? 30,
};
const now = new Date();
const rows = await ctx.db
.select()
.from(schema.inventoryItems)
.where(and(isNull(schema.inventoryItems.depletedAt), gt(schema.inventoryItems.quantity, 0)))
.limit(500);
let updated = 0;
for (const item of rows) {
const { state } = computeTrust(
{
confidence: item.confidence,
verifiedByUser: item.verifiedByUser,
lastVerifiedAt: item.lastVerifiedAt,
quantity: item.quantity,
updatedAt: item.updatedAt,
},
now,
decayProfile,
);
if (state !== item.trustState) {
await ctx.db
.update(schema.inventoryItems)
.set({ trustState: state, updatedAt: now })
.where(eq(schema.inventoryItems.id, item.id));
updated++;
}
}
return updated;
}
/** SEND_EXPIRY_NOTIFICATION (spec §54): skapa notiser för varor som snart går ut. */
export async function processExpiryNotifications(ctx: WorkerContext): Promise<number> {
const households = await ctx.db.select({ id: schema.households.id }).from(schema.households);
@@ -0,0 +1,3 @@
ALTER TABLE "inventory_items" ALTER COLUMN "trust_state" SET DATA TYPE varchar(16);--> statement-breakpoint
ALTER TABLE "inventory_items" ALTER COLUMN "trust_state" SET DEFAULT 'unverified';--> statement-breakpoint
DROP TYPE "public"."trust_state";
@@ -0,0 +1,19 @@
CREATE TABLE "inventory_decay_profiles" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(64) NOT NULL,
"description" text,
"half_life_days" double precision DEFAULT 7 NOT NULL,
"stale_after_days" integer DEFAULT 30 NOT NULL,
"active" boolean DEFAULT true NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "inventory_decay_profiles_name_unique" UNIQUE("name")
);
--> statement-breakpoint
CREATE TABLE "inventory_item_decay_profile" (
"inventory_item_id" uuid PRIMARY KEY NOT NULL,
"decay_profile_id" uuid NOT NULL
);
--> statement-breakpoint
ALTER TABLE "inventory_item_decay_profile" ADD CONSTRAINT "inventory_item_decay_profile_inventory_item_id_inventory_items_id_fk" FOREIGN KEY ("inventory_item_id") REFERENCES "public"."inventory_items"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "inventory_item_decay_profile" ADD CONSTRAINT "inventory_item_decay_profile_decay_profile_id_inventory_decay_profiles_id_fk" FOREIGN KEY ("decay_profile_id") REFERENCES "public"."inventory_decay_profiles"("id") ON DELETE restrict ON UPDATE no action;
@@ -0,0 +1,8865 @@
{
"id": "b26aaf39-2905-4816-9575-ac7e429c3a28",
"prevId": "a3870bb9-6526-4977-bf4d-312899f6a7b9",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.admin_totp": {
"name": "admin_totp",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"secret_base32": {
"name": "secret_base32",
"type": "text",
"primaryKey": false,
"notNull": true
},
"enabled_at": {
"name": "enabled_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_used_step": {
"name": "last_used_step",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"admin_totp_user_id_users_id_fk": {
"name": "admin_totp_user_id_users_id_fk",
"tableFrom": "admin_totp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.email_verification_tokens": {
"name": "email_verification_tokens",
"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
},
"token_hash": {
"name": "token_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"used_at": {
"name": "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()"
}
},
"indexes": {
"email_verification_tokens_user_idx": {
"name": "email_verification_tokens_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"email_verification_tokens_hash_unique": {
"name": "email_verification_tokens_hash_unique",
"columns": [
{
"expression": "token_hash",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"email_verification_tokens_user_id_users_id_fk": {
"name": "email_verification_tokens_user_id_users_id_fk",
"tableFrom": "email_verification_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.password_reset_tokens": {
"name": "password_reset_tokens",
"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
},
"token_hash": {
"name": "token_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"used_at": {
"name": "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()"
}
},
"indexes": {
"password_reset_tokens_user_idx": {
"name": "password_reset_tokens_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"password_reset_tokens_hash_unique": {
"name": "password_reset_tokens_hash_unique",
"columns": [
{
"expression": "token_hash",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"password_reset_tokens_user_id_users_id_fk": {
"name": "password_reset_tokens_user_id_users_id_fk",
"tableFrom": "password_reset_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.refresh_tokens": {
"name": "refresh_tokens",
"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
},
"token_hash": {
"name": "token_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"family_id": {
"name": "family_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"revoked_at": {
"name": "revoked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"replaced_by_token_id": {
"name": "replaced_by_token_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false
},
"ip": {
"name": "ip",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"refresh_tokens_user_idx": {
"name": "refresh_tokens_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"refresh_tokens_hash_unique": {
"name": "refresh_tokens_hash_unique",
"columns": [
{
"expression": "token_hash",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"refresh_tokens_user_id_users_id_fk": {
"name": "refresh_tokens_user_id_users_id_fk",
"tableFrom": "refresh_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_consents": {
"name": "user_consents",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"kind": {
"name": "kind",
"type": "consent_kind",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "consent_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"granted_at": {
"name": "granted_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"revoked_at": {
"name": "revoked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_consents_user_id_users_id_fk": {
"name": "user_consents_user_id_users_id_fk",
"tableFrom": "user_consents",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"user_consents_user_id_kind_pk": {
"name": "user_consents_user_id_kind_pk",
"columns": [
"user_id",
"kind"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_credentials": {
"name": "user_credentials",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"password_hash": {
"name": "password_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password_updated_at": {
"name": "password_updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_credentials_user_id_users_id_fk": {
"name": "user_credentials_user_id_users_id_fk",
"tableFrom": "user_credentials",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_health_profiles": {
"name": "user_health_profiles",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"birth_year": {
"name": "birth_year",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"sex": {
"name": "sex",
"type": "sex",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"height_cm": {
"name": "height_cm",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"weight_kg": {
"name": "weight_kg",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"target_weight_kg": {
"name": "target_weight_kg",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"activity_level": {
"name": "activity_level",
"type": "activity_level",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'moderate'"
},
"training_sessions_per_week": {
"name": "training_sessions_per_week",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"training_types": {
"name": "training_types",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_health_profiles_user_id_users_id_fk": {
"name": "user_health_profiles_user_id_users_id_fk",
"tableFrom": "user_health_profiles",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_preferences": {
"name": "user_preferences",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"primary_goal": {
"name": "primary_goal",
"type": "goal_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"goals": {
"name": "goals",
"type": "goal_type[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"diet_pattern": {
"name": "diet_pattern",
"type": "diet_pattern",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'omnivore'"
},
"religious_rule": {
"name": "religious_rule",
"type": "religious_rule",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'none'"
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"intolerances": {
"name": "intolerances",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"avoid_ingredient_ids": {
"name": "avoid_ingredient_ids",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"favorite_cuisines": {
"name": "favorite_cuisines",
"type": "cuisine[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"disliked_dishes": {
"name": "disliked_dishes",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"spice_level_max": {
"name": "spice_level_max",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 3
},
"weekly_budget_minor": {
"name": "weekly_budget_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"max_cooking_minutes_weekday": {
"name": "max_cooking_minutes_weekday",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"equipment": {
"name": "equipment",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"default_portions": {
"name": "default_portions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 2
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_preferences_user_id_users_id_fk": {
"name": "user_preferences_user_id_users_id_fk",
"tableFrom": "user_preferences",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email_verified_at": {
"name": "email_verified_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "user_role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"locale": {
"name": "locale",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'sv-SE'"
},
"precision_mode": {
"name": "precision_mode",
"type": "precision_mode",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'simple'"
},
"onboarding_completed": {
"name": "onboarding_completed",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"onboarding_step": {
"name": "onboarding_step",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'a'"
},
"deleted_at": {
"name": "deleted_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": {
"users_email_unique": {
"name": "users_email_unique",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_locale_preferences": {
"name": "user_locale_preferences",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'sv-SE'"
},
"region_code": {
"name": "region_code",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SE'"
},
"time_zone": {
"name": "time_zone",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'Europe/Stockholm'"
},
"measurement_system": {
"name": "measurement_system",
"type": "measurement_system",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'METRIC'"
},
"temperature_unit": {
"name": "temperature_unit",
"type": "temperature_unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'CELSIUS'"
},
"currency_code": {
"name": "currency_code",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SEK'"
},
"first_day_of_week": {
"name": "first_day_of_week",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 1
},
"use_24_hour_time": {
"name": "use_24_hour_time",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_locale_preferences_user_id_users_id_fk": {
"name": "user_locale_preferences_user_id_users_id_fk",
"tableFrom": "user_locale_preferences",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.household_members": {
"name": "household_members",
"schema": "",
"columns": {
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "household_role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'member'"
},
"portion_factor": {
"name": "portion_factor",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"joined_at": {
"name": "joined_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"household_members_user_idx": {
"name": "household_members_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"household_members_household_id_households_id_fk": {
"name": "household_members_household_id_households_id_fk",
"tableFrom": "household_members",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"household_members_user_id_users_id_fk": {
"name": "household_members_user_id_users_id_fk",
"tableFrom": "household_members",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"household_members_household_id_user_id_pk": {
"name": "household_members_household_id_user_id_pk",
"columns": [
"household_id",
"user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.households": {
"name": "households",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"invite_code": {
"name": "invite_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"weekly_budget_minor": {
"name": "weekly_budget_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"first_scan_completed_at": {
"name": "first_scan_completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"fifth_item_confirmed_at": {
"name": "fifth_item_confirmed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"first_recipe_recommendation_viewed_at": {
"name": "first_recipe_recommendation_viewed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"first_recipe_saved_or_started_at": {
"name": "first_recipe_saved_or_started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"activated_at": {
"name": "activated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"first_cooking_session_completed_at": {
"name": "first_cooking_session_completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"inventory_updated_after_cooking_at": {
"name": "inventory_updated_after_cooking_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"value_confirmed_at": {
"name": "value_confirmed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"currency_code": {
"name": "currency_code",
"type": "varchar(3)",
"primaryKey": false,
"notNull": true,
"default": "'SEK'"
},
"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": {
"households_invite_code_unique": {
"name": "households_invite_code_unique",
"columns": [
{
"expression": "invite_code",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.storage_locations": {
"name": "storage_locations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "storage_location_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"sublocations": {
"name": "sublocations",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"storage_locations_household_idx": {
"name": "storage_locations_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"storage_locations_household_id_households_id_fk": {
"name": "storage_locations_household_id_households_id_fk",
"tableFrom": "storage_locations",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.canonical_ingredients": {
"name": "canonical_ingredients",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_en": {
"name": "name_en",
"type": "text",
"primaryKey": false,
"notNull": true
},
"aliases": {
"name": "aliases",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"category": {
"name": "category",
"type": "text",
"primaryKey": false,
"notNull": true
},
"default_unit": {
"name": "default_unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"density_g_per_ml": {
"name": "density_g_per_ml",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"grams_per_piece": {
"name": "grams_per_piece",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"is_vegan": {
"name": "is_vegan",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_vegetarian": {
"name": "is_vegetarian",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"contains_gluten": {
"name": "contains_gluten",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"contains_lactose": {
"name": "contains_lactose",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_pork": {
"name": "is_pork",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_beef": {
"name": "is_beef",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_alcohol": {
"name": "is_alcohol",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"nutrition_per_100": {
"name": "nutrition_per_100",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"nutrition_provenance": {
"name": "nutrition_provenance",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"peak_seasons": {
"name": "peak_seasons",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"shelf_life_guidance": {
"name": "shelf_life_guidance",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"default_price_minor_per_kg": {
"name": "default_price_minor_per_kg",
"type": "integer",
"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": {
"canonical_ingredients_category_idx": {
"name": "canonical_ingredients_category_idx",
"columns": [
{
"expression": "category",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.substitutions": {
"name": "substitutions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"from_ingredient_id": {
"name": "from_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"to_ingredient_id": {
"name": "to_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"ratio": {
"name": "ratio",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"instructions_sv": {
"name": "instructions_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"best_for": {
"name": "best_for",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"not_recommended_for": {
"name": "not_recommended_for",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"flavor_impact_sv": {
"name": "flavor_impact_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"texture_impact_sv": {
"name": "texture_impact_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"priority": {
"name": "priority",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"substitutions_from_idx": {
"name": "substitutions_from_idx",
"columns": [
{
"expression": "from_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"substitutions_pair_unique": {
"name": "substitutions_pair_unique",
"columns": [
{
"expression": "from_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "to_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"substitutions_from_ingredient_id_canonical_ingredients_id_fk": {
"name": "substitutions_from_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "substitutions",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"from_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"substitutions_to_ingredient_id_canonical_ingredients_id_fk": {
"name": "substitutions_to_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "substitutions",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"to_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.products": {
"name": "products",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"gtin": {
"name": "gtin",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"brand": {
"name": "brand",
"type": "text",
"primaryKey": false,
"notNull": false
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"package_size_value": {
"name": "package_size_value",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"package_size_unit": {
"name": "package_size_unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"ingredients_text": {
"name": "ingredients_text",
"type": "text",
"primaryKey": false,
"notNull": false
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"may_contain_allergens": {
"name": "may_contain_allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"nutrition": {
"name": "nutrition",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"image_urls": {
"name": "image_urls",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"language": {
"name": "language",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'sv'"
},
"market": {
"name": "market",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SE'"
},
"data_source": {
"name": "data_source",
"type": "text",
"primaryKey": false,
"notNull": true
},
"verification_status": {
"name": "verification_status",
"type": "verification_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'unverified'"
},
"version": {
"name": "version",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 1
},
"valid_from": {
"name": "valid_from",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"valid_to": {
"name": "valid_to",
"type": "timestamp with time zone",
"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": {
"products_gtin_version_unique": {
"name": "products_gtin_version_unique",
"columns": [
{
"expression": "gtin",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "version",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"where": "\"products\".\"gtin\" IS NOT NULL",
"concurrently": false,
"method": "btree",
"with": {}
},
"products_gtin_current_idx": {
"name": "products_gtin_current_idx",
"columns": [
{
"expression": "gtin",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"products\".\"valid_to\" IS NULL",
"concurrently": false,
"method": "btree",
"with": {}
},
"products_canonical_idx": {
"name": "products_canonical_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"products_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "products_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "products",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.inventory_items": {
"name": "inventory_items",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"brand": {
"name": "brand",
"type": "text",
"primaryKey": false,
"notNull": false
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"storage_location_id": {
"name": "storage_location_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"sublocation": {
"name": "sublocation",
"type": "text",
"primaryKey": false,
"notNull": false
},
"purchased_at": {
"name": "purchased_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"opened_at": {
"name": "opened_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"best_before_date": {
"name": "best_before_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"use_by_date": {
"name": "use_by_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"date_kind": {
"name": "date_kind",
"type": "date_kind",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"frozen_at": {
"name": "frozen_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"thawed_at": {
"name": "thawed_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"price_minor": {
"name": "price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"nutrition_per_100": {
"name": "nutrition_per_100",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"source": {
"name": "source",
"type": "inventory_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"confidence": {
"name": "confidence",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"verified_by_user": {
"name": "verified_by_user",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"last_verified_at": {
"name": "last_verified_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expiry_status": {
"name": "expiry_status",
"type": "expiry_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'unknown'"
},
"trust_state": {
"name": "trust_state",
"type": "varchar(16)",
"primaryKey": false,
"notNull": true,
"default": "'unverified'"
},
"depleted_at": {
"name": "depleted_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prompt_version": {
"name": "prompt_version",
"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": {
"inventory_items_household_idx": {
"name": "inventory_items_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_items_household_bb_idx": {
"name": "inventory_items_household_bb_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "best_before_date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_items_location_idx": {
"name": "inventory_items_location_idx",
"columns": [
{
"expression": "storage_location_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_items_canonical_idx": {
"name": "inventory_items_canonical_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"inventory_items_household_id_households_id_fk": {
"name": "inventory_items_household_id_households_id_fk",
"tableFrom": "inventory_items",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_items_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "inventory_items_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "inventory_items",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"inventory_items_product_id_products_id_fk": {
"name": "inventory_items_product_id_products_id_fk",
"tableFrom": "inventory_items",
"tableTo": "products",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"inventory_items_storage_location_id_storage_locations_id_fk": {
"name": "inventory_items_storage_location_id_storage_locations_id_fk",
"tableFrom": "inventory_items",
"tableTo": "storage_locations",
"columnsFrom": [
"storage_location_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.inventory_transactions": {
"name": "inventory_transactions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"inventory_item_id": {
"name": "inventory_item_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "inventory_transaction_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"quantity_delta": {
"name": "quantity_delta",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"ref_type": {
"name": "ref_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"ref_id": {
"name": "ref_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"actor_user_id": {
"name": "actor_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"note": {
"name": "note",
"type": "text",
"primaryKey": false,
"notNull": false
},
"value_minor": {
"name": "value_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"inventory_tx_item_idx": {
"name": "inventory_tx_item_idx",
"columns": [
{
"expression": "inventory_item_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_tx_household_time_idx": {
"name": "inventory_tx_household_time_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_tx_type_idx": {
"name": "inventory_tx_type_idx",
"columns": [
{
"expression": "type",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"inventory_transactions_household_id_households_id_fk": {
"name": "inventory_transactions_household_id_households_id_fk",
"tableFrom": "inventory_transactions",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_transactions_inventory_item_id_inventory_items_id_fk": {
"name": "inventory_transactions_inventory_item_id_inventory_items_id_fk",
"tableFrom": "inventory_transactions",
"tableTo": "inventory_items",
"columnsFrom": [
"inventory_item_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_transactions_actor_user_id_users_id_fk": {
"name": "inventory_transactions_actor_user_id_users_id_fk",
"tableFrom": "inventory_transactions",
"tableTo": "users",
"columnsFrom": [
"actor_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_cooks": {
"name": "recipe_cooks",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"portions_cooked": {
"name": "portions_cooked",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"cooked_at": {
"name": "cooked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"recipe_cooks_recipe_idx": {
"name": "recipe_cooks_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_cooks_user_idx": {
"name": "recipe_cooks_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_cooks_recipe_id_recipes_id_fk": {
"name": "recipe_cooks_recipe_id_recipes_id_fk",
"tableFrom": "recipe_cooks",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_cooks_user_id_users_id_fk": {
"name": "recipe_cooks_user_id_users_id_fk",
"tableFrom": "recipe_cooks",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_favorites": {
"name": "recipe_favorites",
"schema": "",
"columns": {
"recipe_id": {
"name": "recipe_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": {
"recipe_favorites_user_idx": {
"name": "recipe_favorites_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_favorites_recipe_id_recipes_id_fk": {
"name": "recipe_favorites_recipe_id_recipes_id_fk",
"tableFrom": "recipe_favorites",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_favorites_user_id_users_id_fk": {
"name": "recipe_favorites_user_id_users_id_fk",
"tableFrom": "recipe_favorites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"recipe_favorites_recipe_id_user_id_pk": {
"name": "recipe_favorites_recipe_id_user_id_pk",
"columns": [
"recipe_id",
"user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_ingredients": {
"name": "recipe_ingredients",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"display_name_sv": {
"name": "display_name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"note": {
"name": "note",
"type": "text",
"primaryKey": false,
"notNull": false
},
"optional": {
"name": "optional",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"group_name": {
"name": "group_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"recipe_ingredients_recipe_idx": {
"name": "recipe_ingredients_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_ingredients_canonical_idx": {
"name": "recipe_ingredients_canonical_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_ingredients_recipe_id_recipes_id_fk": {
"name": "recipe_ingredients_recipe_id_recipes_id_fk",
"tableFrom": "recipe_ingredients",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_ingredients_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "recipe_ingredients_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "recipe_ingredients",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_ratings": {
"name": "recipe_ratings",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stars": {
"name": "stars",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"feedback_tags": {
"name": "feedback_tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"comment": {
"name": "comment",
"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": {
"recipe_ratings_user_recipe_unique": {
"name": "recipe_ratings_user_recipe_unique",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_ratings_recipe_idx": {
"name": "recipe_ratings_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_ratings_recipe_id_recipes_id_fk": {
"name": "recipe_ratings_recipe_id_recipes_id_fk",
"tableFrom": "recipe_ratings",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_ratings_user_id_users_id_fk": {
"name": "recipe_ratings_user_id_users_id_fk",
"tableFrom": "recipe_ratings",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_similarities": {
"name": "recipe_similarities",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_a_id": {
"name": "recipe_a_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"recipe_b_id": {
"name": "recipe_b_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"similarity_score": {
"name": "similarity_score",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"classification": {
"name": "classification",
"type": "recipe_similarity_class",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"details": {
"name": "details",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"recipe_similarities_pair_unique": {
"name": "recipe_similarities_pair_unique",
"columns": [
{
"expression": "recipe_a_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "recipe_b_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_similarities_recipe_a_id_recipes_id_fk": {
"name": "recipe_similarities_recipe_a_id_recipes_id_fk",
"tableFrom": "recipe_similarities",
"tableTo": "recipes",
"columnsFrom": [
"recipe_a_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_similarities_recipe_b_id_recipes_id_fk": {
"name": "recipe_similarities_recipe_b_id_recipes_id_fk",
"tableFrom": "recipe_similarities",
"tableTo": "recipes",
"columnsFrom": [
"recipe_b_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_source_registry": {
"name": "recipe_source_registry",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"source_name": {
"name": "source_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"license": {
"name": "license",
"type": "text",
"primaryKey": false,
"notNull": true
},
"right_to_store": {
"name": "right_to_store",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"right_to_modify": {
"name": "right_to_modify",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"right_to_display": {
"name": "right_to_display",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"attribution_required": {
"name": "attribution_required",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"attribution_text": {
"name": "attribution_text",
"type": "text",
"primaryKey": false,
"notNull": false
},
"commercial_use": {
"name": "commercial_use",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"valid_from": {
"name": "valid_from",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"valid_to": {
"name": "valid_to",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false
},
"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.recipe_steps": {
"name": "recipe_steps",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"step_number": {
"name": "step_number",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"instruction_sv": {
"name": "instruction_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"timer_seconds": {
"name": "timer_seconds",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"temperature_c": {
"name": "temperature_c",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"tip": {
"name": "tip",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"recipe_steps_recipe_idx": {
"name": "recipe_steps_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_steps_recipe_step_unique": {
"name": "recipe_steps_recipe_step_unique",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "step_number",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_steps_recipe_id_recipes_id_fk": {
"name": "recipe_steps_recipe_id_recipes_id_fk",
"tableFrom": "recipe_steps",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipes": {
"name": "recipes",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"slug": {
"name": "slug",
"type": "text",
"primaryKey": false,
"notNull": true
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description_sv": {
"name": "description_sv",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"country": {
"name": "country",
"type": "text",
"primaryKey": false,
"notNull": false
},
"region": {
"name": "region",
"type": "text",
"primaryKey": false,
"notNull": false
},
"cuisine": {
"name": "cuisine",
"type": "cuisine",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"meal_types": {
"name": "meal_types",
"type": "meal_type[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"tags": {
"name": "tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"methods": {
"name": "methods",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"equipment": {
"name": "equipment",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"difficulty": {
"name": "difficulty",
"type": "recipe_difficulty",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'easy'"
},
"prep_time_minutes": {
"name": "prep_time_minutes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"cook_time_minutes": {
"name": "cook_time_minutes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"total_time_minutes": {
"name": "total_time_minutes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"portions": {
"name": "portions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 4
},
"nutrition_per_portion": {
"name": "nutrition_per_portion",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"spice_level": {
"name": "spice_level",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"estimated_cost_minor_per_portion": {
"name": "estimated_cost_minor_per_portion",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"storage_guidance_sv": {
"name": "storage_guidance_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"meal_prep_friendly": {
"name": "meal_prep_friendly",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"freezer_friendly": {
"name": "freezer_friendly",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"peak_seasons": {
"name": "peak_seasons",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"holiday_tags": {
"name": "holiday_tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"dna": {
"name": "dna",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"variant_type": {
"name": "variant_type",
"type": "recipe_variant_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'standard'"
},
"variant_of_recipe_id": {
"name": "variant_of_recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"forked_from_recipe_id": {
"name": "forked_from_recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "recipe_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'draft'"
},
"verification_status": {
"name": "verification_status",
"type": "recipe_verification_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'unverified'"
},
"source_type": {
"name": "source_type",
"type": "recipe_source_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"source_registry_id": {
"name": "source_registry_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"creator_user_id": {
"name": "creator_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"creator_display_name": {
"name": "creator_display_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"image_urls": {
"name": "image_urls",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"version": {
"name": "version",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 1
},
"rating_average": {
"name": "rating_average",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"rating_count": {
"name": "rating_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"cook_count": {
"name": "cook_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"favorite_count": {
"name": "favorite_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"moderation_note": {
"name": "moderation_note",
"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": {
"recipes_slug_unique": {
"name": "recipes_slug_unique",
"columns": [
{
"expression": "slug",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_status_idx": {
"name": "recipes_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_cuisine_idx": {
"name": "recipes_cuisine_idx",
"columns": [
{
"expression": "cuisine",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_variant_of_idx": {
"name": "recipes_variant_of_idx",
"columns": [
{
"expression": "variant_of_recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_creator_idx": {
"name": "recipes_creator_idx",
"columns": [
{
"expression": "creator_user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_total_time_idx": {
"name": "recipes_total_time_idx",
"columns": [
{
"expression": "total_time_minutes",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipes_source_registry_id_recipe_source_registry_id_fk": {
"name": "recipes_source_registry_id_recipe_source_registry_id_fk",
"tableFrom": "recipes",
"tableTo": "recipe_source_registry",
"columnsFrom": [
"source_registry_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"recipes_creator_user_id_users_id_fk": {
"name": "recipes_creator_user_id_users_id_fk",
"tableFrom": "recipes",
"tableTo": "users",
"columnsFrom": [
"creator_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ingredient_translations": {
"name": "ingredient_translations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"ingredient_id": {
"name": "ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"aliases": {
"name": "aliases",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"source": {
"name": "source",
"type": "translation_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'seed'"
},
"status": {
"name": "status",
"type": "translation_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'published'"
},
"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": {
"ingredient_translations_unique": {
"name": "ingredient_translations_unique",
"columns": [
{
"expression": "ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"ingredient_translations_lang_idx": {
"name": "ingredient_translations_lang_idx",
"columns": [
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"ingredient_translations_ingredient_id_canonical_ingredients_id_fk": {
"name": "ingredient_translations_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "ingredient_translations",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_step_translations": {
"name": "recipe_step_translations",
"schema": "",
"columns": {
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"step_number": {
"name": "step_number",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"instruction": {
"name": "instruction",
"type": "text",
"primaryKey": false,
"notNull": true
},
"tip": {
"name": "tip",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"recipe_step_translations_recipe_id_recipes_id_fk": {
"name": "recipe_step_translations_recipe_id_recipes_id_fk",
"tableFrom": "recipe_step_translations",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"recipe_step_translations_recipe_id_language_tag_step_number_pk": {
"name": "recipe_step_translations_recipe_id_language_tag_step_number_pk",
"columns": [
"recipe_id",
"language_tag",
"step_number"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_translations": {
"name": "recipe_translations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"storage_guidance": {
"name": "storage_guidance",
"type": "text",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "translation_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'draft_ai'"
},
"source": {
"name": "source",
"type": "translation_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'ai'"
},
"verification": {
"name": "verification",
"type": "jsonb",
"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": {
"recipe_translations_unique": {
"name": "recipe_translations_unique",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_translations_lang_idx": {
"name": "recipe_translations_lang_idx",
"columns": [
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_translations_recipe_id_recipes_id_fk": {
"name": "recipe_translations_recipe_id_recipes_id_fk",
"tableFrom": "recipe_translations",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.unit_translations": {
"name": "unit_translations",
"schema": "",
"columns": {
"unit_code": {
"name": "unit_code",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"abbreviation": {
"name": "abbreviation",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"unit_translations_unit_code_language_tag_pk": {
"name": "unit_translations_unit_code_language_tag_pk",
"columns": [
"unit_code",
"language_tag"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.allergen_market_rules": {
"name": "allergen_market_rules",
"schema": "",
"columns": {
"region_code": {
"name": "region_code",
"type": "varchar(2)",
"primaryKey": false,
"notNull": true
},
"allergen": {
"name": "allergen",
"type": "allergen",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"must_highlight": {
"name": "must_highlight",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"allergen_market_rules_region_code_allergen_pk": {
"name": "allergen_market_rules_region_code_allergen_pk",
"columns": [
"region_code",
"allergen"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.nutrition_display_profiles": {
"name": "nutrition_display_profiles",
"schema": "",
"columns": {
"region_code": {
"name": "region_code",
"type": "varchar(2)",
"primaryKey": true,
"notNull": true
},
"energy_display": {
"name": "energy_display",
"type": "text",
"primaryKey": false,
"notNull": true
},
"salt_display": {
"name": "salt_display",
"type": "text",
"primaryKey": false,
"notNull": true
},
"energy_label_key": {
"name": "energy_label_key",
"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": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.meal_boxes": {
"name": "meal_boxes",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"portions": {
"name": "portions",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"portions_remaining": {
"name": "portions_remaining",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"nutrition_per_portion": {
"name": "nutrition_per_portion",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"cooked_at": {
"name": "cooked_at",
"type": "date",
"primaryKey": false,
"notNull": true
},
"storage_location_id": {
"name": "storage_location_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"frozen": {
"name": "frozen",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"recommended_use_by": {
"name": "recommended_use_by",
"type": "date",
"primaryKey": false,
"notNull": true
},
"reserved_for_user_id": {
"name": "reserved_for_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'available'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"meal_boxes_household_idx": {
"name": "meal_boxes_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"meal_boxes_use_by_idx": {
"name": "meal_boxes_use_by_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "recommended_use_by",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"meal_boxes_household_id_households_id_fk": {
"name": "meal_boxes_household_id_households_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"meal_boxes_recipe_id_recipes_id_fk": {
"name": "meal_boxes_recipe_id_recipes_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"meal_boxes_storage_location_id_storage_locations_id_fk": {
"name": "meal_boxes_storage_location_id_storage_locations_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "storage_locations",
"columnsFrom": [
"storage_location_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"meal_boxes_reserved_for_user_id_users_id_fk": {
"name": "meal_boxes_reserved_for_user_id_users_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "users",
"columnsFrom": [
"reserved_for_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.meals": {
"name": "meals",
"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
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"date": {
"name": "date",
"type": "date",
"primaryKey": false,
"notNull": true
},
"meal_type": {
"name": "meal_type",
"type": "meal_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"source": {
"name": "source",
"type": "meal_log_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"portion_fraction": {
"name": "portion_fraction",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"nutrition": {
"name": "nutrition",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"nutrition_is_estimate": {
"name": "nutrition_is_estimate",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"estimate_min_kcal": {
"name": "estimate_min_kcal",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"estimate_max_kcal": {
"name": "estimate_max_kcal",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"items": {
"name": "items",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"photo_url": {
"name": "photo_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scan_job_id": {
"name": "scan_job_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"logged_at": {
"name": "logged_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"meals_user_date_idx": {
"name": "meals_user_date_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"meals_household_idx": {
"name": "meals_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"meals_user_id_users_id_fk": {
"name": "meals_user_id_users_id_fk",
"tableFrom": "meals",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"meals_household_id_households_id_fk": {
"name": "meals_household_id_households_id_fk",
"tableFrom": "meals",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"meals_recipe_id_recipes_id_fk": {
"name": "meals_recipe_id_recipes_id_fk",
"tableFrom": "meals",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.shopping_list_items": {
"name": "shopping_list_items",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"shopping_list_id": {
"name": "shopping_list_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'COUNT'"
},
"store_section": {
"name": "store_section",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'hygien_ovrigt'"
},
"suggested_package_size": {
"name": "suggested_package_size",
"type": "text",
"primaryKey": false,
"notNull": false
},
"estimated_price_minor": {
"name": "estimated_price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"checked": {
"name": "checked",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"added_by_user_id": {
"name": "added_by_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"origin": {
"name": "origin",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'manual'"
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"shopping_list_items_list_idx": {
"name": "shopping_list_items_list_idx",
"columns": [
{
"expression": "shopping_list_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"shopping_list_items_shopping_list_id_shopping_lists_id_fk": {
"name": "shopping_list_items_shopping_list_id_shopping_lists_id_fk",
"tableFrom": "shopping_list_items",
"tableTo": "shopping_lists",
"columnsFrom": [
"shopping_list_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"shopping_list_items_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "shopping_list_items_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "shopping_list_items",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"shopping_list_items_added_by_user_id_users_id_fk": {
"name": "shopping_list_items_added_by_user_id_users_id_fk",
"tableFrom": "shopping_list_items",
"tableTo": "users",
"columnsFrom": [
"added_by_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.shopping_lists": {
"name": "shopping_lists",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'Inköpslista'"
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'active'"
},
"week_plan_id": {
"name": "week_plan_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": {
"shopping_lists_household_idx": {
"name": "shopping_lists_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"shopping_lists_household_id_households_id_fk": {
"name": "shopping_lists_household_id_households_id_fk",
"tableFrom": "shopping_lists",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"shopping_lists_week_plan_id_week_plans_id_fk": {
"name": "shopping_lists_week_plan_id_week_plans_id_fk",
"tableFrom": "shopping_lists",
"tableTo": "week_plans",
"columnsFrom": [
"week_plan_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.week_plan_entries": {
"name": "week_plan_entries",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"week_plan_id": {
"name": "week_plan_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"date": {
"name": "date",
"type": "date",
"primaryKey": false,
"notNull": true
},
"meal_type": {
"name": "meal_type",
"type": "meal_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"meal_box_id": {
"name": "meal_box_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"portions": {
"name": "portions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 2
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'planned'"
},
"reschedule_reason_sv": {
"name": "reschedule_reason_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"week_plan_entries_plan_idx": {
"name": "week_plan_entries_plan_idx",
"columns": [
{
"expression": "week_plan_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"week_plan_entries_week_plan_id_week_plans_id_fk": {
"name": "week_plan_entries_week_plan_id_week_plans_id_fk",
"tableFrom": "week_plan_entries",
"tableTo": "week_plans",
"columnsFrom": [
"week_plan_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"week_plan_entries_recipe_id_recipes_id_fk": {
"name": "week_plan_entries_recipe_id_recipes_id_fk",
"tableFrom": "week_plan_entries",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"week_plan_entries_meal_box_id_meal_boxes_id_fk": {
"name": "week_plan_entries_meal_box_id_meal_boxes_id_fk",
"tableFrom": "week_plan_entries",
"tableTo": "meal_boxes",
"columnsFrom": [
"meal_box_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.week_plans": {
"name": "week_plans",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"week_start_date": {
"name": "week_start_date",
"type": "date",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'draft'"
},
"generated_by": {
"name": "generated_by",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"notes": {
"name": "notes",
"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": {
"week_plans_household_week_idx": {
"name": "week_plans_household_week_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "week_start_date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"week_plans_household_id_households_id_fk": {
"name": "week_plans_household_id_households_id_fk",
"tableFrom": "week_plans",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.price_observations": {
"name": "price_observations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"store_name": {
"name": "store_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"price_minor": {
"name": "price_minor",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"price_per_kg_minor": {
"name": "price_per_kg_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"observed_at": {
"name": "observed_at",
"type": "date",
"primaryKey": false,
"notNull": true
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'receipt'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"price_observations_ingredient_idx": {
"name": "price_observations_ingredient_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "observed_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"price_observations_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "price_observations_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "price_observations",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"price_observations_product_id_products_id_fk": {
"name": "price_observations_product_id_products_id_fk",
"tableFrom": "price_observations",
"tableTo": "products",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.receipt_lines": {
"name": "receipt_lines",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"receipt_id": {
"name": "receipt_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"raw_text": {
"name": "raw_text",
"type": "text",
"primaryKey": false,
"notNull": true
},
"normalized_name": {
"name": "normalized_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"unit_price_minor": {
"name": "unit_price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"total_price_minor": {
"name": "total_price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"confidence": {
"name": "confidence",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0
},
"verified_by_user": {
"name": "verified_by_user",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"added_to_inventory": {
"name": "added_to_inventory",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
}
},
"indexes": {
"receipt_lines_receipt_idx": {
"name": "receipt_lines_receipt_idx",
"columns": [
{
"expression": "receipt_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"receipt_lines_receipt_id_receipts_id_fk": {
"name": "receipt_lines_receipt_id_receipts_id_fk",
"tableFrom": "receipt_lines",
"tableTo": "receipts",
"columnsFrom": [
"receipt_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"receipt_lines_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "receipt_lines_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "receipt_lines",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"receipt_lines_product_id_products_id_fk": {
"name": "receipt_lines_product_id_products_id_fk",
"tableFrom": "receipt_lines",
"tableTo": "products",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.receipts": {
"name": "receipts",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"store_name": {
"name": "store_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"purchase_date": {
"name": "purchase_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"total_minor": {
"name": "total_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"discount_minor": {
"name": "discount_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"image_url": {
"name": "image_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scan_job_id": {
"name": "scan_job_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"receipts_household_idx": {
"name": "receipts_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "purchase_date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"receipts_household_id_households_id_fk": {
"name": "receipts_household_id_households_id_fk",
"tableFrom": "receipts",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_corrections": {
"name": "ai_corrections",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"scan_job_id": {
"name": "scan_job_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"task_type": {
"name": "task_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"ai_output": {
"name": "ai_output",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"user_correction": {
"name": "user_correction",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prompt_version": {
"name": "prompt_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"consent_snapshot": {
"name": "consent_snapshot",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"exported_to_training": {
"name": "exported_to_training",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"training_batch_id": {
"name": "training_batch_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"ai_corrections_task_idx": {
"name": "ai_corrections_task_idx",
"columns": [
{
"expression": "task_type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"ai_corrections_scan_job_id_scan_jobs_id_fk": {
"name": "ai_corrections_scan_job_id_scan_jobs_id_fk",
"tableFrom": "ai_corrections",
"tableTo": "scan_jobs",
"columnsFrom": [
"scan_job_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"ai_corrections_user_id_users_id_fk": {
"name": "ai_corrections_user_id_users_id_fk",
"tableFrom": "ai_corrections",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.scan_jobs": {
"name": "scan_jobs",
"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
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"scan_type": {
"name": "scan_type",
"type": "scan_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"job_type": {
"name": "job_type",
"type": "job_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "job_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'queued'"
},
"s3_keys": {
"name": "s3_keys",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"context": {
"name": "context",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"result": {
"name": "result",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"error": {
"name": "error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prompt_version": {
"name": "prompt_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"latency_ms": {
"name": "latency_ms",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"cost_usd": {
"name": "cost_usd",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"attempts": {
"name": "attempts",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"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": {
"scan_jobs_user_idx": {
"name": "scan_jobs_user_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": {}
},
"scan_jobs_status_idx": {
"name": "scan_jobs_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"scan_jobs_user_id_users_id_fk": {
"name": "scan_jobs_user_id_users_id_fk",
"tableFrom": "scan_jobs",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"scan_jobs_household_id_households_id_fk": {
"name": "scan_jobs_household_id_households_id_fk",
"tableFrom": "scan_jobs",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.food_memories": {
"name": "food_memories",
"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": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"summary_sv": {
"name": "summary_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"holiday_tag": {
"name": "holiday_tag",
"type": "text",
"primaryKey": false,
"notNull": false
},
"photo_url": {
"name": "photo_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"stars": {
"name": "stars",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"occurred_at": {
"name": "occurred_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()"
}
},
"indexes": {
"food_memories_household_idx": {
"name": "food_memories_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"food_memories_holiday_idx": {
"name": "food_memories_holiday_idx",
"columns": [
{
"expression": "holiday_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"food_memories_user_id_users_id_fk": {
"name": "food_memories_user_id_users_id_fk",
"tableFrom": "food_memories",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"food_memories_household_id_households_id_fk": {
"name": "food_memories_household_id_households_id_fk",
"tableFrom": "food_memories",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"food_memories_recipe_id_recipes_id_fk": {
"name": "food_memories_recipe_id_recipes_id_fk",
"tableFrom": "food_memories",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.memory_items": {
"name": "memory_items",
"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": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"kind": {
"name": "kind",
"type": "memory_kind",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"summary_sv": {
"name": "summary_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"value": {
"name": "value",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"origin": {
"name": "origin",
"type": "signal_origin",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"confidence": {
"name": "confidence",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0.5
},
"verified_by_user": {
"name": "verified_by_user",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"paused": {
"name": "paused",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"last_used_at": {
"name": "last_used_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "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": {
"memory_items_user_idx": {
"name": "memory_items_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "kind",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"memory_items_household_idx": {
"name": "memory_items_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "kind",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"memory_items_key_idx": {
"name": "memory_items_key_idx",
"columns": [
{
"expression": "key",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"memory_items_user_id_users_id_fk": {
"name": "memory_items_user_id_users_id_fk",
"tableFrom": "memory_items",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"memory_items_household_id_households_id_fk": {
"name": "memory_items_household_id_households_id_fk",
"tableFrom": "memory_items",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.taste_signals": {
"name": "taste_signals",
"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
},
"axis": {
"name": "axis",
"type": "taste_axis",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"direction": {
"name": "direction",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"strength": {
"name": "strength",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0.5
},
"origin": {
"name": "origin",
"type": "signal_origin",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"ref_recipe_id": {
"name": "ref_recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"taste_signals_user_idx": {
"name": "taste_signals_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "axis",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"taste_signals_user_id_users_id_fk": {
"name": "taste_signals_user_id_users_id_fk",
"tableFrom": "taste_signals",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"taste_signals_ref_recipe_id_recipes_id_fk": {
"name": "taste_signals_ref_recipe_id_recipes_id_fk",
"tableFrom": "taste_signals",
"tableTo": "recipes",
"columnsFrom": [
"ref_recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.season_events": {
"name": "season_events",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"slug": {
"name": "slug",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"market": {
"name": "market",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SE'"
},
"date_rule": {
"name": "date_rule",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"lead_days": {
"name": "lead_days",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 7
},
"food_tags": {
"name": "food_tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"recipe_slugs": {
"name": "recipe_slugs",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"priority": {
"name": "priority",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"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": {
"season_events_slug_market_unique": {
"name": "season_events_slug_market_unique",
"columns": [
{
"expression": "slug",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "market",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_usage_counters": {
"name": "ai_usage_counters",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"month": {
"name": "month",
"type": "text",
"primaryKey": false,
"notNull": true
},
"ai_scans": {
"name": "ai_scans",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"ai_tokens_in": {
"name": "ai_tokens_in",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"ai_tokens_out": {
"name": "ai_tokens_out",
"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": {
"ai_usage_user_month_unique": {
"name": "ai_usage_user_month_unique",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "month",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"ai_usage_counters_user_id_users_id_fk": {
"name": "ai_usage_counters_user_id_users_id_fk",
"tableFrom": "ai_usage_counters",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.store_notifications": {
"name": "store_notifications",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"provider": {
"name": "provider",
"type": "subscription_provider",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"notification_type": {
"name": "notification_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"raw_payload": {
"name": "raw_payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"signature_verified": {
"name": "signature_verified",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"processed": {
"name": "processed",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"processed_at": {
"name": "processed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"error": {
"name": "error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"store_notifications_pending_idx": {
"name": "store_notifications_pending_idx",
"columns": [
{
"expression": "processed",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.store_transactions": {
"name": "store_transactions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"provider": {
"name": "provider",
"type": "subscription_provider",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"transaction_id": {
"name": "transaction_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"original_transaction_id": {
"name": "original_transaction_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"raw_payload": {
"name": "raw_payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"processed_at": {
"name": "processed_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": {
"store_transactions_unique": {
"name": "store_transactions_unique",
"columns": [
{
"expression": "provider",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "transaction_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"store_transactions_user_id_users_id_fk": {
"name": "store_transactions_user_id_users_id_fk",
"tableFrom": "store_transactions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.subscription_events": {
"name": "subscription_events",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"subscription_id": {
"name": "subscription_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"event_type": {
"name": "event_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"payload": {
"name": "payload",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"subscription_events_sub_idx": {
"name": "subscription_events_sub_idx",
"columns": [
{
"expression": "subscription_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"subscription_events_subscription_id_subscriptions_id_fk": {
"name": "subscription_events_subscription_id_subscriptions_id_fk",
"tableFrom": "subscription_events",
"tableTo": "subscriptions",
"columnsFrom": [
"subscription_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"subscription_events_user_id_users_id_fk": {
"name": "subscription_events_user_id_users_id_fk",
"tableFrom": "subscription_events",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.subscriptions": {
"name": "subscriptions",
"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
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"provider": {
"name": "provider",
"type": "subscription_provider",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"plan": {
"name": "plan",
"type": "subscription_plan",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"original_transaction_id": {
"name": "original_transaction_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "subscription_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"purchased_at": {
"name": "purchased_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"grace_period_expires_at": {
"name": "grace_period_expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"canceled_at": {
"name": "canceled_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_verified_at": {
"name": "last_verified_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": {
"subscriptions_user_idx": {
"name": "subscriptions_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"subscriptions_original_tx_unique": {
"name": "subscriptions_original_tx_unique",
"columns": [
{
"expression": "provider",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "original_transaction_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"where": "\"subscriptions\".\"original_transaction_id\" IS NOT NULL",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"subscriptions_user_id_users_id_fk": {
"name": "subscriptions_user_id_users_id_fk",
"tableFrom": "subscriptions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"subscriptions_household_id_households_id_fk": {
"name": "subscriptions_household_id_households_id_fk",
"tableFrom": "subscriptions",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.trials": {
"name": "trials",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"started_at": {
"name": "started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"ends_at": {
"name": "ends_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"trials_user_id_users_id_fk": {
"name": "trials_user_id_users_id_fk",
"tableFrom": "trials",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.analytics_daily_snapshots": {
"name": "analytics_daily_snapshots",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"date": {
"name": "date",
"type": "varchar(10)",
"primaryKey": false,
"notNull": true
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"event_name": {
"name": "event_name",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"count": {
"name": "count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"unique_sessions": {
"name": "unique_sessions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"properties_fingerprint": {
"name": "properties_fingerprint",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"pa_daily_household_date_idx": {
"name": "pa_daily_household_date_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_daily_date_event_idx": {
"name": "pa_daily_date_event_idx",
"columns": [
{
"expression": "date",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "event_name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"analytics_daily_snapshots_household_id_households_id_fk": {
"name": "analytics_daily_snapshots_household_id_households_id_fk",
"tableFrom": "analytics_daily_snapshots",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.product_analytics_events": {
"name": "product_analytics_events",
"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()"
},
"received_at": {
"name": "received_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"event_name": {
"name": "event_name",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"anonymous_id": {
"name": "anonymous_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"session_id": {
"name": "session_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"app_version": {
"name": "app_version",
"type": "varchar(32)",
"primaryKey": false,
"notNull": false
},
"platform": {
"name": "platform",
"type": "varchar(16)",
"primaryKey": false,
"notNull": false
},
"locale": {
"name": "locale",
"type": "varchar(16)",
"primaryKey": false,
"notNull": false
},
"experiment_variant": {
"name": "experiment_variant",
"type": "varchar(128)",
"primaryKey": false,
"notNull": false
},
"properties": {
"name": "properties",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
}
},
"indexes": {
"pa_events_name_occurred_idx": {
"name": "pa_events_name_occurred_idx",
"columns": [
{
"expression": "event_name",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_household_occurred_idx": {
"name": "pa_events_household_occurred_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_user_occurred_idx": {
"name": "pa_events_user_occurred_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_session_idx": {
"name": "pa_events_session_idx",
"columns": [
{
"expression": "session_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_received_idx": {
"name": "pa_events_received_idx",
"columns": [
{
"expression": "received_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"product_analytics_events_user_id_users_id_fk": {
"name": "product_analytics_events_user_id_users_id_fk",
"tableFrom": "product_analytics_events",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"product_analytics_events_household_id_households_id_fk": {
"name": "product_analytics_events_household_id_households_id_fk",
"tableFrom": "product_analytics_events",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_eval_cases": {
"name": "ai_eval_cases",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"task_type": {
"name": "task_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"input_ref": {
"name": "input_ref",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"expected_output": {
"name": "expected_output",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"category": {
"name": "category",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'standard'"
},
"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()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_eval_runs": {
"name": "ai_eval_runs",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"task_type": {
"name": "task_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": true
},
"prompt_version": {
"name": "prompt_version",
"type": "text",
"primaryKey": false,
"notNull": true
},
"metrics": {
"name": "metrics",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"passed": {
"name": "passed",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"ai_eval_runs_task_idx": {
"name": "ai_eval_runs_task_idx",
"columns": [
{
"expression": "task_type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.audit_logs": {
"name": "audit_logs",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"actor_user_id": {
"name": "actor_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"actor_type": {
"name": "actor_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"action": {
"name": "action",
"type": "text",
"primaryKey": false,
"notNull": true
},
"target_type": {
"name": "target_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"target_id": {
"name": "target_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"ip": {
"name": "ip",
"type": "text",
"primaryKey": false,
"notNull": false
},
"correlation_id": {
"name": "correlation_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"audit_logs_actor_idx": {
"name": "audit_logs_actor_idx",
"columns": [
{
"expression": "actor_user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"audit_logs_action_idx": {
"name": "audit_logs_action_idx",
"columns": [
{
"expression": "action",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.creator_follows": {
"name": "creator_follows",
"schema": "",
"columns": {
"follower_user_id": {
"name": "follower_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"creator_user_id": {
"name": "creator_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": {
"creator_follows_follower_user_id_users_id_fk": {
"name": "creator_follows_follower_user_id_users_id_fk",
"tableFrom": "creator_follows",
"tableTo": "users",
"columnsFrom": [
"follower_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"creator_follows_creator_user_id_users_id_fk": {
"name": "creator_follows_creator_user_id_users_id_fk",
"tableFrom": "creator_follows",
"tableTo": "users",
"columnsFrom": [
"creator_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"creator_follows_follower_user_id_creator_user_id_pk": {
"name": "creator_follows_follower_user_id_creator_user_id_pk",
"columns": [
"follower_user_id",
"creator_user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.creator_stats": {
"name": "creator_stats",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"visibility": {
"name": "visibility",
"type": "profile_visibility",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'private'"
},
"level": {
"name": "level",
"type": "creator_level",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'beginner'"
},
"published_recipes": {
"name": "published_recipes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"followers": {
"name": "followers",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"total_cooks": {
"name": "total_cooks",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"total_favorites": {
"name": "total_favorites",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"average_rating": {
"name": "average_rating",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"verified_recipes": {
"name": "verified_recipes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"badges": {
"name": "badges",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"creator_stats_user_id_users_id_fk": {
"name": "creator_stats_user_id_users_id_fk",
"tableFrom": "creator_stats",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.domain_events": {
"name": "domain_events",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"type": {
"name": "type",
"type": "event_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"payload": {
"name": "payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"correlation_id": {
"name": "correlation_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"occurred_at": {
"name": "occurred_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"published_at": {
"name": "published_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"domain_events_unpublished_idx": {
"name": "domain_events_unpublished_idx",
"columns": [
{
"expression": "published_at",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"domain_events_type_idx": {
"name": "domain_events_type_idx",
"columns": [
{
"expression": "type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"domain_events_household_idx": {
"name": "domain_events_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.feature_flags": {
"name": "feature_flags",
"schema": "",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"enabled": {
"name": "enabled",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"description_sv": {
"name": "description_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"rollout_percent": {
"name": "rollout_percent",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 100
},
"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.idempotency_keys": {
"name": "idempotency_keys",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"endpoint": {
"name": "endpoint",
"type": "text",
"primaryKey": false,
"notNull": true
},
"response_status": {
"name": "response_status",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"response_body": {
"name": "response_body",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"idempotency_keys_user_id_users_id_fk": {
"name": "idempotency_keys_user_id_users_id_fk",
"tableFrom": "idempotency_keys",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"idempotency_keys_user_id_key_endpoint_pk": {
"name": "idempotency_keys_user_id_key_endpoint_pk",
"columns": [
"user_id",
"key",
"endpoint"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.notifications": {
"name": "notifications",
"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
},
"type": {
"name": "type",
"type": "notification_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"body_sv": {
"name": "body_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"template_key": {
"name": "template_key",
"type": "text",
"primaryKey": false,
"notNull": false
},
"variables": {
"name": "variables",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"locale": {
"name": "locale",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scheduled_for": {
"name": "scheduled_for",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"sent_at": {
"name": "sent_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"read_at": {
"name": "read_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": {
"notifications_user_idx": {
"name": "notifications_user_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": {
"notifications_user_id_users_id_fk": {
"name": "notifications_user_id_users_id_fk",
"tableFrom": "notifications",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.push_tokens": {
"name": "push_tokens",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"platform": {
"name": "platform",
"type": "text",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"push_tokens_user_id_users_id_fk": {
"name": "push_tokens_user_id_users_id_fk",
"tableFrom": "push_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"push_tokens_user_id_token_pk": {
"name": "push_tokens_user_id_token_pk",
"columns": [
"user_id",
"token"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.waste_summaries": {
"name": "waste_summaries",
"schema": "",
"columns": {
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"week_start_date": {
"name": "week_start_date",
"type": "text",
"primaryKey": false,
"notNull": true
},
"discarded_count": {
"name": "discarded_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"discarded_value_minor": {
"name": "discarded_value_minor",
"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": {
"waste_summaries_household_id_households_id_fk": {
"name": "waste_summaries_household_id_households_id_fk",
"tableFrom": "waste_summaries",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"waste_summaries_household_id_week_start_date_pk": {
"name": "waste_summaries_household_id_week_start_date_pk",
"columns": [
"household_id",
"week_start_date"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.release_gates": {
"name": "release_gates",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"gate_key": {
"name": "gate_key",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"category": {
"name": "category",
"type": "release_gate_category",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_en": {
"name": "name_en",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description_sv": {
"name": "description_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"description_en": {
"name": "description_en",
"type": "text",
"primaryKey": false,
"notNull": false
},
"target_value": {
"name": "target_value",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"comparison": {
"name": "comparison",
"type": "release_gate_comparison",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"evaluation_window_days": {
"name": "evaluation_window_days",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 7
},
"last_value": {
"name": "last_value",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"last_evaluated_at": {
"name": "last_evaluated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "release_gate_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"blocking": {
"name": "blocking",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"notes": {
"name": "notes",
"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": {
"release_gates_category_idx": {
"name": "release_gates_category_idx",
"columns": [
{
"expression": "category",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"release_gates_status_idx": {
"name": "release_gates_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"release_gates_gate_key_unique": {
"name": "release_gates_gate_key_unique",
"nullsNotDistinct": false,
"columns": [
"gate_key"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.activity_level": {
"name": "activity_level",
"schema": "public",
"values": [
"sedentary",
"light",
"moderate",
"active",
"very_active"
]
},
"public.allergen": {
"name": "allergen",
"schema": "public",
"values": [
"gluten",
"crustaceans",
"eggs",
"fish",
"peanuts",
"soy",
"milk",
"tree_nuts",
"celery",
"mustard",
"sesame",
"sulphites",
"lupin",
"molluscs"
]
},
"public.consent_kind": {
"name": "consent_kind",
"schema": "public",
"values": [
"personalization",
"anonymized_improvement",
"image_training",
"health_integration",
"location_weather",
"push_notifications",
"product_analytics"
]
},
"public.consent_status": {
"name": "consent_status",
"schema": "public",
"values": [
"granted",
"denied",
"revoked"
]
},
"public.cooking_method": {
"name": "cooking_method",
"schema": "public",
"values": [
"stovetop",
"oven",
"grill",
"airfryer",
"wok",
"slow_cooker",
"sous_vide",
"microwave",
"no_cook",
"pressure_cooker",
"deep_fry",
"steam"
]
},
"public.creator_level": {
"name": "creator_level",
"schema": "public",
"values": [
"beginner",
"sous_chef",
"chef",
"master_chef",
"legend"
]
},
"public.cuisine": {
"name": "cuisine",
"schema": "public",
"values": [
"swedish",
"nordic",
"italian",
"french",
"spanish",
"greek",
"thai",
"chinese",
"japanese",
"korean",
"vietnamese",
"indian",
"mexican",
"american",
"turkish",
"lebanese",
"moroccan",
"middle_eastern",
"international"
]
},
"public.date_kind": {
"name": "date_kind",
"schema": "public",
"values": [
"best_before",
"use_by"
]
},
"public.diet_pattern": {
"name": "diet_pattern",
"schema": "public",
"values": [
"omnivore",
"flexitarian",
"pescatarian",
"vegetarian",
"vegan",
"low_carb",
"keto",
"high_protein",
"mediterranean"
]
},
"public.event_type": {
"name": "event_type",
"schema": "public",
"values": [
"PRODUCT_ADDED",
"PRODUCT_UPDATED",
"PRODUCT_CONSUMED",
"PRODUCT_DISCARDED",
"RECIPE_COOKED",
"RECIPE_RATED",
"RECIPE_CREATED",
"RECIPE_FORKED",
"MEAL_LOGGED",
"MEAL_PHOTO_ANALYZED",
"HOUSEHOLD_MEMBER_ADDED",
"SUBSCRIPTION_STARTED",
"SUBSCRIPTION_CHANGED",
"AI_CORRECTED",
"MEMORY_UPDATED",
"SHOPPING_COMPLETED",
"WEEK_PLAN_UPDATED",
"MEAL_BOX_CREATED",
"MEAL_BOX_CONSUMED"
]
},
"public.expiry_status": {
"name": "expiry_status",
"schema": "public",
"values": [
"fresh",
"use_soon",
"expiring",
"expired",
"unknown"
]
},
"public.goal_type": {
"name": "goal_type",
"schema": "public",
"values": [
"lose_weight",
"gain_weight",
"build_muscle",
"maintain_weight",
"more_protein",
"less_fat",
"more_fiber",
"more_variety",
"less_waste",
"lower_cost",
"cook_more"
]
},
"public.household_role": {
"name": "household_role",
"schema": "public",
"values": [
"owner",
"adult",
"member",
"child"
]
},
"public.inventory_source": {
"name": "inventory_source",
"schema": "public",
"values": [
"fridge_photo",
"freezer_photo",
"pantry_photo",
"ingredient_photo",
"barcode",
"receipt",
"digital_receipt",
"label_photo",
"manual_search",
"free_text",
"voice",
"cooked_recipe",
"connector",
"seed"
]
},
"public.inventory_transaction_type": {
"name": "inventory_transaction_type",
"schema": "public",
"values": [
"purchase",
"consume",
"discard",
"adjust",
"cook_use",
"leftover_created",
"leftover_consumed",
"correction",
"freeze",
"thaw",
"move"
]
},
"public.job_status": {
"name": "job_status",
"schema": "public",
"values": [
"queued",
"running",
"awaiting_confirmation",
"completed",
"failed",
"canceled"
]
},
"public.job_type": {
"name": "job_type",
"schema": "public",
"values": [
"ANALYZE_FRIDGE_IMAGE",
"ANALYZE_PANTRY_IMAGE",
"ANALYZE_MEAL_IMAGE",
"READ_RECEIPT",
"READ_NUTRITION_LABEL",
"READ_EXPIRY_DATE",
"NORMALIZE_PRODUCTS",
"DEDUPLICATE_INVENTORY",
"CALCULATE_NUTRITION",
"GENERATE_RECIPE_OPTIONS",
"RANK_RECIPES",
"UPDATE_USER_MEMORY",
"GENERATE_WEEK_PLAN",
"SEND_EXPIRY_NOTIFICATION",
"VERIFY_SUBSCRIPTION",
"PROCESS_STORE_NOTIFICATION",
"BUILD_TRAINING_SAMPLE",
"RUN_AI_EVALUATION"
]
},
"public.meal_log_source": {
"name": "meal_log_source",
"schema": "public",
"values": [
"cooked_recipe",
"plate_photo",
"barcode",
"product",
"free_text",
"voice",
"previous_meal",
"meal_box",
"manual"
]
},
"public.meal_type": {
"name": "meal_type",
"schema": "public",
"values": [
"breakfast",
"lunch",
"dinner",
"snack",
"dessert",
"starter",
"buffet",
"party"
]
},
"public.memory_kind": {
"name": "memory_kind",
"schema": "public",
"values": [
"structured_fact",
"event",
"semantic",
"profile_summary",
"recipe_memory"
]
},
"public.notification_type": {
"name": "notification_type",
"schema": "public",
"values": [
"expiry_warning",
"meal_box_reminder",
"quick_dinner_suggestion",
"holiday_upcoming",
"creator_new_recipe",
"week_plan_change",
"pantry_forecast",
"subscription_status"
]
},
"public.precision_mode": {
"name": "precision_mode",
"schema": "public",
"values": [
"simple",
"exact"
]
},
"public.profile_visibility": {
"name": "profile_visibility",
"schema": "public",
"values": [
"private",
"friends",
"national",
"global"
]
},
"public.recipe_difficulty": {
"name": "recipe_difficulty",
"schema": "public",
"values": [
"beginner",
"easy",
"medium",
"advanced",
"expert"
]
},
"public.recipe_similarity_class": {
"name": "recipe_similarity_class",
"schema": "public",
"values": [
"duplicate",
"variant",
"inspired",
"independent"
]
},
"public.recipe_source_type": {
"name": "recipe_source_type",
"schema": "public",
"values": [
"own_editorial",
"ai_assisted_reviewed",
"open_license",
"public_domain",
"licensed_database",
"creator_agreement",
"user_generated"
]
},
"public.recipe_status": {
"name": "recipe_status",
"schema": "public",
"values": [
"draft",
"submitted",
"ai_checked",
"in_moderation",
"published",
"rejected",
"archived"
]
},
"public.recipe_variant_type": {
"name": "recipe_variant_type",
"schema": "public",
"values": [
"standard",
"high_protein",
"low_calorie",
"low_fat",
"vegetarian",
"vegan",
"gluten_free",
"lactose_free",
"kid_friendly",
"airfryer",
"budget"
]
},
"public.recipe_verification_status": {
"name": "recipe_verification_status",
"schema": "public",
"values": [
"unverified",
"community",
"verified",
"editorial"
]
},
"public.religious_rule": {
"name": "religious_rule",
"schema": "public",
"values": [
"none",
"halal",
"kosher",
"hindu_no_beef",
"buddhist_vegetarian"
]
},
"public.scan_type": {
"name": "scan_type",
"schema": "public",
"values": [
"fridge",
"freezer",
"pantry",
"ingredients",
"plate",
"receipt",
"barcode",
"expiry_date",
"nutrition_label",
"product_package"
]
},
"public.sex": {
"name": "sex",
"schema": "public",
"values": [
"female",
"male",
"unspecified"
]
},
"public.signal_origin": {
"name": "signal_origin",
"schema": "public",
"values": [
"user_stated",
"observed",
"ai_inferred"
]
},
"public.storage_location_type": {
"name": "storage_location_type",
"schema": "public",
"values": [
"fridge",
"freezer",
"pantry",
"garage_freezer",
"wine_fridge",
"cellar",
"meal_box",
"custom"
]
},
"public.subscription_plan": {
"name": "subscription_plan",
"schema": "public",
"values": [
"free",
"household",
"family",
"large_household"
]
},
"public.subscription_provider": {
"name": "subscription_provider",
"schema": "public",
"values": [
"apple",
"google",
"promo",
"none"
]
},
"public.subscription_status": {
"name": "subscription_status",
"schema": "public",
"values": [
"trial",
"active",
"in_grace",
"on_hold",
"paused",
"canceled",
"expired"
]
},
"public.taste_axis": {
"name": "taste_axis",
"schema": "public",
"values": [
"spice",
"salt",
"acid",
"creaminess",
"garlic",
"sweetness",
"herbs",
"umami"
]
},
"public.unit": {
"name": "unit",
"schema": "public",
"values": [
"GRAM",
"KILOGRAM",
"MILLILITER",
"DECILITER",
"LITER",
"TEASPOON",
"TABLESPOON",
"CUP_US",
"FLUID_OUNCE_US",
"OUNCE",
"POUND",
"COUNT",
"PORTION",
"PINCH",
"SLICE",
"CLOVE",
"CAN",
"PACKAGE"
]
},
"public.user_role": {
"name": "user_role",
"schema": "public",
"values": [
"user",
"moderator",
"admin"
]
},
"public.verification_status": {
"name": "verification_status",
"schema": "public",
"values": [
"unverified",
"user_verified",
"editorially_verified"
]
},
"public.measurement_system": {
"name": "measurement_system",
"schema": "public",
"values": [
"METRIC",
"US_CUSTOMARY",
"MIXED"
]
},
"public.temperature_unit": {
"name": "temperature_unit",
"schema": "public",
"values": [
"CELSIUS",
"FAHRENHEIT"
]
},
"public.translation_source": {
"name": "translation_source",
"schema": "public",
"values": [
"seed",
"ai",
"human"
]
},
"public.translation_status": {
"name": "translation_status",
"schema": "public",
"values": [
"draft_ai",
"in_review",
"published"
]
},
"public.release_gate_category": {
"name": "release_gate_category",
"schema": "public",
"values": [
"product",
"quality",
"retention",
"economy"
]
},
"public.release_gate_comparison": {
"name": "release_gate_comparison",
"schema": "public",
"values": [
"gte",
"lte",
"eq"
]
},
"public.release_gate_status": {
"name": "release_gate_status",
"schema": "public",
"values": [
"pending",
"passed",
"failed",
"blocked",
"not_measurable"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
@@ -0,0 +1,8992 @@
{
"id": "a6520529-bbb4-405d-8310-a8b8f0809e35",
"prevId": "b26aaf39-2905-4816-9575-ac7e429c3a28",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.admin_totp": {
"name": "admin_totp",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"secret_base32": {
"name": "secret_base32",
"type": "text",
"primaryKey": false,
"notNull": true
},
"enabled_at": {
"name": "enabled_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_used_step": {
"name": "last_used_step",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"admin_totp_user_id_users_id_fk": {
"name": "admin_totp_user_id_users_id_fk",
"tableFrom": "admin_totp",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.email_verification_tokens": {
"name": "email_verification_tokens",
"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
},
"token_hash": {
"name": "token_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"used_at": {
"name": "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()"
}
},
"indexes": {
"email_verification_tokens_user_idx": {
"name": "email_verification_tokens_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"email_verification_tokens_hash_unique": {
"name": "email_verification_tokens_hash_unique",
"columns": [
{
"expression": "token_hash",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"email_verification_tokens_user_id_users_id_fk": {
"name": "email_verification_tokens_user_id_users_id_fk",
"tableFrom": "email_verification_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.password_reset_tokens": {
"name": "password_reset_tokens",
"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
},
"token_hash": {
"name": "token_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"used_at": {
"name": "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()"
}
},
"indexes": {
"password_reset_tokens_user_idx": {
"name": "password_reset_tokens_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"password_reset_tokens_hash_unique": {
"name": "password_reset_tokens_hash_unique",
"columns": [
{
"expression": "token_hash",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"password_reset_tokens_user_id_users_id_fk": {
"name": "password_reset_tokens_user_id_users_id_fk",
"tableFrom": "password_reset_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.refresh_tokens": {
"name": "refresh_tokens",
"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
},
"token_hash": {
"name": "token_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"family_id": {
"name": "family_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"revoked_at": {
"name": "revoked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"replaced_by_token_id": {
"name": "replaced_by_token_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false
},
"ip": {
"name": "ip",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"refresh_tokens_user_idx": {
"name": "refresh_tokens_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"refresh_tokens_hash_unique": {
"name": "refresh_tokens_hash_unique",
"columns": [
{
"expression": "token_hash",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"refresh_tokens_user_id_users_id_fk": {
"name": "refresh_tokens_user_id_users_id_fk",
"tableFrom": "refresh_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_consents": {
"name": "user_consents",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"kind": {
"name": "kind",
"type": "consent_kind",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "consent_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"granted_at": {
"name": "granted_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"revoked_at": {
"name": "revoked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_consents_user_id_users_id_fk": {
"name": "user_consents_user_id_users_id_fk",
"tableFrom": "user_consents",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"user_consents_user_id_kind_pk": {
"name": "user_consents_user_id_kind_pk",
"columns": [
"user_id",
"kind"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_credentials": {
"name": "user_credentials",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"password_hash": {
"name": "password_hash",
"type": "text",
"primaryKey": false,
"notNull": true
},
"password_updated_at": {
"name": "password_updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_credentials_user_id_users_id_fk": {
"name": "user_credentials_user_id_users_id_fk",
"tableFrom": "user_credentials",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_health_profiles": {
"name": "user_health_profiles",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"birth_year": {
"name": "birth_year",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"sex": {
"name": "sex",
"type": "sex",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"height_cm": {
"name": "height_cm",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"weight_kg": {
"name": "weight_kg",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"target_weight_kg": {
"name": "target_weight_kg",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"activity_level": {
"name": "activity_level",
"type": "activity_level",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'moderate'"
},
"training_sessions_per_week": {
"name": "training_sessions_per_week",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"training_types": {
"name": "training_types",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_health_profiles_user_id_users_id_fk": {
"name": "user_health_profiles_user_id_users_id_fk",
"tableFrom": "user_health_profiles",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_preferences": {
"name": "user_preferences",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"primary_goal": {
"name": "primary_goal",
"type": "goal_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"goals": {
"name": "goals",
"type": "goal_type[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"diet_pattern": {
"name": "diet_pattern",
"type": "diet_pattern",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'omnivore'"
},
"religious_rule": {
"name": "religious_rule",
"type": "religious_rule",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'none'"
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"intolerances": {
"name": "intolerances",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"avoid_ingredient_ids": {
"name": "avoid_ingredient_ids",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"favorite_cuisines": {
"name": "favorite_cuisines",
"type": "cuisine[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"disliked_dishes": {
"name": "disliked_dishes",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"spice_level_max": {
"name": "spice_level_max",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 3
},
"weekly_budget_minor": {
"name": "weekly_budget_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"max_cooking_minutes_weekday": {
"name": "max_cooking_minutes_weekday",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"equipment": {
"name": "equipment",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"default_portions": {
"name": "default_portions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 2
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_preferences_user_id_users_id_fk": {
"name": "user_preferences_user_id_users_id_fk",
"tableFrom": "user_preferences",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email_verified_at": {
"name": "email_verified_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "user_role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"locale": {
"name": "locale",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'sv-SE'"
},
"precision_mode": {
"name": "precision_mode",
"type": "precision_mode",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'simple'"
},
"onboarding_completed": {
"name": "onboarding_completed",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"onboarding_step": {
"name": "onboarding_step",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'a'"
},
"deleted_at": {
"name": "deleted_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": {
"users_email_unique": {
"name": "users_email_unique",
"columns": [
{
"expression": "email",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_locale_preferences": {
"name": "user_locale_preferences",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'sv-SE'"
},
"region_code": {
"name": "region_code",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SE'"
},
"time_zone": {
"name": "time_zone",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'Europe/Stockholm'"
},
"measurement_system": {
"name": "measurement_system",
"type": "measurement_system",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'METRIC'"
},
"temperature_unit": {
"name": "temperature_unit",
"type": "temperature_unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'CELSIUS'"
},
"currency_code": {
"name": "currency_code",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SEK'"
},
"first_day_of_week": {
"name": "first_day_of_week",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 1
},
"use_24_hour_time": {
"name": "use_24_hour_time",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"user_locale_preferences_user_id_users_id_fk": {
"name": "user_locale_preferences_user_id_users_id_fk",
"tableFrom": "user_locale_preferences",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.household_members": {
"name": "household_members",
"schema": "",
"columns": {
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "household_role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'member'"
},
"portion_factor": {
"name": "portion_factor",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"joined_at": {
"name": "joined_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"household_members_user_idx": {
"name": "household_members_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"household_members_household_id_households_id_fk": {
"name": "household_members_household_id_households_id_fk",
"tableFrom": "household_members",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"household_members_user_id_users_id_fk": {
"name": "household_members_user_id_users_id_fk",
"tableFrom": "household_members",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"household_members_household_id_user_id_pk": {
"name": "household_members_household_id_user_id_pk",
"columns": [
"household_id",
"user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.households": {
"name": "households",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"invite_code": {
"name": "invite_code",
"type": "text",
"primaryKey": false,
"notNull": true
},
"weekly_budget_minor": {
"name": "weekly_budget_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"first_scan_completed_at": {
"name": "first_scan_completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"fifth_item_confirmed_at": {
"name": "fifth_item_confirmed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"first_recipe_recommendation_viewed_at": {
"name": "first_recipe_recommendation_viewed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"first_recipe_saved_or_started_at": {
"name": "first_recipe_saved_or_started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"activated_at": {
"name": "activated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"first_cooking_session_completed_at": {
"name": "first_cooking_session_completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"inventory_updated_after_cooking_at": {
"name": "inventory_updated_after_cooking_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"value_confirmed_at": {
"name": "value_confirmed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"size": {
"name": "size",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"currency_code": {
"name": "currency_code",
"type": "varchar(3)",
"primaryKey": false,
"notNull": true,
"default": "'SEK'"
},
"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": {
"households_invite_code_unique": {
"name": "households_invite_code_unique",
"columns": [
{
"expression": "invite_code",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.storage_locations": {
"name": "storage_locations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "storage_location_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"sublocations": {
"name": "sublocations",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"storage_locations_household_idx": {
"name": "storage_locations_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"storage_locations_household_id_households_id_fk": {
"name": "storage_locations_household_id_households_id_fk",
"tableFrom": "storage_locations",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.canonical_ingredients": {
"name": "canonical_ingredients",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_en": {
"name": "name_en",
"type": "text",
"primaryKey": false,
"notNull": true
},
"aliases": {
"name": "aliases",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"category": {
"name": "category",
"type": "text",
"primaryKey": false,
"notNull": true
},
"default_unit": {
"name": "default_unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"density_g_per_ml": {
"name": "density_g_per_ml",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"grams_per_piece": {
"name": "grams_per_piece",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"is_vegan": {
"name": "is_vegan",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_vegetarian": {
"name": "is_vegetarian",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"contains_gluten": {
"name": "contains_gluten",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"contains_lactose": {
"name": "contains_lactose",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_pork": {
"name": "is_pork",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_beef": {
"name": "is_beef",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_alcohol": {
"name": "is_alcohol",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"nutrition_per_100": {
"name": "nutrition_per_100",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"nutrition_provenance": {
"name": "nutrition_provenance",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"peak_seasons": {
"name": "peak_seasons",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"shelf_life_guidance": {
"name": "shelf_life_guidance",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"default_price_minor_per_kg": {
"name": "default_price_minor_per_kg",
"type": "integer",
"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": {
"canonical_ingredients_category_idx": {
"name": "canonical_ingredients_category_idx",
"columns": [
{
"expression": "category",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.substitutions": {
"name": "substitutions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"from_ingredient_id": {
"name": "from_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"to_ingredient_id": {
"name": "to_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"ratio": {
"name": "ratio",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"instructions_sv": {
"name": "instructions_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"best_for": {
"name": "best_for",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"not_recommended_for": {
"name": "not_recommended_for",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"flavor_impact_sv": {
"name": "flavor_impact_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"texture_impact_sv": {
"name": "texture_impact_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"priority": {
"name": "priority",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"substitutions_from_idx": {
"name": "substitutions_from_idx",
"columns": [
{
"expression": "from_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"substitutions_pair_unique": {
"name": "substitutions_pair_unique",
"columns": [
{
"expression": "from_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "to_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"substitutions_from_ingredient_id_canonical_ingredients_id_fk": {
"name": "substitutions_from_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "substitutions",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"from_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"substitutions_to_ingredient_id_canonical_ingredients_id_fk": {
"name": "substitutions_to_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "substitutions",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"to_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.products": {
"name": "products",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"gtin": {
"name": "gtin",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"brand": {
"name": "brand",
"type": "text",
"primaryKey": false,
"notNull": false
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"package_size_value": {
"name": "package_size_value",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"package_size_unit": {
"name": "package_size_unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"ingredients_text": {
"name": "ingredients_text",
"type": "text",
"primaryKey": false,
"notNull": false
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"may_contain_allergens": {
"name": "may_contain_allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"nutrition": {
"name": "nutrition",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"image_urls": {
"name": "image_urls",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"language": {
"name": "language",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'sv'"
},
"market": {
"name": "market",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SE'"
},
"data_source": {
"name": "data_source",
"type": "text",
"primaryKey": false,
"notNull": true
},
"verification_status": {
"name": "verification_status",
"type": "verification_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'unverified'"
},
"version": {
"name": "version",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 1
},
"valid_from": {
"name": "valid_from",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"valid_to": {
"name": "valid_to",
"type": "timestamp with time zone",
"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": {
"products_gtin_version_unique": {
"name": "products_gtin_version_unique",
"columns": [
{
"expression": "gtin",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "version",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"where": "\"products\".\"gtin\" IS NOT NULL",
"concurrently": false,
"method": "btree",
"with": {}
},
"products_gtin_current_idx": {
"name": "products_gtin_current_idx",
"columns": [
{
"expression": "gtin",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"where": "\"products\".\"valid_to\" IS NULL",
"concurrently": false,
"method": "btree",
"with": {}
},
"products_canonical_idx": {
"name": "products_canonical_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"products_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "products_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "products",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.inventory_items": {
"name": "inventory_items",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"brand": {
"name": "brand",
"type": "text",
"primaryKey": false,
"notNull": false
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"storage_location_id": {
"name": "storage_location_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"sublocation": {
"name": "sublocation",
"type": "text",
"primaryKey": false,
"notNull": false
},
"purchased_at": {
"name": "purchased_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"opened_at": {
"name": "opened_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"best_before_date": {
"name": "best_before_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"use_by_date": {
"name": "use_by_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"date_kind": {
"name": "date_kind",
"type": "date_kind",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"frozen_at": {
"name": "frozen_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"thawed_at": {
"name": "thawed_at",
"type": "date",
"primaryKey": false,
"notNull": false
},
"price_minor": {
"name": "price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"nutrition_per_100": {
"name": "nutrition_per_100",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"source": {
"name": "source",
"type": "inventory_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"confidence": {
"name": "confidence",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"verified_by_user": {
"name": "verified_by_user",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"last_verified_at": {
"name": "last_verified_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expiry_status": {
"name": "expiry_status",
"type": "expiry_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'unknown'"
},
"trust_state": {
"name": "trust_state",
"type": "varchar(16)",
"primaryKey": false,
"notNull": true,
"default": "'unverified'"
},
"depleted_at": {
"name": "depleted_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prompt_version": {
"name": "prompt_version",
"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": {
"inventory_items_household_idx": {
"name": "inventory_items_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_items_household_bb_idx": {
"name": "inventory_items_household_bb_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "best_before_date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_items_location_idx": {
"name": "inventory_items_location_idx",
"columns": [
{
"expression": "storage_location_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_items_canonical_idx": {
"name": "inventory_items_canonical_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"inventory_items_household_id_households_id_fk": {
"name": "inventory_items_household_id_households_id_fk",
"tableFrom": "inventory_items",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_items_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "inventory_items_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "inventory_items",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"inventory_items_product_id_products_id_fk": {
"name": "inventory_items_product_id_products_id_fk",
"tableFrom": "inventory_items",
"tableTo": "products",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"inventory_items_storage_location_id_storage_locations_id_fk": {
"name": "inventory_items_storage_location_id_storage_locations_id_fk",
"tableFrom": "inventory_items",
"tableTo": "storage_locations",
"columnsFrom": [
"storage_location_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.inventory_transactions": {
"name": "inventory_transactions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"inventory_item_id": {
"name": "inventory_item_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "inventory_transaction_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"quantity_delta": {
"name": "quantity_delta",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"ref_type": {
"name": "ref_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"ref_id": {
"name": "ref_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"actor_user_id": {
"name": "actor_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"note": {
"name": "note",
"type": "text",
"primaryKey": false,
"notNull": false
},
"value_minor": {
"name": "value_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"inventory_tx_item_idx": {
"name": "inventory_tx_item_idx",
"columns": [
{
"expression": "inventory_item_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_tx_household_time_idx": {
"name": "inventory_tx_household_time_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"inventory_tx_type_idx": {
"name": "inventory_tx_type_idx",
"columns": [
{
"expression": "type",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"inventory_transactions_household_id_households_id_fk": {
"name": "inventory_transactions_household_id_households_id_fk",
"tableFrom": "inventory_transactions",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_transactions_inventory_item_id_inventory_items_id_fk": {
"name": "inventory_transactions_inventory_item_id_inventory_items_id_fk",
"tableFrom": "inventory_transactions",
"tableTo": "inventory_items",
"columnsFrom": [
"inventory_item_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_transactions_actor_user_id_users_id_fk": {
"name": "inventory_transactions_actor_user_id_users_id_fk",
"tableFrom": "inventory_transactions",
"tableTo": "users",
"columnsFrom": [
"actor_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.inventory_decay_profiles": {
"name": "inventory_decay_profiles",
"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
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"half_life_days": {
"name": "half_life_days",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 7
},
"stale_after_days": {
"name": "stale_after_days",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 30
},
"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": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"inventory_decay_profiles_name_unique": {
"name": "inventory_decay_profiles_name_unique",
"nullsNotDistinct": false,
"columns": [
"name"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.inventory_item_decay_profile": {
"name": "inventory_item_decay_profile",
"schema": "",
"columns": {
"inventory_item_id": {
"name": "inventory_item_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"decay_profile_id": {
"name": "decay_profile_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"inventory_item_decay_profile_inventory_item_id_inventory_items_id_fk": {
"name": "inventory_item_decay_profile_inventory_item_id_inventory_items_id_fk",
"tableFrom": "inventory_item_decay_profile",
"tableTo": "inventory_items",
"columnsFrom": [
"inventory_item_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"inventory_item_decay_profile_decay_profile_id_inventory_decay_profiles_id_fk": {
"name": "inventory_item_decay_profile_decay_profile_id_inventory_decay_profiles_id_fk",
"tableFrom": "inventory_item_decay_profile",
"tableTo": "inventory_decay_profiles",
"columnsFrom": [
"decay_profile_id"
],
"columnsTo": [
"id"
],
"onDelete": "restrict",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_cooks": {
"name": "recipe_cooks",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"portions_cooked": {
"name": "portions_cooked",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"cooked_at": {
"name": "cooked_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"recipe_cooks_recipe_idx": {
"name": "recipe_cooks_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_cooks_user_idx": {
"name": "recipe_cooks_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_cooks_recipe_id_recipes_id_fk": {
"name": "recipe_cooks_recipe_id_recipes_id_fk",
"tableFrom": "recipe_cooks",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_cooks_user_id_users_id_fk": {
"name": "recipe_cooks_user_id_users_id_fk",
"tableFrom": "recipe_cooks",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_favorites": {
"name": "recipe_favorites",
"schema": "",
"columns": {
"recipe_id": {
"name": "recipe_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": {
"recipe_favorites_user_idx": {
"name": "recipe_favorites_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_favorites_recipe_id_recipes_id_fk": {
"name": "recipe_favorites_recipe_id_recipes_id_fk",
"tableFrom": "recipe_favorites",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_favorites_user_id_users_id_fk": {
"name": "recipe_favorites_user_id_users_id_fk",
"tableFrom": "recipe_favorites",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"recipe_favorites_recipe_id_user_id_pk": {
"name": "recipe_favorites_recipe_id_user_id_pk",
"columns": [
"recipe_id",
"user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_ingredients": {
"name": "recipe_ingredients",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"display_name_sv": {
"name": "display_name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"note": {
"name": "note",
"type": "text",
"primaryKey": false,
"notNull": false
},
"optional": {
"name": "optional",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"group_name": {
"name": "group_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"recipe_ingredients_recipe_idx": {
"name": "recipe_ingredients_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_ingredients_canonical_idx": {
"name": "recipe_ingredients_canonical_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_ingredients_recipe_id_recipes_id_fk": {
"name": "recipe_ingredients_recipe_id_recipes_id_fk",
"tableFrom": "recipe_ingredients",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_ingredients_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "recipe_ingredients_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "recipe_ingredients",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_ratings": {
"name": "recipe_ratings",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stars": {
"name": "stars",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"feedback_tags": {
"name": "feedback_tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"comment": {
"name": "comment",
"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": {
"recipe_ratings_user_recipe_unique": {
"name": "recipe_ratings_user_recipe_unique",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_ratings_recipe_idx": {
"name": "recipe_ratings_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_ratings_recipe_id_recipes_id_fk": {
"name": "recipe_ratings_recipe_id_recipes_id_fk",
"tableFrom": "recipe_ratings",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_ratings_user_id_users_id_fk": {
"name": "recipe_ratings_user_id_users_id_fk",
"tableFrom": "recipe_ratings",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_similarities": {
"name": "recipe_similarities",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_a_id": {
"name": "recipe_a_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"recipe_b_id": {
"name": "recipe_b_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"similarity_score": {
"name": "similarity_score",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"classification": {
"name": "classification",
"type": "recipe_similarity_class",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"details": {
"name": "details",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"recipe_similarities_pair_unique": {
"name": "recipe_similarities_pair_unique",
"columns": [
{
"expression": "recipe_a_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "recipe_b_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_similarities_recipe_a_id_recipes_id_fk": {
"name": "recipe_similarities_recipe_a_id_recipes_id_fk",
"tableFrom": "recipe_similarities",
"tableTo": "recipes",
"columnsFrom": [
"recipe_a_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"recipe_similarities_recipe_b_id_recipes_id_fk": {
"name": "recipe_similarities_recipe_b_id_recipes_id_fk",
"tableFrom": "recipe_similarities",
"tableTo": "recipes",
"columnsFrom": [
"recipe_b_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_source_registry": {
"name": "recipe_source_registry",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"source_name": {
"name": "source_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"license": {
"name": "license",
"type": "text",
"primaryKey": false,
"notNull": true
},
"right_to_store": {
"name": "right_to_store",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"right_to_modify": {
"name": "right_to_modify",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"right_to_display": {
"name": "right_to_display",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"attribution_required": {
"name": "attribution_required",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"attribution_text": {
"name": "attribution_text",
"type": "text",
"primaryKey": false,
"notNull": false
},
"commercial_use": {
"name": "commercial_use",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"valid_from": {
"name": "valid_from",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"valid_to": {
"name": "valid_to",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false
},
"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.recipe_steps": {
"name": "recipe_steps",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"step_number": {
"name": "step_number",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"instruction_sv": {
"name": "instruction_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"timer_seconds": {
"name": "timer_seconds",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"temperature_c": {
"name": "temperature_c",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"tip": {
"name": "tip",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"recipe_steps_recipe_idx": {
"name": "recipe_steps_recipe_idx",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_steps_recipe_step_unique": {
"name": "recipe_steps_recipe_step_unique",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "step_number",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_steps_recipe_id_recipes_id_fk": {
"name": "recipe_steps_recipe_id_recipes_id_fk",
"tableFrom": "recipe_steps",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipes": {
"name": "recipes",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"slug": {
"name": "slug",
"type": "text",
"primaryKey": false,
"notNull": true
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description_sv": {
"name": "description_sv",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "''"
},
"country": {
"name": "country",
"type": "text",
"primaryKey": false,
"notNull": false
},
"region": {
"name": "region",
"type": "text",
"primaryKey": false,
"notNull": false
},
"cuisine": {
"name": "cuisine",
"type": "cuisine",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"meal_types": {
"name": "meal_types",
"type": "meal_type[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"tags": {
"name": "tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"methods": {
"name": "methods",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"equipment": {
"name": "equipment",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"difficulty": {
"name": "difficulty",
"type": "recipe_difficulty",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'easy'"
},
"prep_time_minutes": {
"name": "prep_time_minutes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"cook_time_minutes": {
"name": "cook_time_minutes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"total_time_minutes": {
"name": "total_time_minutes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"portions": {
"name": "portions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 4
},
"nutrition_per_portion": {
"name": "nutrition_per_portion",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"allergens": {
"name": "allergens",
"type": "allergen[]",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"spice_level": {
"name": "spice_level",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"estimated_cost_minor_per_portion": {
"name": "estimated_cost_minor_per_portion",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"storage_guidance_sv": {
"name": "storage_guidance_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"meal_prep_friendly": {
"name": "meal_prep_friendly",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"freezer_friendly": {
"name": "freezer_friendly",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"peak_seasons": {
"name": "peak_seasons",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"holiday_tags": {
"name": "holiday_tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"dna": {
"name": "dna",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"variant_type": {
"name": "variant_type",
"type": "recipe_variant_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'standard'"
},
"variant_of_recipe_id": {
"name": "variant_of_recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"forked_from_recipe_id": {
"name": "forked_from_recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "recipe_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'draft'"
},
"verification_status": {
"name": "verification_status",
"type": "recipe_verification_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'unverified'"
},
"source_type": {
"name": "source_type",
"type": "recipe_source_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"source_registry_id": {
"name": "source_registry_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"creator_user_id": {
"name": "creator_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"creator_display_name": {
"name": "creator_display_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"image_urls": {
"name": "image_urls",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"version": {
"name": "version",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 1
},
"rating_average": {
"name": "rating_average",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"rating_count": {
"name": "rating_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"cook_count": {
"name": "cook_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"favorite_count": {
"name": "favorite_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"moderation_note": {
"name": "moderation_note",
"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": {
"recipes_slug_unique": {
"name": "recipes_slug_unique",
"columns": [
{
"expression": "slug",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_status_idx": {
"name": "recipes_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_cuisine_idx": {
"name": "recipes_cuisine_idx",
"columns": [
{
"expression": "cuisine",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_variant_of_idx": {
"name": "recipes_variant_of_idx",
"columns": [
{
"expression": "variant_of_recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_creator_idx": {
"name": "recipes_creator_idx",
"columns": [
{
"expression": "creator_user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipes_total_time_idx": {
"name": "recipes_total_time_idx",
"columns": [
{
"expression": "total_time_minutes",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipes_source_registry_id_recipe_source_registry_id_fk": {
"name": "recipes_source_registry_id_recipe_source_registry_id_fk",
"tableFrom": "recipes",
"tableTo": "recipe_source_registry",
"columnsFrom": [
"source_registry_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"recipes_creator_user_id_users_id_fk": {
"name": "recipes_creator_user_id_users_id_fk",
"tableFrom": "recipes",
"tableTo": "users",
"columnsFrom": [
"creator_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ingredient_translations": {
"name": "ingredient_translations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"ingredient_id": {
"name": "ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"aliases": {
"name": "aliases",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"source": {
"name": "source",
"type": "translation_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'seed'"
},
"status": {
"name": "status",
"type": "translation_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'published'"
},
"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": {
"ingredient_translations_unique": {
"name": "ingredient_translations_unique",
"columns": [
{
"expression": "ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"ingredient_translations_lang_idx": {
"name": "ingredient_translations_lang_idx",
"columns": [
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"ingredient_translations_ingredient_id_canonical_ingredients_id_fk": {
"name": "ingredient_translations_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "ingredient_translations",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_step_translations": {
"name": "recipe_step_translations",
"schema": "",
"columns": {
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"step_number": {
"name": "step_number",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"instruction": {
"name": "instruction",
"type": "text",
"primaryKey": false,
"notNull": true
},
"tip": {
"name": "tip",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"recipe_step_translations_recipe_id_recipes_id_fk": {
"name": "recipe_step_translations_recipe_id_recipes_id_fk",
"tableFrom": "recipe_step_translations",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"recipe_step_translations_recipe_id_language_tag_step_number_pk": {
"name": "recipe_step_translations_recipe_id_language_tag_step_number_pk",
"columns": [
"recipe_id",
"language_tag",
"step_number"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.recipe_translations": {
"name": "recipe_translations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"storage_guidance": {
"name": "storage_guidance",
"type": "text",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "translation_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'draft_ai'"
},
"source": {
"name": "source",
"type": "translation_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'ai'"
},
"verification": {
"name": "verification",
"type": "jsonb",
"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": {
"recipe_translations_unique": {
"name": "recipe_translations_unique",
"columns": [
{
"expression": "recipe_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
},
"recipe_translations_lang_idx": {
"name": "recipe_translations_lang_idx",
"columns": [
{
"expression": "language_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"recipe_translations_recipe_id_recipes_id_fk": {
"name": "recipe_translations_recipe_id_recipes_id_fk",
"tableFrom": "recipe_translations",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.unit_translations": {
"name": "unit_translations",
"schema": "",
"columns": {
"unit_code": {
"name": "unit_code",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"language_tag": {
"name": "language_tag",
"type": "varchar(35)",
"primaryKey": false,
"notNull": true
},
"abbreviation": {
"name": "abbreviation",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"unit_translations_unit_code_language_tag_pk": {
"name": "unit_translations_unit_code_language_tag_pk",
"columns": [
"unit_code",
"language_tag"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.allergen_market_rules": {
"name": "allergen_market_rules",
"schema": "",
"columns": {
"region_code": {
"name": "region_code",
"type": "varchar(2)",
"primaryKey": false,
"notNull": true
},
"allergen": {
"name": "allergen",
"type": "allergen",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"must_highlight": {
"name": "must_highlight",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"allergen_market_rules_region_code_allergen_pk": {
"name": "allergen_market_rules_region_code_allergen_pk",
"columns": [
"region_code",
"allergen"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.nutrition_display_profiles": {
"name": "nutrition_display_profiles",
"schema": "",
"columns": {
"region_code": {
"name": "region_code",
"type": "varchar(2)",
"primaryKey": true,
"notNull": true
},
"energy_display": {
"name": "energy_display",
"type": "text",
"primaryKey": false,
"notNull": true
},
"salt_display": {
"name": "salt_display",
"type": "text",
"primaryKey": false,
"notNull": true
},
"energy_label_key": {
"name": "energy_label_key",
"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": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.meal_boxes": {
"name": "meal_boxes",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"portions": {
"name": "portions",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"portions_remaining": {
"name": "portions_remaining",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"nutrition_per_portion": {
"name": "nutrition_per_portion",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"cooked_at": {
"name": "cooked_at",
"type": "date",
"primaryKey": false,
"notNull": true
},
"storage_location_id": {
"name": "storage_location_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"frozen": {
"name": "frozen",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"recommended_use_by": {
"name": "recommended_use_by",
"type": "date",
"primaryKey": false,
"notNull": true
},
"reserved_for_user_id": {
"name": "reserved_for_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'available'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"meal_boxes_household_idx": {
"name": "meal_boxes_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"meal_boxes_use_by_idx": {
"name": "meal_boxes_use_by_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "recommended_use_by",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"meal_boxes_household_id_households_id_fk": {
"name": "meal_boxes_household_id_households_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"meal_boxes_recipe_id_recipes_id_fk": {
"name": "meal_boxes_recipe_id_recipes_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"meal_boxes_storage_location_id_storage_locations_id_fk": {
"name": "meal_boxes_storage_location_id_storage_locations_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "storage_locations",
"columnsFrom": [
"storage_location_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"meal_boxes_reserved_for_user_id_users_id_fk": {
"name": "meal_boxes_reserved_for_user_id_users_id_fk",
"tableFrom": "meal_boxes",
"tableTo": "users",
"columnsFrom": [
"reserved_for_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.meals": {
"name": "meals",
"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
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"date": {
"name": "date",
"type": "date",
"primaryKey": false,
"notNull": true
},
"meal_type": {
"name": "meal_type",
"type": "meal_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"source": {
"name": "source",
"type": "meal_log_source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"portion_fraction": {
"name": "portion_fraction",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"nutrition": {
"name": "nutrition",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"nutrition_is_estimate": {
"name": "nutrition_is_estimate",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"estimate_min_kcal": {
"name": "estimate_min_kcal",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"estimate_max_kcal": {
"name": "estimate_max_kcal",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"items": {
"name": "items",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"photo_url": {
"name": "photo_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scan_job_id": {
"name": "scan_job_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"logged_at": {
"name": "logged_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"meals_user_date_idx": {
"name": "meals_user_date_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"meals_household_idx": {
"name": "meals_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"meals_user_id_users_id_fk": {
"name": "meals_user_id_users_id_fk",
"tableFrom": "meals",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"meals_household_id_households_id_fk": {
"name": "meals_household_id_households_id_fk",
"tableFrom": "meals",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"meals_recipe_id_recipes_id_fk": {
"name": "meals_recipe_id_recipes_id_fk",
"tableFrom": "meals",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.shopping_list_items": {
"name": "shopping_list_items",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"shopping_list_id": {
"name": "shopping_list_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"display_name": {
"name": "display_name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 1
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'COUNT'"
},
"store_section": {
"name": "store_section",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'hygien_ovrigt'"
},
"suggested_package_size": {
"name": "suggested_package_size",
"type": "text",
"primaryKey": false,
"notNull": false
},
"estimated_price_minor": {
"name": "estimated_price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"checked": {
"name": "checked",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"added_by_user_id": {
"name": "added_by_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"origin": {
"name": "origin",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'manual'"
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"shopping_list_items_list_idx": {
"name": "shopping_list_items_list_idx",
"columns": [
{
"expression": "shopping_list_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"shopping_list_items_shopping_list_id_shopping_lists_id_fk": {
"name": "shopping_list_items_shopping_list_id_shopping_lists_id_fk",
"tableFrom": "shopping_list_items",
"tableTo": "shopping_lists",
"columnsFrom": [
"shopping_list_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"shopping_list_items_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "shopping_list_items_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "shopping_list_items",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"shopping_list_items_added_by_user_id_users_id_fk": {
"name": "shopping_list_items_added_by_user_id_users_id_fk",
"tableFrom": "shopping_list_items",
"tableTo": "users",
"columnsFrom": [
"added_by_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.shopping_lists": {
"name": "shopping_lists",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'Inköpslista'"
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'active'"
},
"week_plan_id": {
"name": "week_plan_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": {
"shopping_lists_household_idx": {
"name": "shopping_lists_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"shopping_lists_household_id_households_id_fk": {
"name": "shopping_lists_household_id_households_id_fk",
"tableFrom": "shopping_lists",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"shopping_lists_week_plan_id_week_plans_id_fk": {
"name": "shopping_lists_week_plan_id_week_plans_id_fk",
"tableFrom": "shopping_lists",
"tableTo": "week_plans",
"columnsFrom": [
"week_plan_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.week_plan_entries": {
"name": "week_plan_entries",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"week_plan_id": {
"name": "week_plan_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"date": {
"name": "date",
"type": "date",
"primaryKey": false,
"notNull": true
},
"meal_type": {
"name": "meal_type",
"type": "meal_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"meal_box_id": {
"name": "meal_box_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"portions": {
"name": "portions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 2
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'planned'"
},
"reschedule_reason_sv": {
"name": "reschedule_reason_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sort_order": {
"name": "sort_order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
}
},
"indexes": {
"week_plan_entries_plan_idx": {
"name": "week_plan_entries_plan_idx",
"columns": [
{
"expression": "week_plan_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"week_plan_entries_week_plan_id_week_plans_id_fk": {
"name": "week_plan_entries_week_plan_id_week_plans_id_fk",
"tableFrom": "week_plan_entries",
"tableTo": "week_plans",
"columnsFrom": [
"week_plan_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"week_plan_entries_recipe_id_recipes_id_fk": {
"name": "week_plan_entries_recipe_id_recipes_id_fk",
"tableFrom": "week_plan_entries",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"week_plan_entries_meal_box_id_meal_boxes_id_fk": {
"name": "week_plan_entries_meal_box_id_meal_boxes_id_fk",
"tableFrom": "week_plan_entries",
"tableTo": "meal_boxes",
"columnsFrom": [
"meal_box_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.week_plans": {
"name": "week_plans",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"week_start_date": {
"name": "week_start_date",
"type": "date",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'draft'"
},
"generated_by": {
"name": "generated_by",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"notes": {
"name": "notes",
"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": {
"week_plans_household_week_idx": {
"name": "week_plans_household_week_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "week_start_date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"week_plans_household_id_households_id_fk": {
"name": "week_plans_household_id_households_id_fk",
"tableFrom": "week_plans",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.price_observations": {
"name": "price_observations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"store_name": {
"name": "store_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"price_minor": {
"name": "price_minor",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"price_per_kg_minor": {
"name": "price_per_kg_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"observed_at": {
"name": "observed_at",
"type": "date",
"primaryKey": false,
"notNull": true
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'receipt'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"price_observations_ingredient_idx": {
"name": "price_observations_ingredient_idx",
"columns": [
{
"expression": "canonical_ingredient_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "observed_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"price_observations_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "price_observations_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "price_observations",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"price_observations_product_id_products_id_fk": {
"name": "price_observations_product_id_products_id_fk",
"tableFrom": "price_observations",
"tableTo": "products",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.receipt_lines": {
"name": "receipt_lines",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"receipt_id": {
"name": "receipt_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"raw_text": {
"name": "raw_text",
"type": "text",
"primaryKey": false,
"notNull": true
},
"normalized_name": {
"name": "normalized_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"canonical_ingredient_id": {
"name": "canonical_ingredient_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"quantity": {
"name": "quantity",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"unit": {
"name": "unit",
"type": "unit",
"typeSchema": "public",
"primaryKey": false,
"notNull": false
},
"unit_price_minor": {
"name": "unit_price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"total_price_minor": {
"name": "total_price_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"confidence": {
"name": "confidence",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0
},
"verified_by_user": {
"name": "verified_by_user",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"added_to_inventory": {
"name": "added_to_inventory",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
}
},
"indexes": {
"receipt_lines_receipt_idx": {
"name": "receipt_lines_receipt_idx",
"columns": [
{
"expression": "receipt_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"receipt_lines_receipt_id_receipts_id_fk": {
"name": "receipt_lines_receipt_id_receipts_id_fk",
"tableFrom": "receipt_lines",
"tableTo": "receipts",
"columnsFrom": [
"receipt_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"receipt_lines_canonical_ingredient_id_canonical_ingredients_id_fk": {
"name": "receipt_lines_canonical_ingredient_id_canonical_ingredients_id_fk",
"tableFrom": "receipt_lines",
"tableTo": "canonical_ingredients",
"columnsFrom": [
"canonical_ingredient_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"receipt_lines_product_id_products_id_fk": {
"name": "receipt_lines_product_id_products_id_fk",
"tableFrom": "receipt_lines",
"tableTo": "products",
"columnsFrom": [
"product_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.receipts": {
"name": "receipts",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"store_name": {
"name": "store_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"purchase_date": {
"name": "purchase_date",
"type": "date",
"primaryKey": false,
"notNull": false
},
"total_minor": {
"name": "total_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"discount_minor": {
"name": "discount_minor",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"image_url": {
"name": "image_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scan_job_id": {
"name": "scan_job_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"receipts_household_idx": {
"name": "receipts_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "purchase_date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"receipts_household_id_households_id_fk": {
"name": "receipts_household_id_households_id_fk",
"tableFrom": "receipts",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_corrections": {
"name": "ai_corrections",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"scan_job_id": {
"name": "scan_job_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"task_type": {
"name": "task_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"ai_output": {
"name": "ai_output",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"user_correction": {
"name": "user_correction",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prompt_version": {
"name": "prompt_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"consent_snapshot": {
"name": "consent_snapshot",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"exported_to_training": {
"name": "exported_to_training",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"training_batch_id": {
"name": "training_batch_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"ai_corrections_task_idx": {
"name": "ai_corrections_task_idx",
"columns": [
{
"expression": "task_type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"ai_corrections_scan_job_id_scan_jobs_id_fk": {
"name": "ai_corrections_scan_job_id_scan_jobs_id_fk",
"tableFrom": "ai_corrections",
"tableTo": "scan_jobs",
"columnsFrom": [
"scan_job_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"ai_corrections_user_id_users_id_fk": {
"name": "ai_corrections_user_id_users_id_fk",
"tableFrom": "ai_corrections",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.scan_jobs": {
"name": "scan_jobs",
"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
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"scan_type": {
"name": "scan_type",
"type": "scan_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"job_type": {
"name": "job_type",
"type": "job_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "job_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'queued'"
},
"s3_keys": {
"name": "s3_keys",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"context": {
"name": "context",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"result": {
"name": "result",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"error": {
"name": "error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"prompt_version": {
"name": "prompt_version",
"type": "text",
"primaryKey": false,
"notNull": false
},
"latency_ms": {
"name": "latency_ms",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"cost_usd": {
"name": "cost_usd",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"attempts": {
"name": "attempts",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"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": {
"scan_jobs_user_idx": {
"name": "scan_jobs_user_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": {}
},
"scan_jobs_status_idx": {
"name": "scan_jobs_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"scan_jobs_user_id_users_id_fk": {
"name": "scan_jobs_user_id_users_id_fk",
"tableFrom": "scan_jobs",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"scan_jobs_household_id_households_id_fk": {
"name": "scan_jobs_household_id_households_id_fk",
"tableFrom": "scan_jobs",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.food_memories": {
"name": "food_memories",
"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": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"recipe_id": {
"name": "recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"summary_sv": {
"name": "summary_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"holiday_tag": {
"name": "holiday_tag",
"type": "text",
"primaryKey": false,
"notNull": false
},
"photo_url": {
"name": "photo_url",
"type": "text",
"primaryKey": false,
"notNull": false
},
"stars": {
"name": "stars",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"occurred_at": {
"name": "occurred_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()"
}
},
"indexes": {
"food_memories_household_idx": {
"name": "food_memories_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"food_memories_holiday_idx": {
"name": "food_memories_holiday_idx",
"columns": [
{
"expression": "holiday_tag",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"food_memories_user_id_users_id_fk": {
"name": "food_memories_user_id_users_id_fk",
"tableFrom": "food_memories",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"food_memories_household_id_households_id_fk": {
"name": "food_memories_household_id_households_id_fk",
"tableFrom": "food_memories",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"food_memories_recipe_id_recipes_id_fk": {
"name": "food_memories_recipe_id_recipes_id_fk",
"tableFrom": "food_memories",
"tableTo": "recipes",
"columnsFrom": [
"recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.memory_items": {
"name": "memory_items",
"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": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"kind": {
"name": "kind",
"type": "memory_kind",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"summary_sv": {
"name": "summary_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"value": {
"name": "value",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"origin": {
"name": "origin",
"type": "signal_origin",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"confidence": {
"name": "confidence",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0.5
},
"verified_by_user": {
"name": "verified_by_user",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"paused": {
"name": "paused",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"last_used_at": {
"name": "last_used_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "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": {
"memory_items_user_idx": {
"name": "memory_items_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "kind",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"memory_items_household_idx": {
"name": "memory_items_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "kind",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"memory_items_key_idx": {
"name": "memory_items_key_idx",
"columns": [
{
"expression": "key",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"memory_items_user_id_users_id_fk": {
"name": "memory_items_user_id_users_id_fk",
"tableFrom": "memory_items",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"memory_items_household_id_households_id_fk": {
"name": "memory_items_household_id_households_id_fk",
"tableFrom": "memory_items",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.taste_signals": {
"name": "taste_signals",
"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
},
"axis": {
"name": "axis",
"type": "taste_axis",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"direction": {
"name": "direction",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"strength": {
"name": "strength",
"type": "double precision",
"primaryKey": false,
"notNull": true,
"default": 0.5
},
"origin": {
"name": "origin",
"type": "signal_origin",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"ref_recipe_id": {
"name": "ref_recipe_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"taste_signals_user_idx": {
"name": "taste_signals_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "axis",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"taste_signals_user_id_users_id_fk": {
"name": "taste_signals_user_id_users_id_fk",
"tableFrom": "taste_signals",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"taste_signals_ref_recipe_id_recipes_id_fk": {
"name": "taste_signals_ref_recipe_id_recipes_id_fk",
"tableFrom": "taste_signals",
"tableTo": "recipes",
"columnsFrom": [
"ref_recipe_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.season_events": {
"name": "season_events",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"slug": {
"name": "slug",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"market": {
"name": "market",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'SE'"
},
"date_rule": {
"name": "date_rule",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"lead_days": {
"name": "lead_days",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 7
},
"food_tags": {
"name": "food_tags",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"recipe_slugs": {
"name": "recipe_slugs",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"priority": {
"name": "priority",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"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": {
"season_events_slug_market_unique": {
"name": "season_events_slug_market_unique",
"columns": [
{
"expression": "slug",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "market",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_usage_counters": {
"name": "ai_usage_counters",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"month": {
"name": "month",
"type": "text",
"primaryKey": false,
"notNull": true
},
"ai_scans": {
"name": "ai_scans",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"ai_tokens_in": {
"name": "ai_tokens_in",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"ai_tokens_out": {
"name": "ai_tokens_out",
"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": {
"ai_usage_user_month_unique": {
"name": "ai_usage_user_month_unique",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "month",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"ai_usage_counters_user_id_users_id_fk": {
"name": "ai_usage_counters_user_id_users_id_fk",
"tableFrom": "ai_usage_counters",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.store_notifications": {
"name": "store_notifications",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"provider": {
"name": "provider",
"type": "subscription_provider",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"notification_type": {
"name": "notification_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"raw_payload": {
"name": "raw_payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"signature_verified": {
"name": "signature_verified",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"processed": {
"name": "processed",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"processed_at": {
"name": "processed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"error": {
"name": "error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"store_notifications_pending_idx": {
"name": "store_notifications_pending_idx",
"columns": [
{
"expression": "processed",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.store_transactions": {
"name": "store_transactions",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"provider": {
"name": "provider",
"type": "subscription_provider",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"transaction_id": {
"name": "transaction_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"original_transaction_id": {
"name": "original_transaction_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"raw_payload": {
"name": "raw_payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"processed_at": {
"name": "processed_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": {
"store_transactions_unique": {
"name": "store_transactions_unique",
"columns": [
{
"expression": "provider",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "transaction_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"store_transactions_user_id_users_id_fk": {
"name": "store_transactions_user_id_users_id_fk",
"tableFrom": "store_transactions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.subscription_events": {
"name": "subscription_events",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"subscription_id": {
"name": "subscription_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"event_type": {
"name": "event_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"payload": {
"name": "payload",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"subscription_events_sub_idx": {
"name": "subscription_events_sub_idx",
"columns": [
{
"expression": "subscription_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"subscription_events_subscription_id_subscriptions_id_fk": {
"name": "subscription_events_subscription_id_subscriptions_id_fk",
"tableFrom": "subscription_events",
"tableTo": "subscriptions",
"columnsFrom": [
"subscription_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"subscription_events_user_id_users_id_fk": {
"name": "subscription_events_user_id_users_id_fk",
"tableFrom": "subscription_events",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.subscriptions": {
"name": "subscriptions",
"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
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"provider": {
"name": "provider",
"type": "subscription_provider",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"plan": {
"name": "plan",
"type": "subscription_plan",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"original_transaction_id": {
"name": "original_transaction_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "subscription_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"purchased_at": {
"name": "purchased_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"grace_period_expires_at": {
"name": "grace_period_expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"canceled_at": {
"name": "canceled_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_verified_at": {
"name": "last_verified_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": {
"subscriptions_user_idx": {
"name": "subscriptions_user_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"subscriptions_original_tx_unique": {
"name": "subscriptions_original_tx_unique",
"columns": [
{
"expression": "provider",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "original_transaction_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"where": "\"subscriptions\".\"original_transaction_id\" IS NOT NULL",
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"subscriptions_user_id_users_id_fk": {
"name": "subscriptions_user_id_users_id_fk",
"tableFrom": "subscriptions",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"subscriptions_household_id_households_id_fk": {
"name": "subscriptions_household_id_households_id_fk",
"tableFrom": "subscriptions",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.trials": {
"name": "trials",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"started_at": {
"name": "started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"ends_at": {
"name": "ends_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"trials_user_id_users_id_fk": {
"name": "trials_user_id_users_id_fk",
"tableFrom": "trials",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.analytics_daily_snapshots": {
"name": "analytics_daily_snapshots",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"date": {
"name": "date",
"type": "varchar(10)",
"primaryKey": false,
"notNull": true
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"event_name": {
"name": "event_name",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"count": {
"name": "count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"unique_sessions": {
"name": "unique_sessions",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"properties_fingerprint": {
"name": "properties_fingerprint",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"pa_daily_household_date_idx": {
"name": "pa_daily_household_date_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "date",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_daily_date_event_idx": {
"name": "pa_daily_date_event_idx",
"columns": [
{
"expression": "date",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "event_name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"analytics_daily_snapshots_household_id_households_id_fk": {
"name": "analytics_daily_snapshots_household_id_households_id_fk",
"tableFrom": "analytics_daily_snapshots",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.product_analytics_events": {
"name": "product_analytics_events",
"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()"
},
"received_at": {
"name": "received_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"event_name": {
"name": "event_name",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"anonymous_id": {
"name": "anonymous_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"session_id": {
"name": "session_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"app_version": {
"name": "app_version",
"type": "varchar(32)",
"primaryKey": false,
"notNull": false
},
"platform": {
"name": "platform",
"type": "varchar(16)",
"primaryKey": false,
"notNull": false
},
"locale": {
"name": "locale",
"type": "varchar(16)",
"primaryKey": false,
"notNull": false
},
"experiment_variant": {
"name": "experiment_variant",
"type": "varchar(128)",
"primaryKey": false,
"notNull": false
},
"properties": {
"name": "properties",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{}'::jsonb"
}
},
"indexes": {
"pa_events_name_occurred_idx": {
"name": "pa_events_name_occurred_idx",
"columns": [
{
"expression": "event_name",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_household_occurred_idx": {
"name": "pa_events_household_occurred_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_user_occurred_idx": {
"name": "pa_events_user_occurred_idx",
"columns": [
{
"expression": "user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_session_idx": {
"name": "pa_events_session_idx",
"columns": [
{
"expression": "session_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"pa_events_received_idx": {
"name": "pa_events_received_idx",
"columns": [
{
"expression": "received_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"product_analytics_events_user_id_users_id_fk": {
"name": "product_analytics_events_user_id_users_id_fk",
"tableFrom": "product_analytics_events",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
},
"product_analytics_events_household_id_households_id_fk": {
"name": "product_analytics_events_household_id_households_id_fk",
"tableFrom": "product_analytics_events",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "set null",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_eval_cases": {
"name": "ai_eval_cases",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"task_type": {
"name": "task_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"input_ref": {
"name": "input_ref",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"expected_output": {
"name": "expected_output",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"category": {
"name": "category",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'standard'"
},
"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()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.ai_eval_runs": {
"name": "ai_eval_runs",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"task_type": {
"name": "task_type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"model_version": {
"name": "model_version",
"type": "text",
"primaryKey": false,
"notNull": true
},
"prompt_version": {
"name": "prompt_version",
"type": "text",
"primaryKey": false,
"notNull": true
},
"metrics": {
"name": "metrics",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"passed": {
"name": "passed",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"notes": {
"name": "notes",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"ai_eval_runs_task_idx": {
"name": "ai_eval_runs_task_idx",
"columns": [
{
"expression": "task_type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.audit_logs": {
"name": "audit_logs",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"actor_user_id": {
"name": "actor_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"actor_type": {
"name": "actor_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'user'"
},
"action": {
"name": "action",
"type": "text",
"primaryKey": false,
"notNull": true
},
"target_type": {
"name": "target_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"target_id": {
"name": "target_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"ip": {
"name": "ip",
"type": "text",
"primaryKey": false,
"notNull": false
},
"correlation_id": {
"name": "correlation_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"audit_logs_actor_idx": {
"name": "audit_logs_actor_idx",
"columns": [
{
"expression": "actor_user_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"audit_logs_action_idx": {
"name": "audit_logs_action_idx",
"columns": [
{
"expression": "action",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "created_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.creator_follows": {
"name": "creator_follows",
"schema": "",
"columns": {
"follower_user_id": {
"name": "follower_user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"creator_user_id": {
"name": "creator_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": {
"creator_follows_follower_user_id_users_id_fk": {
"name": "creator_follows_follower_user_id_users_id_fk",
"tableFrom": "creator_follows",
"tableTo": "users",
"columnsFrom": [
"follower_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"creator_follows_creator_user_id_users_id_fk": {
"name": "creator_follows_creator_user_id_users_id_fk",
"tableFrom": "creator_follows",
"tableTo": "users",
"columnsFrom": [
"creator_user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"creator_follows_follower_user_id_creator_user_id_pk": {
"name": "creator_follows_follower_user_id_creator_user_id_pk",
"columns": [
"follower_user_id",
"creator_user_id"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.creator_stats": {
"name": "creator_stats",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"visibility": {
"name": "visibility",
"type": "profile_visibility",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'private'"
},
"level": {
"name": "level",
"type": "creator_level",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'beginner'"
},
"published_recipes": {
"name": "published_recipes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"followers": {
"name": "followers",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"total_cooks": {
"name": "total_cooks",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"total_favorites": {
"name": "total_favorites",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"average_rating": {
"name": "average_rating",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"verified_recipes": {
"name": "verified_recipes",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"badges": {
"name": "badges",
"type": "text[]",
"primaryKey": false,
"notNull": true,
"default": "'{}'"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"creator_stats_user_id_users_id_fk": {
"name": "creator_stats_user_id_users_id_fk",
"tableFrom": "creator_stats",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.domain_events": {
"name": "domain_events",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"type": {
"name": "type",
"type": "event_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"payload": {
"name": "payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"correlation_id": {
"name": "correlation_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"occurred_at": {
"name": "occurred_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"published_at": {
"name": "published_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
}
},
"indexes": {
"domain_events_unpublished_idx": {
"name": "domain_events_unpublished_idx",
"columns": [
{
"expression": "published_at",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"domain_events_type_idx": {
"name": "domain_events_type_idx",
"columns": [
{
"expression": "type",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"domain_events_household_idx": {
"name": "domain_events_household_idx",
"columns": [
{
"expression": "household_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "occurred_at",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.feature_flags": {
"name": "feature_flags",
"schema": "",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"enabled": {
"name": "enabled",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"description_sv": {
"name": "description_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"rollout_percent": {
"name": "rollout_percent",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 100
},
"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.idempotency_keys": {
"name": "idempotency_keys",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"endpoint": {
"name": "endpoint",
"type": "text",
"primaryKey": false,
"notNull": true
},
"response_status": {
"name": "response_status",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"response_body": {
"name": "response_body",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"idempotency_keys_user_id_users_id_fk": {
"name": "idempotency_keys_user_id_users_id_fk",
"tableFrom": "idempotency_keys",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"idempotency_keys_user_id_key_endpoint_pk": {
"name": "idempotency_keys_user_id_key_endpoint_pk",
"columns": [
"user_id",
"key",
"endpoint"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.notifications": {
"name": "notifications",
"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
},
"type": {
"name": "type",
"type": "notification_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"title_sv": {
"name": "title_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"body_sv": {
"name": "body_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"template_key": {
"name": "template_key",
"type": "text",
"primaryKey": false,
"notNull": false
},
"variables": {
"name": "variables",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"locale": {
"name": "locale",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scheduled_for": {
"name": "scheduled_for",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"sent_at": {
"name": "sent_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"read_at": {
"name": "read_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": {
"notifications_user_idx": {
"name": "notifications_user_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": {
"notifications_user_id_users_id_fk": {
"name": "notifications_user_id_users_id_fk",
"tableFrom": "notifications",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.push_tokens": {
"name": "push_tokens",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"platform": {
"name": "platform",
"type": "text",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"push_tokens_user_id_users_id_fk": {
"name": "push_tokens_user_id_users_id_fk",
"tableFrom": "push_tokens",
"tableTo": "users",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"push_tokens_user_id_token_pk": {
"name": "push_tokens_user_id_token_pk",
"columns": [
"user_id",
"token"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.waste_summaries": {
"name": "waste_summaries",
"schema": "",
"columns": {
"household_id": {
"name": "household_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"week_start_date": {
"name": "week_start_date",
"type": "text",
"primaryKey": false,
"notNull": true
},
"discarded_count": {
"name": "discarded_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"discarded_value_minor": {
"name": "discarded_value_minor",
"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": {
"waste_summaries_household_id_households_id_fk": {
"name": "waste_summaries_household_id_households_id_fk",
"tableFrom": "waste_summaries",
"tableTo": "households",
"columnsFrom": [
"household_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"waste_summaries_household_id_week_start_date_pk": {
"name": "waste_summaries_household_id_week_start_date_pk",
"columns": [
"household_id",
"week_start_date"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.release_gates": {
"name": "release_gates",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"gate_key": {
"name": "gate_key",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"category": {
"name": "category",
"type": "release_gate_category",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"name_sv": {
"name": "name_sv",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name_en": {
"name": "name_en",
"type": "text",
"primaryKey": false,
"notNull": true
},
"description_sv": {
"name": "description_sv",
"type": "text",
"primaryKey": false,
"notNull": false
},
"description_en": {
"name": "description_en",
"type": "text",
"primaryKey": false,
"notNull": false
},
"target_value": {
"name": "target_value",
"type": "double precision",
"primaryKey": false,
"notNull": true
},
"comparison": {
"name": "comparison",
"type": "release_gate_comparison",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"evaluation_window_days": {
"name": "evaluation_window_days",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 7
},
"last_value": {
"name": "last_value",
"type": "double precision",
"primaryKey": false,
"notNull": false
},
"last_evaluated_at": {
"name": "last_evaluated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "release_gate_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"blocking": {
"name": "blocking",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"notes": {
"name": "notes",
"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": {
"release_gates_category_idx": {
"name": "release_gates_category_idx",
"columns": [
{
"expression": "category",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
},
"release_gates_status_idx": {
"name": "release_gates_status_idx",
"columns": [
{
"expression": "status",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": false,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"release_gates_gate_key_unique": {
"name": "release_gates_gate_key_unique",
"nullsNotDistinct": false,
"columns": [
"gate_key"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.activity_level": {
"name": "activity_level",
"schema": "public",
"values": [
"sedentary",
"light",
"moderate",
"active",
"very_active"
]
},
"public.allergen": {
"name": "allergen",
"schema": "public",
"values": [
"gluten",
"crustaceans",
"eggs",
"fish",
"peanuts",
"soy",
"milk",
"tree_nuts",
"celery",
"mustard",
"sesame",
"sulphites",
"lupin",
"molluscs"
]
},
"public.consent_kind": {
"name": "consent_kind",
"schema": "public",
"values": [
"personalization",
"anonymized_improvement",
"image_training",
"health_integration",
"location_weather",
"push_notifications",
"product_analytics"
]
},
"public.consent_status": {
"name": "consent_status",
"schema": "public",
"values": [
"granted",
"denied",
"revoked"
]
},
"public.cooking_method": {
"name": "cooking_method",
"schema": "public",
"values": [
"stovetop",
"oven",
"grill",
"airfryer",
"wok",
"slow_cooker",
"sous_vide",
"microwave",
"no_cook",
"pressure_cooker",
"deep_fry",
"steam"
]
},
"public.creator_level": {
"name": "creator_level",
"schema": "public",
"values": [
"beginner",
"sous_chef",
"chef",
"master_chef",
"legend"
]
},
"public.cuisine": {
"name": "cuisine",
"schema": "public",
"values": [
"swedish",
"nordic",
"italian",
"french",
"spanish",
"greek",
"thai",
"chinese",
"japanese",
"korean",
"vietnamese",
"indian",
"mexican",
"american",
"turkish",
"lebanese",
"moroccan",
"middle_eastern",
"international"
]
},
"public.date_kind": {
"name": "date_kind",
"schema": "public",
"values": [
"best_before",
"use_by"
]
},
"public.diet_pattern": {
"name": "diet_pattern",
"schema": "public",
"values": [
"omnivore",
"flexitarian",
"pescatarian",
"vegetarian",
"vegan",
"low_carb",
"keto",
"high_protein",
"mediterranean"
]
},
"public.event_type": {
"name": "event_type",
"schema": "public",
"values": [
"PRODUCT_ADDED",
"PRODUCT_UPDATED",
"PRODUCT_CONSUMED",
"PRODUCT_DISCARDED",
"RECIPE_COOKED",
"RECIPE_RATED",
"RECIPE_CREATED",
"RECIPE_FORKED",
"MEAL_LOGGED",
"MEAL_PHOTO_ANALYZED",
"HOUSEHOLD_MEMBER_ADDED",
"SUBSCRIPTION_STARTED",
"SUBSCRIPTION_CHANGED",
"AI_CORRECTED",
"MEMORY_UPDATED",
"SHOPPING_COMPLETED",
"WEEK_PLAN_UPDATED",
"MEAL_BOX_CREATED",
"MEAL_BOX_CONSUMED"
]
},
"public.expiry_status": {
"name": "expiry_status",
"schema": "public",
"values": [
"fresh",
"use_soon",
"expiring",
"expired",
"unknown"
]
},
"public.goal_type": {
"name": "goal_type",
"schema": "public",
"values": [
"lose_weight",
"gain_weight",
"build_muscle",
"maintain_weight",
"more_protein",
"less_fat",
"more_fiber",
"more_variety",
"less_waste",
"lower_cost",
"cook_more"
]
},
"public.household_role": {
"name": "household_role",
"schema": "public",
"values": [
"owner",
"adult",
"member",
"child"
]
},
"public.inventory_source": {
"name": "inventory_source",
"schema": "public",
"values": [
"fridge_photo",
"freezer_photo",
"pantry_photo",
"ingredient_photo",
"barcode",
"receipt",
"digital_receipt",
"label_photo",
"manual_search",
"free_text",
"voice",
"cooked_recipe",
"connector",
"seed"
]
},
"public.inventory_transaction_type": {
"name": "inventory_transaction_type",
"schema": "public",
"values": [
"purchase",
"consume",
"discard",
"adjust",
"cook_use",
"leftover_created",
"leftover_consumed",
"correction",
"freeze",
"thaw",
"move"
]
},
"public.job_status": {
"name": "job_status",
"schema": "public",
"values": [
"queued",
"running",
"awaiting_confirmation",
"completed",
"failed",
"canceled"
]
},
"public.job_type": {
"name": "job_type",
"schema": "public",
"values": [
"ANALYZE_FRIDGE_IMAGE",
"ANALYZE_PANTRY_IMAGE",
"ANALYZE_MEAL_IMAGE",
"READ_RECEIPT",
"READ_NUTRITION_LABEL",
"READ_EXPIRY_DATE",
"NORMALIZE_PRODUCTS",
"DEDUPLICATE_INVENTORY",
"CALCULATE_NUTRITION",
"GENERATE_RECIPE_OPTIONS",
"RANK_RECIPES",
"UPDATE_USER_MEMORY",
"GENERATE_WEEK_PLAN",
"SEND_EXPIRY_NOTIFICATION",
"VERIFY_SUBSCRIPTION",
"PROCESS_STORE_NOTIFICATION",
"BUILD_TRAINING_SAMPLE",
"RUN_AI_EVALUATION"
]
},
"public.meal_log_source": {
"name": "meal_log_source",
"schema": "public",
"values": [
"cooked_recipe",
"plate_photo",
"barcode",
"product",
"free_text",
"voice",
"previous_meal",
"meal_box",
"manual"
]
},
"public.meal_type": {
"name": "meal_type",
"schema": "public",
"values": [
"breakfast",
"lunch",
"dinner",
"snack",
"dessert",
"starter",
"buffet",
"party"
]
},
"public.memory_kind": {
"name": "memory_kind",
"schema": "public",
"values": [
"structured_fact",
"event",
"semantic",
"profile_summary",
"recipe_memory"
]
},
"public.notification_type": {
"name": "notification_type",
"schema": "public",
"values": [
"expiry_warning",
"meal_box_reminder",
"quick_dinner_suggestion",
"holiday_upcoming",
"creator_new_recipe",
"week_plan_change",
"pantry_forecast",
"subscription_status"
]
},
"public.precision_mode": {
"name": "precision_mode",
"schema": "public",
"values": [
"simple",
"exact"
]
},
"public.profile_visibility": {
"name": "profile_visibility",
"schema": "public",
"values": [
"private",
"friends",
"national",
"global"
]
},
"public.recipe_difficulty": {
"name": "recipe_difficulty",
"schema": "public",
"values": [
"beginner",
"easy",
"medium",
"advanced",
"expert"
]
},
"public.recipe_similarity_class": {
"name": "recipe_similarity_class",
"schema": "public",
"values": [
"duplicate",
"variant",
"inspired",
"independent"
]
},
"public.recipe_source_type": {
"name": "recipe_source_type",
"schema": "public",
"values": [
"own_editorial",
"ai_assisted_reviewed",
"open_license",
"public_domain",
"licensed_database",
"creator_agreement",
"user_generated"
]
},
"public.recipe_status": {
"name": "recipe_status",
"schema": "public",
"values": [
"draft",
"submitted",
"ai_checked",
"in_moderation",
"published",
"rejected",
"archived"
]
},
"public.recipe_variant_type": {
"name": "recipe_variant_type",
"schema": "public",
"values": [
"standard",
"high_protein",
"low_calorie",
"low_fat",
"vegetarian",
"vegan",
"gluten_free",
"lactose_free",
"kid_friendly",
"airfryer",
"budget"
]
},
"public.recipe_verification_status": {
"name": "recipe_verification_status",
"schema": "public",
"values": [
"unverified",
"community",
"verified",
"editorial"
]
},
"public.religious_rule": {
"name": "religious_rule",
"schema": "public",
"values": [
"none",
"halal",
"kosher",
"hindu_no_beef",
"buddhist_vegetarian"
]
},
"public.scan_type": {
"name": "scan_type",
"schema": "public",
"values": [
"fridge",
"freezer",
"pantry",
"ingredients",
"plate",
"receipt",
"barcode",
"expiry_date",
"nutrition_label",
"product_package"
]
},
"public.sex": {
"name": "sex",
"schema": "public",
"values": [
"female",
"male",
"unspecified"
]
},
"public.signal_origin": {
"name": "signal_origin",
"schema": "public",
"values": [
"user_stated",
"observed",
"ai_inferred"
]
},
"public.storage_location_type": {
"name": "storage_location_type",
"schema": "public",
"values": [
"fridge",
"freezer",
"pantry",
"garage_freezer",
"wine_fridge",
"cellar",
"meal_box",
"custom"
]
},
"public.subscription_plan": {
"name": "subscription_plan",
"schema": "public",
"values": [
"free",
"household",
"family",
"large_household"
]
},
"public.subscription_provider": {
"name": "subscription_provider",
"schema": "public",
"values": [
"apple",
"google",
"promo",
"none"
]
},
"public.subscription_status": {
"name": "subscription_status",
"schema": "public",
"values": [
"trial",
"active",
"in_grace",
"on_hold",
"paused",
"canceled",
"expired"
]
},
"public.taste_axis": {
"name": "taste_axis",
"schema": "public",
"values": [
"spice",
"salt",
"acid",
"creaminess",
"garlic",
"sweetness",
"herbs",
"umami"
]
},
"public.unit": {
"name": "unit",
"schema": "public",
"values": [
"GRAM",
"KILOGRAM",
"MILLILITER",
"DECILITER",
"LITER",
"TEASPOON",
"TABLESPOON",
"CUP_US",
"FLUID_OUNCE_US",
"OUNCE",
"POUND",
"COUNT",
"PORTION",
"PINCH",
"SLICE",
"CLOVE",
"CAN",
"PACKAGE"
]
},
"public.user_role": {
"name": "user_role",
"schema": "public",
"values": [
"user",
"moderator",
"admin"
]
},
"public.verification_status": {
"name": "verification_status",
"schema": "public",
"values": [
"unverified",
"user_verified",
"editorially_verified"
]
},
"public.measurement_system": {
"name": "measurement_system",
"schema": "public",
"values": [
"METRIC",
"US_CUSTOMARY",
"MIXED"
]
},
"public.temperature_unit": {
"name": "temperature_unit",
"schema": "public",
"values": [
"CELSIUS",
"FAHRENHEIT"
]
},
"public.translation_source": {
"name": "translation_source",
"schema": "public",
"values": [
"seed",
"ai",
"human"
]
},
"public.translation_status": {
"name": "translation_status",
"schema": "public",
"values": [
"draft_ai",
"in_review",
"published"
]
},
"public.release_gate_category": {
"name": "release_gate_category",
"schema": "public",
"values": [
"product",
"quality",
"retention",
"economy"
]
},
"public.release_gate_comparison": {
"name": "release_gate_comparison",
"schema": "public",
"values": [
"gte",
"lte",
"eq"
]
},
"public.release_gate_status": {
"name": "release_gate_status",
"schema": "public",
"values": [
"pending",
"passed",
"failed",
"blocked",
"not_measurable"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
@@ -57,6 +57,20 @@
"when": 1786031744466,
"tag": "0007_unusual_leader",
"breakpoints": true
},
{
"idx": 8,
"version": "7",
"when": 1786032811621,
"tag": "0008_exotic_fallen_one",
"breakpoints": true
},
{
"idx": 9,
"version": "7",
"when": 1786033392652,
"tag": "0009_lovely_stingray",
"breakpoints": true
}
]
}
-2
View File
@@ -46,7 +46,6 @@ import {
UNITS,
USER_ROLES,
VERIFICATION_STATUSES,
TRUST_STATES,
tuple,
} from "@app/shared-types";
@@ -113,4 +112,3 @@ export const creatorLevelEnum = pgEnum("creator_level", tuple(CREATOR_LEVELS));
export const profileVisibilityEnum = pgEnum("profile_visibility", tuple(PROFILE_VISIBILITIES));
export const notificationTypeEnum = pgEnum("notification_type", tuple(NOTIFICATION_TYPES));
export const verificationStatusEnum = pgEnum("verification_status", tuple(VERIFICATION_STATUSES));
export const trustStateEnum = pgEnum("trust_state", tuple(TRUST_STATES));
+32
View File
@@ -0,0 +1,32 @@
import { boolean, doublePrecision, integer, pgTable, text, uuid, varchar } from "drizzle-orm/pg-core";
import { createdAt, updatedAt } from "./_shared.js";
import { inventoryItems } from "./inventory.js";
/**
* Inventory Trust Engine (Fas 2 §5.2): deterministiska decay-profiler.
* En aktiv profil styr hur snabbt confidence sjunker med tiden.
* Decay påverkar endast FÖRTROENDE, inte ätbarhet (mjölkprincipen D-035).
*/
export const inventoryDecayProfiles = pgTable("inventory_decay_profiles", {
id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 64 }).notNull().unique(),
description: text("description"),
/** Antal dagar för confidence att halveras. */
halfLifeDays: doublePrecision("half_life_days").notNull().default(7),
/** Efter detta antal dagar anses posten vara stale oavsett ursprunglig confidence. */
staleAfterDays: integer("stale_after_days").notNull().default(30),
/** Sätt till false för att arkivera en profil utan att ta bort historiken. */
active: boolean("active").notNull().default(true),
createdAt: createdAt(),
updatedAt: updatedAt(),
});
/** Valbar FK från inventory_items till den profil som användes när posten skapades. */
export const inventoryItemDecayProfile = pgTable("inventory_item_decay_profile", {
inventoryItemId: uuid("inventory_item_id")
.primaryKey()
.references(() => inventoryItems.id, { onDelete: "cascade" }),
decayProfileId: uuid("decay_profile_id")
.notNull()
.references(() => inventoryDecayProfiles.id, { onDelete: "restrict" }),
});
+1
View File
@@ -5,6 +5,7 @@ export * from "./households.js";
export * from "./ingredients.js";
export * from "./products.js";
export * from "./inventory.js";
export * from "./decay.js";
export * from "./recipes.js";
export * from "./translations.js";
export * from "./markets.js";
+2 -2
View File
@@ -9,6 +9,7 @@ import {
timestamp,
uuid,
integer,
varchar,
} from "drizzle-orm/pg-core";
import type { NutritionDeclaration } from "@app/shared-types";
import {
@@ -17,7 +18,6 @@ import {
expiryStatusEnum,
inventorySourceEnum,
inventoryTransactionTypeEnum,
trustStateEnum,
unitEnum,
updatedAt,
} from "./_shared.js";
@@ -64,7 +64,7 @@ export const inventoryItems = pgTable(
lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true }),
expiryStatus: expiryStatusEnum("expiry_status").notNull().default("unknown"),
/** Inventory Trust Engine state (Fas 2): computed from confidence, decay and verification. */
trustState: trustStateEnum("trust_state").notNull().default("unverified"),
trustState: varchar("trust_state", { length: 16 }).notNull().default("unverified"),
/** Sätts när saldot nått 0 och posten arkiverats. */
depletedAt: timestamp("depleted_at", { withTimezone: true }),
modelVersion: text("model_version"),
+13
View File
@@ -590,6 +590,19 @@ async function main() {
}
console.log(`[seed] ${flags.length} feature flags`);
// 7. Default trust decay profile (Fas 2 §5.2)
await db
.insert(schema.inventoryDecayProfiles)
.values({
name: "default",
description: "Standardprofil: confidence halveras efter 7 dagar, stale efter 30 dagar.",
halfLifeDays: 7,
staleAfterDays: 30,
active: true,
})
.onConflictDoNothing();
console.log("[seed] 1 default decay profile");
console.log("[seed] Klart.");
await pool.end();
}
+52 -18
View File
@@ -1,5 +1,10 @@
import type { TrustState } from "@app/shared-types";
export interface DecayProfile {
halfLifeDays: number;
staleAfterDays: number;
}
export interface TrustInput {
confidence: number;
verifiedByUser: boolean;
@@ -21,6 +26,23 @@ export interface TrustResult {
score: number; // 0100
}
const DEFAULT_DECAY: DecayProfile = { halfLifeDays: 7, staleAfterDays: 30 };
/**
* Deterministic exponential decay of confidence.
* Decay affects TRUST only, never edibility (mjölkprincipen D-035).
*/
export function applyDecay(
confidence: number,
elapsedDays: number,
profile: DecayProfile = DEFAULT_DECAY,
): number {
if (elapsedDays <= 0) return confidence;
if (elapsedDays >= profile.staleAfterDays) return 0;
const factor = Math.pow(0.5, elapsedDays / profile.halfLifeDays);
return Math.max(0, confidence * factor);
}
/**
* Compute the trust state of an inventory item.
*
@@ -29,32 +51,40 @@ export interface TrustResult {
* - decaying: confidence is dropping / not verified for a while.
* - stale: very old, unverified, or confidence critically low.
*
* Decay affects TRUST, not edibility (mjölkprincipen spec D-035).
* Decay affects TRUST, not edibility (mjölkprincipen D-035).
*/
export function computeTrust(input: TrustInput): TrustResult {
const now = Date.now();
export function computeTrust(
input: TrustInput,
now: Date = new Date(),
profile: DecayProfile = DEFAULT_DECAY,
): TrustResult {
const nowMs = now.getTime();
const lastVerified = input.lastVerifiedAt ? new Date(input.lastVerifiedAt).getTime() : null;
const updated = new Date(input.updatedAt).getTime();
const daysSinceVerification = lastVerified ? (now - lastVerified) / 86_400_000 : null;
const daysSinceUpdate = (now - updated) / 86_400_000;
const referenceMs = lastVerified ?? updated;
const elapsedDays = (nowMs - referenceMs) / 86_400_000;
const daysSinceUpdate = (nowMs - updated) / 86_400_000;
// Base score from confidence (080 points)
let score = Math.round(input.confidence * 80);
// Decay confidence deterministically from the profile.
const effectiveConfidence = applyDecay(input.confidence, elapsedDays, profile);
// Verification bonus (020 points)
if (input.verifiedByUser && daysSinceVerification !== null && daysSinceVerification <= 7) {
// Base score from effective confidence (080 points)
let score = Math.round(effectiveConfidence * 80);
// Verification bonus (020 points) verification age is already reflected by decay,
// but a known user-verified item retains a small pedigree bonus.
if (input.verifiedByUser && elapsedDays <= 7) {
score += 20;
} else if (input.verifiedByUser && daysSinceVerification !== null && daysSinceVerification <= 30) {
} else if (input.verifiedByUser && elapsedDays <= 30) {
score += 10;
} else if (input.verifiedByUser) {
score += 5;
}
// Decay penalties (only affect trust score)
if (daysSinceVerification !== null && daysSinceVerification > 7) {
score -= Math.min(20, Math.floor((daysSinceVerification - 7) / 7) * 5);
}
if (daysSinceUpdate > 14) {
// Additional staleness penalty when update is old.
if (daysSinceUpdate > profile.staleAfterDays) {
score -= 20;
} else if (daysSinceUpdate > 14) {
score -= Math.min(15, Math.floor((daysSinceUpdate - 14) / 7) * 5);
}
if (input.quantity <= 0) {
@@ -64,7 +94,7 @@ export function computeTrust(input: TrustInput): TrustResult {
score = Math.max(0, Math.min(100, score));
let state: TrustState;
if (input.verifiedByUser && score >= 80) {
if (score >= 80) {
state = "trusted";
} else if (score >= 60) {
state = "trusted";
@@ -80,8 +110,12 @@ export function computeTrust(input: TrustInput): TrustResult {
}
/** Convenience wrapper that returns just the state for an inventory row. */
export function itemTrustState(item: InventoryItemLike): TrustState {
return computeTrust(item).state;
export function itemTrustState(
item: InventoryItemLike,
now?: Date,
profile?: DecayProfile,
): TrustState {
return computeTrust(item, now, profile).state;
}
/** Pick the most urgent trust state from a list (used for household summary). */
+63 -18
View File
@@ -1,54 +1,99 @@
import { describe, expect, it } from "vitest";
import { computeTrust, worstTrustState } from "../src/trust.js";
import { applyDecay, computeTrust, worstTrustState } from "../src/trust.js";
const PINNED = new Date("2026-08-06T12:00:00.000Z");
describe("applyDecay", () => {
it("returns original confidence when elapsed days is zero", () => {
expect(applyDecay(0.8, 0)).toBe(0.8);
});
it("halves confidence after halfLifeDays", () => {
expect(applyDecay(1.0, 7, { halfLifeDays: 7, staleAfterDays: 30 })).toBeCloseTo(0.5, 3);
});
it("returns zero when elapsed days reaches staleAfterDays", () => {
expect(applyDecay(0.8, 30, { halfLifeDays: 7, staleAfterDays: 30 })).toBe(0);
});
});
describe("computeTrust", () => {
it("returns trusted for a fresh high-confidence item even without user verification", () => {
const result = computeTrust({
it("returns trusted for a fresh high-confidence item", () => {
const result = computeTrust(
{
confidence: 0.8,
verifiedByUser: false,
lastVerifiedAt: null,
quantity: 2,
updatedAt: new Date(),
});
updatedAt: PINNED,
},
PINNED,
);
expect(result.state).toBe("trusted");
expect(result.score).toBeGreaterThanOrEqual(60);
});
it("decays when last verification is old", () => {
const thirtyDaysAgo = new Date(Date.now() - 30 * 86_400_000);
const result = computeTrust({
confidence: 0.6,
const sevenDaysAgo = new Date(PINNED.getTime() - 7 * 86_400_000);
const result = computeTrust(
{
confidence: 0.8,
verifiedByUser: true,
lastVerifiedAt: thirtyDaysAgo,
lastVerifiedAt: sevenDaysAgo,
quantity: 1,
updatedAt: thirtyDaysAgo,
});
updatedAt: sevenDaysAgo,
},
PINNED,
);
expect(result.state).toBe("decaying");
});
it("is stale for very old unverified low-confidence items", () => {
const sixtyDaysAgo = new Date(Date.now() - 60 * 86_400_000);
const result = computeTrust({
const sixtyDaysAgo = new Date(PINNED.getTime() - 60 * 86_400_000);
const result = computeTrust(
{
confidence: 0.2,
verifiedByUser: false,
lastVerifiedAt: null,
quantity: 1,
updatedAt: sixtyDaysAgo,
});
},
PINNED,
);
expect(result.state).toBe("stale");
});
it("is trusted when user verified recently", () => {
const result = computeTrust({
const result = computeTrust(
{
confidence: 0.7,
verifiedByUser: true,
lastVerifiedAt: new Date(),
lastVerifiedAt: PINNED,
quantity: 1,
updatedAt: new Date(),
});
updatedAt: PINNED,
},
PINNED,
);
expect(result.state).toBe("trusted");
expect(result.score).toBeGreaterThanOrEqual(70);
});
it("uses custom decay profile to accelerate staleness", () => {
const tenDaysAgo = new Date(PINNED.getTime() - 10 * 86_400_000);
const fast = { halfLifeDays: 3, staleAfterDays: 10 };
const result = computeTrust(
{
confidence: 0.9,
verifiedByUser: true,
lastVerifiedAt: tenDaysAgo,
quantity: 1,
updatedAt: tenDaysAgo,
},
PINNED,
fast,
);
expect(result.state).toBe("stale");
});
});
describe("worstTrustState", () => {