@intelligo-dev/core 1.0.0-beta.1 → 1.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +6 -0
- package/README.md +102 -0
- package/dist/attachments/errors.d.ts +7 -0
- package/dist/attachments/errors.d.ts.map +1 -0
- package/dist/attachments/errors.js +11 -0
- package/dist/attachments/errors.js.map +1 -0
- package/dist/attachments/index.d.ts +8 -0
- package/dist/attachments/index.d.ts.map +1 -0
- package/dist/attachments/index.js +7 -0
- package/dist/attachments/index.js.map +1 -0
- package/dist/attachments/service.d.ts +45 -0
- package/dist/attachments/service.d.ts.map +1 -0
- package/dist/attachments/service.js +100 -0
- package/dist/attachments/service.js.map +1 -0
- package/dist/attachments/types.d.ts +6 -0
- package/dist/attachments/types.d.ts.map +1 -0
- package/dist/attachments/types.js +2 -0
- package/dist/attachments/types.js.map +1 -0
- package/dist/conversations/errors.d.ts +2 -8
- package/dist/conversations/errors.d.ts.map +1 -1
- package/dist/conversations/errors.js +2 -8
- package/dist/conversations/errors.js.map +1 -1
- package/dist/conversations/index.d.ts +4 -12
- package/dist/conversations/index.d.ts.map +1 -1
- package/dist/conversations/index.js +2 -11
- package/dist/conversations/index.js.map +1 -1
- package/dist/conversations/service.d.ts +49 -61
- package/dist/conversations/service.d.ts.map +1 -1
- package/dist/conversations/service.js +110 -83
- package/dist/conversations/service.js.map +1 -1
- package/dist/conversations/types.d.ts +1 -4
- package/dist/conversations/types.d.ts.map +1 -1
- package/dist/conversations/types.js +0 -3
- package/dist/conversations/types.js.map +1 -1
- package/dist/db/client.d.ts +21 -10
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +43 -18
- package/dist/db/client.js.map +1 -1
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +3 -7
- package/dist/db/index.js.map +1 -1
- package/dist/db/schema/agents.d.ts +14 -51
- package/dist/db/schema/agents.d.ts.map +1 -1
- package/dist/db/schema/agents.js +9 -21
- package/dist/db/schema/agents.js.map +1 -1
- package/dist/db/schema/ai.d.ts +86 -1556
- package/dist/db/schema/ai.d.ts.map +1 -1
- package/dist/db/schema/ai.js +32 -236
- package/dist/db/schema/ai.js.map +1 -1
- package/dist/db/schema/auth.d.ts +5 -34
- package/dist/db/schema/auth.d.ts.map +1 -1
- package/dist/db/schema/auth.js +25 -56
- package/dist/db/schema/auth.js.map +1 -1
- package/dist/db/schema/billing.d.ts +136 -107
- package/dist/db/schema/billing.d.ts.map +1 -1
- package/dist/db/schema/billing.js +72 -60
- package/dist/db/schema/billing.js.map +1 -1
- package/dist/db/schema/feature-flags.d.ts +3 -12
- package/dist/db/schema/feature-flags.d.ts.map +1 -1
- package/dist/db/schema/feature-flags.js +3 -12
- package/dist/db/schema/feature-flags.js.map +1 -1
- package/dist/db/schema/identity.d.ts +12 -274
- package/dist/db/schema/identity.d.ts.map +1 -1
- package/dist/db/schema/identity.js +19 -104
- package/dist/db/schema/identity.js.map +1 -1
- package/dist/db/schema/index.d.ts +8 -15
- package/dist/db/schema/index.d.ts.map +1 -1
- package/dist/db/schema/index.js +12 -42
- package/dist/db/schema/index.js.map +1 -1
- package/dist/db/schema/notifications.d.ts +3 -17
- package/dist/db/schema/notifications.d.ts.map +1 -1
- package/dist/db/schema/notifications.js +3 -17
- package/dist/db/schema/notifications.js.map +1 -1
- package/dist/db/schema/usage.d.ts +94 -77
- package/dist/db/schema/usage.d.ts.map +1 -1
- package/dist/db/schema/usage.js +59 -89
- package/dist/db/schema/usage.js.map +1 -1
- package/dist/db/validate.d.ts +2 -11
- package/dist/db/validate.d.ts.map +1 -1
- package/dist/db/validate.js +6 -17
- package/dist/db/validate.js.map +1 -1
- package/dist/db/workspace-queries.d.ts +5 -29
- package/dist/db/workspace-queries.d.ts.map +1 -1
- package/dist/db/workspace-queries.js +5 -29
- package/dist/db/workspace-queries.js.map +1 -1
- package/dist/documents/classifier.d.ts +5 -12
- package/dist/documents/classifier.d.ts.map +1 -1
- package/dist/documents/classifier.js +16 -16
- package/dist/documents/classifier.js.map +1 -1
- package/dist/documents/errors.d.ts +2 -10
- package/dist/documents/errors.d.ts.map +1 -1
- package/dist/documents/errors.js +2 -10
- package/dist/documents/errors.js.map +1 -1
- package/dist/documents/index.d.ts +4 -13
- package/dist/documents/index.d.ts.map +1 -1
- package/dist/documents/index.js +3 -12
- package/dist/documents/index.js.map +1 -1
- package/dist/documents/service.d.ts +19 -26
- package/dist/documents/service.d.ts.map +1 -1
- package/dist/documents/service.js +44 -38
- package/dist/documents/service.js.map +1 -1
- package/dist/documents/types.d.ts +6 -10
- package/dist/documents/types.d.ts.map +1 -1
- package/dist/documents/types.js +0 -3
- package/dist/documents/types.js.map +1 -1
- package/dist/email/brand.d.ts +17 -0
- package/dist/email/brand.d.ts.map +1 -0
- package/dist/email/brand.js +9 -0
- package/dist/email/brand.js.map +1 -0
- package/dist/email/index.d.ts +4 -4
- package/dist/email/index.js +4 -4
- package/dist/email/provider.d.ts +1 -7
- package/dist/email/provider.d.ts.map +1 -1
- package/dist/email/provider.js +10 -19
- package/dist/email/provider.js.map +1 -1
- package/dist/email/send.d.ts +12 -12
- package/dist/email/send.d.ts.map +1 -1
- package/dist/email/send.js +5 -19
- package/dist/email/send.js.map +1 -1
- package/dist/email/senders.d.ts +17 -30
- package/dist/email/senders.d.ts.map +1 -1
- package/dist/email/senders.js +33 -47
- package/dist/email/senders.js.map +1 -1
- package/dist/email/templates/base-layout.d.ts +1 -1
- package/dist/email/templates/base-layout.d.ts.map +1 -1
- package/dist/email/templates/base-layout.js +4 -6
- package/dist/email/templates/base-layout.js.map +1 -1
- package/dist/email/templates/index.d.ts +10 -10
- package/dist/email/templates/index.d.ts.map +1 -1
- package/dist/email/templates/index.js +10 -16
- package/dist/email/templates/index.js.map +1 -1
- package/dist/email/templates/password-reset.d.ts +2 -2
- package/dist/email/templates/password-reset.d.ts.map +1 -1
- package/dist/email/templates/password-reset.js +10 -22
- package/dist/email/templates/password-reset.js.map +1 -1
- package/dist/email/templates/payment-failed.d.ts +2 -2
- package/dist/email/templates/payment-failed.d.ts.map +1 -1
- package/dist/email/templates/payment-failed.js +11 -24
- package/dist/email/templates/payment-failed.js.map +1 -1
- package/dist/email/templates/quota-warning.d.ts +4 -4
- package/dist/email/templates/quota-warning.d.ts.map +1 -1
- package/dist/email/templates/quota-warning.js +19 -39
- package/dist/email/templates/quota-warning.js.map +1 -1
- package/dist/email/templates/subscription-confirmed.d.ts +2 -2
- package/dist/email/templates/subscription-confirmed.d.ts.map +1 -1
- package/dist/email/templates/subscription-confirmed.js +13 -28
- package/dist/email/templates/subscription-confirmed.js.map +1 -1
- package/dist/email/templates/trial-expiry.d.ts +2 -2
- package/dist/email/templates/trial-expiry.d.ts.map +1 -1
- package/dist/email/templates/trial-expiry.js +12 -36
- package/dist/email/templates/trial-expiry.js.map +1 -1
- package/dist/email/templates/trial-warning.d.ts +2 -2
- package/dist/email/templates/trial-warning.d.ts.map +1 -1
- package/dist/email/templates/trial-warning.js +15 -32
- package/dist/email/templates/trial-warning.js.map +1 -1
- package/dist/email/templates/verify-email.d.ts +2 -2
- package/dist/email/templates/verify-email.d.ts.map +1 -1
- package/dist/email/templates/verify-email.js +10 -22
- package/dist/email/templates/verify-email.js.map +1 -1
- package/dist/email/templates/welcome.d.ts +2 -2
- package/dist/email/templates/welcome.d.ts.map +1 -1
- package/dist/email/templates/welcome.js +13 -20
- package/dist/email/templates/welcome.js.map +1 -1
- package/dist/email/templates/workspace-invitation.d.ts +2 -2
- package/dist/email/templates/workspace-invitation.d.ts.map +1 -1
- package/dist/email/templates/workspace-invitation.js +12 -26
- package/dist/email/templates/workspace-invitation.js.map +1 -1
- package/dist/env.d.ts +5 -10
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +41 -31
- package/dist/env.js.map +1 -1
- package/dist/identity/audit.d.ts +11 -24
- package/dist/identity/audit.d.ts.map +1 -1
- package/dist/identity/audit.js +13 -27
- package/dist/identity/audit.js.map +1 -1
- package/dist/identity/errors.d.ts +4 -12
- package/dist/identity/errors.d.ts.map +1 -1
- package/dist/identity/errors.js +2 -8
- package/dist/identity/errors.js.map +1 -1
- package/dist/identity/index.d.ts +5 -13
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +4 -12
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/service.d.ts +13 -47
- package/dist/identity/service.d.ts.map +1 -1
- package/dist/identity/service.js +31 -78
- package/dist/identity/service.js.map +1 -1
- package/dist/identity/types.d.ts +1 -4
- package/dist/identity/types.d.ts.map +1 -1
- package/dist/identity/types.js +0 -3
- package/dist/identity/types.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -10
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -18
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +45 -49
- package/dist/logger.js.map +1 -1
- package/dist/money.d.ts +95 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/money.js +208 -0
- package/dist/money.js.map +1 -0
- package/dist/notifications/index.d.ts +9 -43
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +9 -49
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/triggers.d.ts +9 -32
- package/dist/notifications/triggers.d.ts.map +1 -1
- package/dist/notifications/triggers.js +21 -58
- package/dist/notifications/triggers.js.map +1 -1
- package/dist/notifications/types.d.ts +1 -10
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/notifications/types.js +0 -9
- package/dist/notifications/types.js.map +1 -1
- package/dist/prompt.d.ts +38 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +118 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +32 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +60 -0
- package/dist/registry.js.map +1 -0
- package/dist/request-context.d.ts +49 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +100 -0
- package/dist/request-context.js.map +1 -0
- package/dist/storage/index.d.ts +65 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +109 -0
- package/dist/storage/index.js.map +1 -0
- package/package.json +74 -24
- package/src/attachments/errors.ts +18 -0
- package/src/attachments/index.ts +22 -0
- package/src/attachments/service.ts +178 -0
- package/src/attachments/types.ts +6 -0
- package/src/conversations/errors.ts +45 -0
- package/src/conversations/index.ts +39 -0
- package/src/conversations/service.ts +594 -0
- package/src/conversations/types.ts +15 -0
- package/src/db/client.ts +91 -0
- package/src/db/index.ts +3 -0
- package/src/db/migrations/0000_baseline.sql +652 -0
- package/src/db/migrations/0001_reconcile_chain_built_databases.sql +53 -0
- package/src/db/migrations/0002_webhook_claim_lease.sql +1 -0
- package/src/db/migrations/README.md +74 -36
- package/src/db/migrations/legacy-chain.json +197 -0
- package/src/db/migrations/meta/0000_snapshot.json +4182 -157
- package/src/db/migrations/meta/0002_snapshot.json +2478 -368
- package/src/db/migrations/meta/_journal.json +6 -279
- package/src/db/schema/agents.ts +57 -0
- package/src/db/schema/ai.ts +174 -0
- package/src/db/schema/auth.ts +183 -0
- package/src/db/schema/billing.ts +209 -0
- package/src/db/schema/feature-flags.ts +20 -0
- package/src/db/schema/identity.ts +250 -0
- package/src/db/schema/index.ts +12 -0
- package/src/db/schema/notifications.ts +31 -0
- package/src/db/schema/usage.ts +269 -0
- package/src/db/validate.ts +63 -0
- package/src/db/workspace-queries.ts +64 -0
- package/src/documents/classifier.ts +61 -0
- package/src/documents/errors.ts +44 -0
- package/src/documents/index.ts +24 -0
- package/src/documents/service.ts +256 -0
- package/src/documents/types.ts +24 -0
- package/src/email/brand.ts +24 -0
- package/src/email/index.ts +19 -0
- package/src/email/provider.ts +278 -0
- package/src/email/send.ts +169 -0
- package/src/email/senders.ts +292 -0
- package/src/email/templates/base-layout.tsx +145 -0
- package/src/email/templates/index.ts +28 -0
- package/src/email/templates/password-reset.tsx +72 -0
- package/src/email/templates/payment-failed.tsx +77 -0
- package/src/email/templates/quota-warning.tsx +118 -0
- package/src/email/templates/subscription-confirmed.tsx +91 -0
- package/src/email/templates/trial-expiry.tsx +124 -0
- package/src/email/templates/trial-warning.tsx +104 -0
- package/src/email/templates/verify-email.tsx +72 -0
- package/src/email/templates/welcome.tsx +64 -0
- package/src/email/templates/workspace-invitation.tsx +105 -0
- package/src/env.ts +180 -0
- package/src/identity/audit.ts +65 -0
- package/src/identity/errors.ts +44 -0
- package/src/identity/index.ts +26 -0
- package/src/identity/service.ts +202 -0
- package/src/identity/types.ts +28 -0
- package/src/index.ts +4 -0
- package/src/logger.ts +198 -0
- package/src/money.ts +270 -0
- package/src/notifications/index.ts +108 -0
- package/src/notifications/triggers.ts +158 -0
- package/src/notifications/types.ts +18 -0
- package/src/prompt.ts +142 -0
- package/src/registry.ts +75 -0
- package/src/request-context.ts +137 -0
- package/src/storage/index.ts +153 -0
- package/dist/db/schema/rag.d.ts +0 -171
- package/dist/db/schema/rag.d.ts.map +0 -1
- package/dist/db/schema/rag.js +0 -42
- package/dist/db/schema/rag.js.map +0 -1
- package/src/db/migrations/0000_sharp_night_nurse.sql +0 -52
- package/src/db/migrations/0001_hesitant_vapor.sql +0 -40
- package/src/db/migrations/0002_numerous_lady_vermin.sql +0 -235
- package/src/db/migrations/0003_mighty_jean_grey.sql +0 -37
- package/src/db/migrations/0004_cynical_grandmaster.sql +0 -2
- package/src/db/migrations/0005_careful_switch.sql +0 -8
- package/src/db/migrations/0006_tense_blue_marvel.sql +0 -16
- package/src/db/migrations/0007_next_squadron_sinister.sql +0 -1
- package/src/db/migrations/0008_powerful_scream.sql +0 -39
- package/src/db/migrations/0009_sad_ink.sql +0 -1
- package/src/db/migrations/0010_shocking_omega_flight.sql +0 -2
- package/src/db/migrations/0011_ambiguous_otto_octavius.sql +0 -151
- package/src/db/migrations/0011_hnsw_vector_index.sql +0 -17
- package/src/db/migrations/0012_user_profiles.sql +0 -30
- package/src/db/migrations/0013_trending_seasonal_columns.sql +0 -9
- package/src/db/migrations/0014_add_product_type_to_agents.sql +0 -6
- package/src/db/migrations/0015_new_v1_tables.sql +0 -149
- package/src/db/migrations/0016_document_types.sql +0 -30
- package/src/db/migrations/0017_document_metadata.sql +0 -2
- package/src/db/migrations/0018_identity_graph.sql +0 -200
- package/src/db/migrations/0019_db_driven_prompts.sql +0 -20
- package/src/db/migrations/0020_pending_extractions.sql +0 -35
- package/src/db/migrations/0021_rag_documents.sql +0 -39
- package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +0 -70
- package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +0 -17
- package/src/db/migrations/0024_user_memories_hnsw.sql +0 -23
- package/src/db/migrations/0025_audit_trigger_errcode.sql +0 -21
- package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +0 -17
- package/src/db/migrations/0027_billing_settings_mnt_columns.sql +0 -54
- package/src/db/migrations/0028_trial_credits_normalized_email.sql +0 -37
- package/src/db/migrations/0029_usage_records_conversation_idx.sql +0 -13
- package/src/db/migrations/0030_pending_extractions_composite_idx.sql +0 -11
- package/src/db/migrations/0031_rag_documents_hnsw.sql +0 -16
- package/src/db/migrations/0032_rate_limit_unique_idx.sql +0 -16
- package/src/db/migrations/0033_pending_extractions_partial_idx.sql +0 -18
- package/src/db/migrations/0034_rate_limit_count.sql +0 -9
- package/src/db/migrations/0035_credit_reservations.sql +0 -24
- package/src/db/migrations/0036_executions_audit_jobs.sql +0 -96
- package/src/db/migrations/0037_rate_limit_minute_bucket.sql +0 -46
- package/src/db/migrations/0038_user_quotas_generic_usage.sql +0 -25
- package/src/db/migrations/0039_platform_admin_impersonation.sql +0 -27
- package/src/db/migrations/0040_ee_audit_chain.sql +0 -23
- package/src/db/migrations/meta/0001_snapshot.json +0 -631
- package/src/db/migrations/meta/0003_snapshot.json +0 -2488
- package/src/db/migrations/meta/0004_snapshot.json +0 -2500
- package/src/db/migrations/meta/0005_snapshot.json +0 -2548
- package/src/db/migrations/meta/0006_snapshot.json +0 -2650
- package/src/db/migrations/meta/0007_snapshot.json +0 -2657
- package/src/db/migrations/meta/0008_snapshot.json +0 -2719
- package/src/db/migrations/meta/0009_snapshot.json +0 -2726
- package/src/db/migrations/meta/0010_snapshot.json +0 -2739
- package/src/db/migrations/meta/0011_snapshot.json +0 -3886
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
-- Phase C — DB-driven prompts and model config.
|
|
2
|
-
--
|
|
3
|
-
-- Adds two columns to the agents table that turn the database into the
|
|
4
|
-
-- single source of truth for prompts and per-agent model selection. Both
|
|
5
|
-
-- columns are nullable so the migration is safe to apply before the seed
|
|
6
|
-
-- backfill runs; once the seed has populated the new fields, application
|
|
7
|
-
-- code reads only from the database (the legacy
|
|
8
|
-
-- apps/app/lib/prompts/career-advisor.ts file is removed in the same
|
|
9
|
-
-- phase).
|
|
10
|
-
--
|
|
11
|
-
-- system_prompt is shaped as the BilingualText JSON {"en": "...", "mn": "..."},
|
|
12
|
-
-- matching the existing `name` and `description` columns. model_config is a
|
|
13
|
-
-- forward-looking JSONB blob that will eventually replace `default_model`
|
|
14
|
-
-- with full routing rules; for now it stores at minimum { primary: "..." }.
|
|
15
|
-
--
|
|
16
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0019_db_driven_prompts.sql
|
|
17
|
-
|
|
18
|
-
ALTER TABLE "agents"
|
|
19
|
-
ADD COLUMN IF NOT EXISTS "system_prompt" jsonb,
|
|
20
|
-
ADD COLUMN IF NOT EXISTS "model_config" jsonb;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
-- Phase F — pending_extractions queue.
|
|
2
|
-
--
|
|
3
|
-
-- Background-job queue for fact extraction. The chat handler enqueues
|
|
4
|
-
-- one row per ended conversation; the worker (in @intelligo-dev/agents)
|
|
5
|
-
-- polls 'pending' rows, transitions them through 'processing' →
|
|
6
|
-
-- ('completed' | 'failed'), and the conversation_id uniqueness
|
|
7
|
-
-- constraint guarantees a conversation is never enqueued twice.
|
|
8
|
-
--
|
|
9
|
-
-- Cron poller wiring lands in a follow-up; this migration only
|
|
10
|
-
-- creates the storage layer so the worker has somewhere to read from.
|
|
11
|
-
--
|
|
12
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0020_pending_extractions.sql
|
|
13
|
-
|
|
14
|
-
CREATE TABLE IF NOT EXISTS "pending_extractions" (
|
|
15
|
-
"id" text PRIMARY KEY,
|
|
16
|
-
"conversation_id" text NOT NULL,
|
|
17
|
-
"workspace_id" text NOT NULL REFERENCES "organization"("id") ON DELETE CASCADE,
|
|
18
|
-
"user_id" text NOT NULL REFERENCES "users"("id") ON DELETE CASCADE,
|
|
19
|
-
"product_slug" text NOT NULL,
|
|
20
|
-
|
|
21
|
-
"status" text NOT NULL DEFAULT 'pending',
|
|
22
|
-
"attempts" integer NOT NULL DEFAULT 0,
|
|
23
|
-
"max_attempts" integer NOT NULL DEFAULT 3,
|
|
24
|
-
|
|
25
|
-
"last_error" text,
|
|
26
|
-
"next_retry_at" timestamp,
|
|
27
|
-
|
|
28
|
-
"enqueued_at" timestamp NOT NULL DEFAULT NOW(),
|
|
29
|
-
"started_at" timestamp,
|
|
30
|
-
"completed_at" timestamp
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
CREATE INDEX IF NOT EXISTS "pending_extractions_status_idx" ON "pending_extractions" ("status");
|
|
34
|
-
CREATE INDEX IF NOT EXISTS "pending_extractions_workspace_idx" ON "pending_extractions" ("workspace_id");
|
|
35
|
-
CREATE UNIQUE INDEX IF NOT EXISTS "pending_extractions_conversation_uniq" ON "pending_extractions" ("conversation_id");
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
-- Phase H — rag_documents table.
|
|
2
|
-
--
|
|
3
|
-
-- One shared table that backs every collection in
|
|
4
|
-
-- @intelligo-dev/agents/rag. Each typed Collection wrapper in a product
|
|
5
|
-
-- package writes through this table with its own `collection` slug
|
|
6
|
-
-- and Zod-validated metadata, so adding a new collection means
|
|
7
|
-
-- adding a TS file, not running a migration.
|
|
8
|
-
--
|
|
9
|
-
-- The pgvector index uses IVFFlat with cosine ops; the lists
|
|
10
|
-
-- parameter starts conservative for early-launch traffic and can be
|
|
11
|
-
-- tuned upward via REINDEX once we measure real recall vs. query
|
|
12
|
-
-- latency. The composite (collection, embedding) layout means a
|
|
13
|
-
-- per-collection ANN search filters first then ranks.
|
|
14
|
-
--
|
|
15
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0021_rag_documents.sql
|
|
16
|
-
|
|
17
|
-
CREATE TABLE IF NOT EXISTS "rag_documents" (
|
|
18
|
-
"id" text PRIMARY KEY,
|
|
19
|
-
"collection" text NOT NULL,
|
|
20
|
-
"external_id" text,
|
|
21
|
-
|
|
22
|
-
"content" text NOT NULL,
|
|
23
|
-
"metadata" jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
24
|
-
"embedding" vector(1536),
|
|
25
|
-
|
|
26
|
-
"created_at" timestamp NOT NULL DEFAULT NOW(),
|
|
27
|
-
"updated_at" timestamp NOT NULL DEFAULT NOW()
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
CREATE INDEX IF NOT EXISTS "rag_documents_collection_idx" ON "rag_documents" ("collection");
|
|
31
|
-
CREATE UNIQUE INDEX IF NOT EXISTS "rag_documents_collection_external_uniq" ON "rag_documents" ("collection", "external_id");
|
|
32
|
-
|
|
33
|
-
-- IVFFlat index for cosine similarity. lists=100 is a reasonable
|
|
34
|
-
-- starting point for ~10k documents per collection; bump after
|
|
35
|
-
-- measuring recall.
|
|
36
|
-
CREATE INDEX IF NOT EXISTS "rag_documents_embedding_idx"
|
|
37
|
-
ON "rag_documents"
|
|
38
|
-
USING ivfflat ("embedding" vector_cosine_ops)
|
|
39
|
-
WITH (lists = 100);
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
-- NOTE (2026-08-26): user_quotas is created here.
|
|
2
|
-
--
|
|
3
|
-
-- No migration ever created it — the table existed only in schema.ts,
|
|
4
|
-
-- so every environment got it from `drizzle-kit push` and replaying
|
|
5
|
-
-- the chain against an empty database died on the ALTER below. Of the
|
|
6
|
-
-- 49 tables in the schema it was the only one missing from the chain.
|
|
7
|
-
--
|
|
8
|
-
-- Created in this file rather than a new earlier one because this is
|
|
9
|
-
-- the first migration that touches the table; a repair migration would
|
|
10
|
-
-- have needed a number that sorts between 0021 and 0022. Guarded, so
|
|
11
|
-
-- databases that already have it are unaffected.
|
|
12
|
-
CREATE TABLE IF NOT EXISTS "user_quotas" (
|
|
13
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
14
|
-
"user_id" text NOT NULL,
|
|
15
|
-
"workspace_id" text NOT NULL,
|
|
16
|
-
"plan" text DEFAULT 'free' NOT NULL,
|
|
17
|
-
"chat_messages_used" integer DEFAULT 0 NOT NULL,
|
|
18
|
-
"assessments_used" integer DEFAULT 0 NOT NULL,
|
|
19
|
-
"reports_used" integer DEFAULT 0 NOT NULL,
|
|
20
|
-
"total_cost_usd" real DEFAULT 0 NOT NULL,
|
|
21
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
22
|
-
"updated_at" timestamp DEFAULT now() NOT NULL,
|
|
23
|
-
CONSTRAINT "user_quotas_user_id_unique" UNIQUE("user_id")
|
|
24
|
-
);
|
|
25
|
-
--> statement-breakpoint
|
|
26
|
-
DO $$ BEGIN
|
|
27
|
-
ALTER TABLE "user_quotas" ADD CONSTRAINT "user_quotas_user_id_users_id_fk"
|
|
28
|
-
FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;
|
|
29
|
-
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
30
|
-
END $$;
|
|
31
|
-
--> statement-breakpoint
|
|
32
|
-
DO $$ BEGIN
|
|
33
|
-
ALTER TABLE "user_quotas" ADD CONSTRAINT "user_quotas_workspace_id_organization_id_fk"
|
|
34
|
-
FOREIGN KEY ("workspace_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
|
35
|
-
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
36
|
-
END $$;
|
|
37
|
-
--> statement-breakpoint
|
|
38
|
-
CREATE INDEX IF NOT EXISTS "user_quotas_user_id_idx" ON "user_quotas" USING btree ("user_id");
|
|
39
|
-
--> statement-breakpoint
|
|
40
|
-
CREATE INDEX IF NOT EXISTS "user_quotas_workspace_id_idx" ON "user_quotas" USING btree ("workspace_id");
|
|
41
|
-
--> statement-breakpoint
|
|
42
|
-
|
|
43
|
-
-- Wave 4 — userQuotas.usage JSONB column for generic per-action counters.
|
|
44
|
-
--
|
|
45
|
-
-- Adds a generic `usage` JSONB column alongside the legacy career-only
|
|
46
|
-
-- chat_messages_used / assessments_used / reports_used integer columns.
|
|
47
|
-
-- The new column starts at '{}' for every row; recordFeatureUsage in
|
|
48
|
-
-- @intelligo-dev/billing/feature-quota.ts dual-writes both the legacy
|
|
49
|
-
-- column AND the corresponding `usage[action]` slot so the read path
|
|
50
|
-
-- can be flipped atomically in a follow-up commit once production
|
|
51
|
-
-- soak confirms the JSONB pathway is reliable.
|
|
52
|
-
--
|
|
53
|
-
-- Backfill query (optional, for any rows that already have legacy
|
|
54
|
-
-- counts that need to be reflected in the JSONB shape):
|
|
55
|
-
--
|
|
56
|
-
-- UPDATE user_quotas
|
|
57
|
-
-- SET usage = jsonb_build_object(
|
|
58
|
-
-- 'chat', chat_messages_used,
|
|
59
|
-
-- 'assessment', assessments_used,
|
|
60
|
-
-- 'report', reports_used
|
|
61
|
-
-- )
|
|
62
|
-
-- WHERE usage = '{}'::jsonb;
|
|
63
|
-
--
|
|
64
|
-
-- Run the backfill once after the deploy and verify counts match
|
|
65
|
-
-- before flipping the read path.
|
|
66
|
-
--
|
|
67
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0022_user_quotas_usage_jsonb.sql
|
|
68
|
-
|
|
69
|
-
ALTER TABLE "user_quotas"
|
|
70
|
-
ADD COLUMN IF NOT EXISTS "usage" jsonb NOT NULL DEFAULT '{}'::jsonb;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
-- AI-ARCHITECTURE follow-up: user_facts uniqueness must include user_id.
|
|
2
|
-
--
|
|
3
|
-
-- The original 0018 migration scoped the unique index to
|
|
4
|
-
-- (workspace_id, category, key), which made it impossible for two
|
|
5
|
-
-- members of the same org (family, classroom, team) to hold the
|
|
6
|
-
-- same fact key — e.g. two students both with `interest: mathematics`.
|
|
7
|
-
-- The second upsert would collide on the unique index and either
|
|
8
|
-
-- fail or silently overwrite the first user's fact.
|
|
9
|
-
--
|
|
10
|
-
-- Drop the old index and replace it with a (user_id, workspace_id,
|
|
11
|
-
-- category, key) unique index so facts are always scoped to the
|
|
12
|
-
-- owning user.
|
|
13
|
-
|
|
14
|
-
DROP INDEX IF EXISTS "user_facts_workspace_category_key_uniq";
|
|
15
|
-
--> statement-breakpoint
|
|
16
|
-
CREATE UNIQUE INDEX "user_facts_user_workspace_category_key_uniq"
|
|
17
|
-
ON "user_facts" USING btree ("user_id", "workspace_id", "category", "key");
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
-- AI-ARCHITECTURE follow-up: switch user_memories embedding index to HNSW.
|
|
2
|
-
--
|
|
3
|
-
-- The original 0018 migration used IVFFlat with `lists = 100`, a value
|
|
4
|
-
-- tuned for ~100k–1M rows. At launch the table starts empty, so for
|
|
5
|
-
-- the first several months IVFFlat recall will be degraded: with
|
|
6
|
-
-- rows << lists the probe count dominates and approximation quality
|
|
7
|
-
-- drops.
|
|
8
|
-
--
|
|
9
|
-
-- HNSW (available in pgvector >= 0.5.0) has no such tuning cliff —
|
|
10
|
-
-- recall is good from a handful of rows up through tens of millions,
|
|
11
|
-
-- at the cost of somewhat higher build time and ~2x memory per vector.
|
|
12
|
-
-- For this workload (synthesis-time recall, not per-request search)
|
|
13
|
-
-- that tradeoff is clearly worth it.
|
|
14
|
-
--
|
|
15
|
-
-- m / ef_construction values follow the pgvector docs' defaults
|
|
16
|
-
-- tuned for text embeddings; we can raise ef_construction later via
|
|
17
|
-
-- REINDEX if recall needs tightening.
|
|
18
|
-
|
|
19
|
-
DROP INDEX IF EXISTS "user_memories_embedding_ivfflat";
|
|
20
|
-
--> statement-breakpoint
|
|
21
|
-
CREATE INDEX "user_memories_embedding_hnsw"
|
|
22
|
-
ON "user_memories" USING hnsw ("embedding" vector_cosine_ops)
|
|
23
|
-
WITH (m = 16, ef_construction = 64);
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-- AI-ARCHITECTURE follow-up: fix audit trigger exception class.
|
|
2
|
-
--
|
|
3
|
-
-- 0018 used ERRCODE 25006 (read_only_sql_transaction) for the
|
|
4
|
-
-- append-only guard on user_memory_audit. That code is documented
|
|
5
|
-
-- for "SQL transaction is read-only" and is semantically wrong for
|
|
6
|
-
-- "this table rejects UPDATE/DELETE" — a Sentry filter or pg error
|
|
7
|
-
-- class handler could misroute the exception into the transient
|
|
8
|
-
-- retry bucket.
|
|
9
|
-
--
|
|
10
|
-
-- P0001 (raise_exception) is the correct generic class for
|
|
11
|
-
-- application-level invariants raised via RAISE EXCEPTION. The
|
|
12
|
-
-- trigger still fires on BEFORE UPDATE and BEFORE DELETE and the
|
|
13
|
-
-- hint stays PII-free.
|
|
14
|
-
|
|
15
|
-
CREATE OR REPLACE FUNCTION public.user_memory_audit_block_mutation()
|
|
16
|
-
RETURNS trigger AS $$
|
|
17
|
-
BEGIN
|
|
18
|
-
RAISE EXCEPTION 'user_memory_audit is append-only'
|
|
19
|
-
USING ERRCODE = 'P0001', HINT = 'INSERT new audit rows; do not UPDATE or DELETE existing ones.';
|
|
20
|
-
END;
|
|
21
|
-
$$ LANGUAGE plpgsql;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
-- AI-ARCHITECTURE follow-up: user_profile_snapshots composite primary key.
|
|
2
|
-
--
|
|
3
|
-
-- 0018 used user_id alone as the PK, which hardcoded "one snapshot per
|
|
4
|
-
-- user globally". The moment a user belongs to more than one workspace
|
|
5
|
-
-- (family + classroom, personal + team, etc.) those workspaces would
|
|
6
|
-
-- be forced to share a single synthesized profile — collapsing
|
|
7
|
-
-- context that should stay separate.
|
|
8
|
-
--
|
|
9
|
-
-- Switch to a composite PK on (user_id, workspace_id). Existing rows
|
|
10
|
-
-- already have workspace_id populated, so the migration is a straight
|
|
11
|
-
-- PK drop + re-add.
|
|
12
|
-
|
|
13
|
-
ALTER TABLE "user_profile_snapshots" DROP CONSTRAINT "user_profile_snapshots_pkey";
|
|
14
|
-
--> statement-breakpoint
|
|
15
|
-
ALTER TABLE "user_profile_snapshots"
|
|
16
|
-
ADD CONSTRAINT "user_profile_snapshots_user_id_workspace_id_pk"
|
|
17
|
-
PRIMARY KEY ("user_id", "workspace_id");
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
-- Wave 4 — MNT-denominated billing + live settings row.
|
|
2
|
-
--
|
|
3
|
-
-- Adds the authoritative MNT columns that `packages/billing/src/quota.ts`
|
|
4
|
-
-- reads on every chat turn (chargedMnt, balanceMnt, credits*Mnt) and the
|
|
5
|
-
-- singleton `billing_settings` row that holds the current FX rate and
|
|
6
|
-
-- margin multiplier. The application reads these in-process with a 60s
|
|
7
|
-
-- TTL cache so prices can be tuned without a code push.
|
|
8
|
-
--
|
|
9
|
-
-- Safe to re-run: all statements use IF NOT EXISTS.
|
|
10
|
-
--
|
|
11
|
-
-- Apply with:
|
|
12
|
-
-- psql $DATABASE_URL -f packages/core/src/db/migrations/0027_billing_settings_mnt_columns.sql
|
|
13
|
-
|
|
14
|
-
-- billing_settings — singleton config row (id = 'default').
|
|
15
|
-
CREATE TABLE IF NOT EXISTS "billing_settings" (
|
|
16
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
17
|
-
"usd_to_mnt_rate" integer NOT NULL DEFAULT 3450,
|
|
18
|
-
"margin_multiplier_bp" integer NOT NULL DEFAULT 400,
|
|
19
|
-
"updated_at" timestamp NOT NULL DEFAULT now()
|
|
20
|
-
);
|
|
21
|
-
--> statement-breakpoint
|
|
22
|
-
|
|
23
|
-
-- Seed the singleton row so getBillingSettings() has a hit on fresh installs.
|
|
24
|
-
INSERT INTO "billing_settings" ("id", "usd_to_mnt_rate", "margin_multiplier_bp")
|
|
25
|
-
VALUES ('default', 3450, 400)
|
|
26
|
-
ON CONFLICT ("id") DO NOTHING;
|
|
27
|
-
--> statement-breakpoint
|
|
28
|
-
|
|
29
|
-
-- credit_balances — MNT balance columns (legacy `balance` column left intact).
|
|
30
|
-
ALTER TABLE "credit_balances"
|
|
31
|
-
ADD COLUMN IF NOT EXISTS "balance_mnt" integer NOT NULL DEFAULT 0,
|
|
32
|
-
ADD COLUMN IF NOT EXISTS "total_purchased_mnt" integer NOT NULL DEFAULT 0,
|
|
33
|
-
ADD COLUMN IF NOT EXISTS "total_used_mnt" integer NOT NULL DEFAULT 0;
|
|
34
|
-
--> statement-breakpoint
|
|
35
|
-
|
|
36
|
-
-- usage_records — per-request MNT + trace fields.
|
|
37
|
-
ALTER TABLE "usage_records"
|
|
38
|
-
ADD COLUMN IF NOT EXISTS "margin_multiplier" real NOT NULL DEFAULT 0,
|
|
39
|
-
ADD COLUMN IF NOT EXISTS "fx_rate" real NOT NULL DEFAULT 0,
|
|
40
|
-
ADD COLUMN IF NOT EXISTS "charged_mnt" integer NOT NULL DEFAULT 0,
|
|
41
|
-
ADD COLUMN IF NOT EXISTS "request_id" text,
|
|
42
|
-
ADD COLUMN IF NOT EXISTS "conversation_id" text;
|
|
43
|
-
--> statement-breakpoint
|
|
44
|
-
|
|
45
|
-
-- monthly_usage — MNT aggregate for O(1) plan quota checks.
|
|
46
|
-
ALTER TABLE "monthly_usage"
|
|
47
|
-
ADD COLUMN IF NOT EXISTS "charged_mnt" integer NOT NULL DEFAULT 0;
|
|
48
|
-
--> statement-breakpoint
|
|
49
|
-
|
|
50
|
-
-- trial_credits — MNT-denominated grant replaces token counters.
|
|
51
|
-
ALTER TABLE "trial_credits"
|
|
52
|
-
ADD COLUMN IF NOT EXISTS "initial_credits_mnt" integer NOT NULL DEFAULT 5000,
|
|
53
|
-
ADD COLUMN IF NOT EXISTS "credits_used_mnt" integer NOT NULL DEFAULT 0,
|
|
54
|
-
ADD COLUMN IF NOT EXISTS "credits_remaining_mnt" integer NOT NULL DEFAULT 5000;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
-- Indexed per-email trial abuse check.
|
|
2
|
-
--
|
|
3
|
-
-- checkTrialAbuse() previously did `SELECT created_by_email FROM
|
|
4
|
-
-- trial_credits` (no WHERE, no LIMIT) and filtered in JS. That's a
|
|
5
|
-
-- full-table scan on every signup. Adding a normalized_email column
|
|
6
|
-
-- (populated at provisioning time) plus a btree index lets the same
|
|
7
|
-
-- check become `SELECT count(*) WHERE normalized_email = ?` — O(log n)
|
|
8
|
-
-- with index-only scan.
|
|
9
|
-
--
|
|
10
|
-
-- Apply with:
|
|
11
|
-
-- psql $DATABASE_URL -f packages/core/src/db/migrations/0028_trial_credits_normalized_email.sql
|
|
12
|
-
|
|
13
|
-
ALTER TABLE "trial_credits"
|
|
14
|
-
ADD COLUMN IF NOT EXISTS "normalized_email" text;
|
|
15
|
-
--> statement-breakpoint
|
|
16
|
-
|
|
17
|
-
-- Backfill existing rows so the abuse check behaves consistently for
|
|
18
|
-
-- trials provisioned before this migration. Mirrors the JS rule in
|
|
19
|
-
-- normalizeEmailForAbuseCheck: lowercase, drop +aliases, collapse dots
|
|
20
|
-
-- on gmail/googlemail, rewrite googlemail.com → gmail.com.
|
|
21
|
-
UPDATE "trial_credits"
|
|
22
|
-
SET "normalized_email" = (
|
|
23
|
-
CASE
|
|
24
|
-
WHEN split_part(lower(trim("created_by_email")), '@', 2) IN ('gmail.com', 'googlemail.com')
|
|
25
|
-
THEN replace(split_part(split_part(lower(trim("created_by_email")), '@', 1), '+', 1), '.', '')
|
|
26
|
-
|| '@gmail.com'
|
|
27
|
-
ELSE split_part(split_part(lower(trim("created_by_email")), '@', 1), '+', 1)
|
|
28
|
-
|| '@'
|
|
29
|
-
|| split_part(lower(trim("created_by_email")), '@', 2)
|
|
30
|
-
END
|
|
31
|
-
)
|
|
32
|
-
WHERE "created_by_email" IS NOT NULL
|
|
33
|
-
AND "normalized_email" IS NULL;
|
|
34
|
-
--> statement-breakpoint
|
|
35
|
-
|
|
36
|
-
CREATE INDEX IF NOT EXISTS "trial_credits_normalized_email_idx"
|
|
37
|
-
ON "trial_credits" ("normalized_email");
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
-- Cover the conversation deep-link path on the usage dashboard.
|
|
2
|
-
--
|
|
3
|
-
-- usage_table.tsx renders a per-row link to /chat/<conversationId>;
|
|
4
|
-
-- once traffic grows, any reverse lookup (e.g. "all usage for this
|
|
5
|
-
-- conversation") has to seq-scan on the nullable conversation_id
|
|
6
|
-
-- column. Adding the index now while the table is still small is
|
|
7
|
-
-- cheap and future-proofs the lookup path.
|
|
8
|
-
--
|
|
9
|
-
-- Apply with:
|
|
10
|
-
-- psql $DATABASE_URL -f packages/core/src/db/migrations/0029_usage_records_conversation_idx.sql
|
|
11
|
-
|
|
12
|
-
CREATE INDEX IF NOT EXISTS "usage_records_conversation_id_idx"
|
|
13
|
-
ON "usage_records" ("conversation_id");
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
-- DB-02: Composite index for efficient workspace-scoped extraction polling.
|
|
2
|
-
--
|
|
3
|
-
-- The worker queries "status = 'pending'" filtered by workspaceId, but the
|
|
4
|
-
-- existing index is on status alone. A scan across all workspaces is
|
|
5
|
-
-- expensive as the queue grows. This composite index allows index-only
|
|
6
|
-
-- scan for workspace-scoped pending-extraction queries.
|
|
7
|
-
--
|
|
8
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0030_pending_extractions_composite_idx.sql
|
|
9
|
-
|
|
10
|
-
CREATE INDEX IF NOT EXISTS "pending_extractions_status_workspace_idx"
|
|
11
|
-
ON "pending_extractions" ("status", "workspace_id");
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
-- DB-04: Migrate rag_documents vector index from IVFFlat to HNSW.
|
|
2
|
-
--
|
|
3
|
-
-- IVFFlat with lists=100 degrades at < 100k docs (probe count dominates,
|
|
4
|
-
-- approximation quality drops). HNSW has no tuning cliff — recall is good
|
|
5
|
-
-- from a handful of rows through tens of millions.
|
|
6
|
-
--
|
|
7
|
-
-- Template: 0011_hnsw_vector_index.sql + 0024_user_memories_hnsw.sql
|
|
8
|
-
-- m / ef_construction follow pgvector docs defaults for text embeddings.
|
|
9
|
-
--
|
|
10
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0031_rag_documents_hnsw.sql
|
|
11
|
-
|
|
12
|
-
DROP INDEX IF EXISTS "rag_documents_embedding_idx";
|
|
13
|
-
--> statement-breakpoint
|
|
14
|
-
CREATE INDEX "rag_documents_embedding_hnsw_idx"
|
|
15
|
-
ON "rag_documents" USING hnsw ("embedding" vector_cosine_ops)
|
|
16
|
-
WITH (m = 16, ef_construction = 64);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
-- DB-06: Unique constraint for rate limit deduplication.
|
|
2
|
-
--
|
|
3
|
-
-- Enables INSERT ... ON CONFLICT DO NOTHING as the authoritative rate limit
|
|
4
|
-
-- check instead of pre-count + insert (which allows 2× concurrent requests through).
|
|
5
|
-
-- The composite unique index is on (workspaceId, endpoint, minute_bucket).
|
|
6
|
-
-- minute_bucket floors requestedAt to the minute, so entries within the same
|
|
7
|
-
-- minute window conflict and only the first is inserted.
|
|
8
|
-
--
|
|
9
|
-
-- Apply with: psql $DATABASE_URL -f packages/core/src/db/migrations/0032_rate_limit_unique_idx.sql
|
|
10
|
-
|
|
11
|
-
CREATE UNIQUE INDEX IF NOT EXISTS "rate_limit_entries_unique_bucket_idx"
|
|
12
|
-
ON "rate_limit_entries" (
|
|
13
|
-
"workspace_id",
|
|
14
|
-
"endpoint",
|
|
15
|
-
date_trunc('minute', "requested_at")
|
|
16
|
-
);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
-- DB-01: Partial index for workspace-scoped pending extraction polling.
|
|
2
|
-
--
|
|
3
|
-
-- Workers claim rows by: WHERE status = 'pending' AND workspace_id = ?
|
|
4
|
-
-- The existing composite index (status, workspace_id) forces a scan of
|
|
5
|
-
-- ALL pending rows across all workspaces before filtering by workspace.
|
|
6
|
-
-- This partial index narrows the scan to just pending rows for the target
|
|
7
|
-
-- workspace — an index-only scan at O(log n) per workspace instead of
|
|
8
|
-
-- O(pending_rows_total).
|
|
9
|
-
--
|
|
10
|
-
-- Applies to: claimNextExtraction() and listPendingExtractions() in
|
|
11
|
-
-- packages/agents/src/extraction/queue.ts
|
|
12
|
-
--
|
|
13
|
-
-- Run with: psql $DATABASE_URL -f packages/core/src/db/migrations/0033_pending_extractions_partial_idx.sql
|
|
14
|
-
-- Or via: cd packages/core && pnpm drizzle-kit push
|
|
15
|
-
|
|
16
|
-
CREATE INDEX IF NOT EXISTS pending_extractions_workspace_pending_idx
|
|
17
|
-
ON pending_extractions (workspace_id)
|
|
18
|
-
WHERE status = 'pending';
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
-- B-05b: Rate limiter admits only ONE request per minute bucket.
|
|
2
|
-
--
|
|
3
|
-
-- The B-05 fix replaced check-then-insert with a unique constraint on
|
|
4
|
-
-- (workspace_id, endpoint, minute_bucket) + ON CONFLICT DO NOTHING, but
|
|
5
|
-
-- that admits exactly one request per bucket — the per-plan limit
|
|
6
|
-
-- (10/60/300 rpm) was never consulted. Add a counter column so the
|
|
7
|
-
-- upsert becomes DO UPDATE SET count = count + 1 RETURNING count, and
|
|
8
|
-
-- admission is count <= limit.
|
|
9
|
-
ALTER TABLE "rate_limit_entries" ADD COLUMN IF NOT EXISTS "count" integer DEFAULT 1 NOT NULL;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
-- B-06: Close the checkQuota → recordTokenUsage TOCTOU window.
|
|
2
|
-
--
|
|
3
|
-
-- checkQuota was a pure read; the debit happened minutes later in
|
|
4
|
-
-- recordTokenUsage, so N concurrent requests could all pass admission
|
|
5
|
-
-- against the same balance. Admission now inserts a reservation for the
|
|
6
|
-
-- worst-case MNT estimate in the same transaction that sums the other
|
|
7
|
-
-- active reservations. recordTokenUsage settles it; abandoned rows
|
|
8
|
-
-- expire via expires_at (TTL >= chat route maxDuration) and are cleaned
|
|
9
|
-
-- by the cleanup cron.
|
|
10
|
-
CREATE TABLE IF NOT EXISTS "credit_reservations" (
|
|
11
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
12
|
-
"workspace_id" text NOT NULL,
|
|
13
|
-
"request_id" text NOT NULL,
|
|
14
|
-
"estimated_mnt" integer NOT NULL,
|
|
15
|
-
"status" text DEFAULT 'active' NOT NULL,
|
|
16
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
17
|
-
"expires_at" timestamp NOT NULL,
|
|
18
|
-
"settled_at" timestamp,
|
|
19
|
-
CONSTRAINT "credit_reservations_request_id_unique" UNIQUE("request_id")
|
|
20
|
-
);
|
|
21
|
-
--> statement-breakpoint
|
|
22
|
-
ALTER TABLE "credit_reservations" ADD CONSTRAINT "credit_reservations_workspace_id_organization_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
|
23
|
-
--> statement-breakpoint
|
|
24
|
-
CREATE INDEX IF NOT EXISTS "credit_reservations_active_idx" ON "credit_reservations" USING btree ("workspace_id","status","expires_at");
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
-- Phase 2: the SaaS execution boundary (ADR-0003, ADR-0004).
|
|
2
|
-
--
|
|
3
|
-
-- Three tables, three owning packages:
|
|
4
|
-
-- executions → @intelligo-dev/executions — one row per AI run: actor,
|
|
5
|
-
-- workspace, capability, entitlement outcome, status,
|
|
6
|
-
-- usage, cost. Records nothing about agents/tools/
|
|
7
|
-
-- messages, which stay native to the AI framework.
|
|
8
|
-
-- audit_events → @intelligo-dev/audit — append-only who-did-what.
|
|
9
|
-
-- jobs → @intelligo-dev/jobs — Postgres-backed queue (claimed
|
|
10
|
-
-- with FOR UPDATE SKIP LOCKED).
|
|
11
|
-
--
|
|
12
|
-
-- usage_records gains execution_id rather than being duplicated into a
|
|
13
|
-
-- new usage_events table: it already IS the per-request usage/cost
|
|
14
|
-
-- detail. The rename happens with the Phase 4 package split.
|
|
15
|
-
|
|
16
|
-
CREATE TABLE IF NOT EXISTS "executions" (
|
|
17
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
18
|
-
"workspace_id" text NOT NULL,
|
|
19
|
-
"user_id" text,
|
|
20
|
-
"capability" text NOT NULL,
|
|
21
|
-
"request_id" text NOT NULL,
|
|
22
|
-
"status" text DEFAULT 'running' NOT NULL,
|
|
23
|
-
"model" text,
|
|
24
|
-
"input_tokens" integer,
|
|
25
|
-
"output_tokens" integer,
|
|
26
|
-
"total_tokens" integer,
|
|
27
|
-
"charged_mnt" integer,
|
|
28
|
-
"reserved_mnt" integer,
|
|
29
|
-
"refusal_reason" text,
|
|
30
|
-
"error_message" text,
|
|
31
|
-
"started_at" timestamp DEFAULT now() NOT NULL,
|
|
32
|
-
"finished_at" timestamp,
|
|
33
|
-
"duration_ms" integer,
|
|
34
|
-
"metadata" jsonb,
|
|
35
|
-
CONSTRAINT "executions_request_id_unique" UNIQUE("request_id")
|
|
36
|
-
);
|
|
37
|
-
--> statement-breakpoint
|
|
38
|
-
CREATE TABLE IF NOT EXISTS "audit_events" (
|
|
39
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
40
|
-
"workspace_id" text,
|
|
41
|
-
"actor_id" text,
|
|
42
|
-
"actor_kind" text DEFAULT 'user' NOT NULL,
|
|
43
|
-
"action" text NOT NULL,
|
|
44
|
-
"resource_kind" text NOT NULL,
|
|
45
|
-
"resource_id" text,
|
|
46
|
-
"outcome" text DEFAULT 'ok' NOT NULL,
|
|
47
|
-
"metadata" jsonb,
|
|
48
|
-
"created_at" timestamp DEFAULT now() NOT NULL
|
|
49
|
-
);
|
|
50
|
-
--> statement-breakpoint
|
|
51
|
-
CREATE TABLE IF NOT EXISTS "jobs" (
|
|
52
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
53
|
-
"workspace_id" text,
|
|
54
|
-
"kind" text NOT NULL,
|
|
55
|
-
"payload" jsonb,
|
|
56
|
-
"status" text DEFAULT 'pending' NOT NULL,
|
|
57
|
-
"attempts" integer DEFAULT 0 NOT NULL,
|
|
58
|
-
"max_attempts" integer DEFAULT 3 NOT NULL,
|
|
59
|
-
"run_at" timestamp DEFAULT now() NOT NULL,
|
|
60
|
-
"started_at" timestamp,
|
|
61
|
-
"finished_at" timestamp,
|
|
62
|
-
"last_error" text,
|
|
63
|
-
"created_at" timestamp DEFAULT now() NOT NULL
|
|
64
|
-
);
|
|
65
|
-
--> statement-breakpoint
|
|
66
|
-
ALTER TABLE "usage_records" ADD COLUMN IF NOT EXISTS "execution_id" text;
|
|
67
|
-
--> statement-breakpoint
|
|
68
|
-
ALTER TABLE "executions" ADD CONSTRAINT "executions_workspace_id_organization_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
|
69
|
-
--> statement-breakpoint
|
|
70
|
-
ALTER TABLE "executions" ADD CONSTRAINT "executions_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
71
|
-
--> statement-breakpoint
|
|
72
|
-
ALTER TABLE "audit_events" ADD CONSTRAINT "audit_events_workspace_id_organization_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
|
73
|
-
--> statement-breakpoint
|
|
74
|
-
ALTER TABLE "audit_events" ADD CONSTRAINT "audit_events_actor_id_users_id_fk" FOREIGN KEY ("actor_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;
|
|
75
|
-
--> statement-breakpoint
|
|
76
|
-
ALTER TABLE "jobs" ADD CONSTRAINT "jobs_workspace_id_organization_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;
|
|
77
|
-
--> statement-breakpoint
|
|
78
|
-
CREATE INDEX IF NOT EXISTS "executions_workspace_started_idx" ON "executions" USING btree ("workspace_id","started_at");
|
|
79
|
-
--> statement-breakpoint
|
|
80
|
-
CREATE INDEX IF NOT EXISTS "executions_status_idx" ON "executions" USING btree ("status","started_at");
|
|
81
|
-
--> statement-breakpoint
|
|
82
|
-
CREATE INDEX IF NOT EXISTS "executions_capability_idx" ON "executions" USING btree ("capability","started_at");
|
|
83
|
-
--> statement-breakpoint
|
|
84
|
-
CREATE INDEX IF NOT EXISTS "audit_events_workspace_created_idx" ON "audit_events" USING btree ("workspace_id","created_at");
|
|
85
|
-
--> statement-breakpoint
|
|
86
|
-
CREATE INDEX IF NOT EXISTS "audit_events_action_idx" ON "audit_events" USING btree ("action","created_at");
|
|
87
|
-
--> statement-breakpoint
|
|
88
|
-
CREATE INDEX IF NOT EXISTS "audit_events_resource_idx" ON "audit_events" USING btree ("resource_kind","resource_id");
|
|
89
|
-
--> statement-breakpoint
|
|
90
|
-
CREATE INDEX IF NOT EXISTS "jobs_claim_idx" ON "jobs" USING btree ("status","run_at");
|
|
91
|
-
--> statement-breakpoint
|
|
92
|
-
CREATE INDEX IF NOT EXISTS "jobs_kind_idx" ON "jobs" USING btree ("kind","status");
|
|
93
|
-
--> statement-breakpoint
|
|
94
|
-
CREATE INDEX IF NOT EXISTS "jobs_workspace_idx" ON "jobs" USING btree ("workspace_id");
|
|
95
|
-
--> statement-breakpoint
|
|
96
|
-
CREATE INDEX IF NOT EXISTS "usage_records_execution_id_idx" ON "usage_records" USING btree ("execution_id");
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
-- Repair the rate-limit schema so a fresh database matches the code.
|
|
2
|
-
--
|
|
3
|
-
-- 0032 documented a unique constraint on (workspace_id, endpoint,
|
|
4
|
-
-- minute_bucket) but created an EXPRESSION index on
|
|
5
|
-
-- date_trunc('minute', requested_at) instead, and no migration ever
|
|
6
|
-
-- added the minute_bucket column. checkRateLimit's
|
|
7
|
-
-- `ON CONFLICT (workspace_id, endpoint, minute_bucket)` can only
|
|
8
|
-
-- resolve against a constraint on those literal columns, so replaying
|
|
9
|
-
-- the committed history against an empty database produced a
|
|
10
|
-
-- rate_limit_entries table that throws
|
|
11
|
-
-- `column "minute_bucket" does not exist` on every chat request.
|
|
12
|
-
-- Production only worked because the live database had been synced
|
|
13
|
-
-- with `drizzle-kit push` straight from schema.ts, bypassing these
|
|
14
|
-
-- files entirely.
|
|
15
|
-
|
|
16
|
-
ALTER TABLE "rate_limit_entries"
|
|
17
|
-
ADD COLUMN IF NOT EXISTS "minute_bucket" timestamp;
|
|
18
|
-
--> statement-breakpoint
|
|
19
|
-
|
|
20
|
-
-- Backfill so the NOT NULL below can be applied to existing rows.
|
|
21
|
-
UPDATE "rate_limit_entries"
|
|
22
|
-
SET "minute_bucket" = date_trunc('minute', "requested_at")
|
|
23
|
-
WHERE "minute_bucket" IS NULL;
|
|
24
|
-
--> statement-breakpoint
|
|
25
|
-
|
|
26
|
-
ALTER TABLE "rate_limit_entries"
|
|
27
|
-
ALTER COLUMN "minute_bucket" SET NOT NULL;
|
|
28
|
-
--> statement-breakpoint
|
|
29
|
-
|
|
30
|
-
-- The expression index carries the name the constraint needs.
|
|
31
|
-
DROP INDEX IF EXISTS "rate_limit_entries_unique_bucket_idx";
|
|
32
|
-
--> statement-breakpoint
|
|
33
|
-
|
|
34
|
-
-- Collapse any duplicate buckets the expression index allowed through
|
|
35
|
-
-- before the real constraint can be created.
|
|
36
|
-
DELETE FROM "rate_limit_entries" a
|
|
37
|
-
USING "rate_limit_entries" b
|
|
38
|
-
WHERE a.ctid < b.ctid
|
|
39
|
-
AND a."workspace_id" = b."workspace_id"
|
|
40
|
-
AND a."endpoint" = b."endpoint"
|
|
41
|
-
AND a."minute_bucket" = b."minute_bucket";
|
|
42
|
-
--> statement-breakpoint
|
|
43
|
-
|
|
44
|
-
ALTER TABLE "rate_limit_entries"
|
|
45
|
-
ADD CONSTRAINT "rate_limit_entries_unique_bucket_idx"
|
|
46
|
-
UNIQUE ("workspace_id", "endpoint", "minute_bucket");
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
-- Finish the user_quotas cutover to a generic usage map (B6).
|
|
2
|
-
--
|
|
3
|
-
-- The table carried three career-specific counters — chat_messages_used,
|
|
4
|
-
-- assessments_used, reports_used — alongside the generic `usage` JSONB
|
|
5
|
-
-- added in migration 0022. Since then recordFeatureUsage dual-wrote both
|
|
6
|
-
-- while reads still preferred the columns, so a public package's schema
|
|
7
|
-
-- named a vertical's actions and no vertical could add a fourth counter
|
|
8
|
-
-- without a migration to Intelligo (ADR-0004, ADR-0006).
|
|
9
|
-
--
|
|
10
|
-
-- Backfill first: rows written since the dual-write started already have
|
|
11
|
-
-- the keys in `usage`, and those values win. Rows that predate it have a
|
|
12
|
-
-- non-zero column and no key, so the built object supplies them. `||` is
|
|
13
|
-
-- right-biased, hence usage on the right.
|
|
14
|
-
|
|
15
|
-
UPDATE user_quotas
|
|
16
|
-
SET usage = jsonb_build_object(
|
|
17
|
-
'chat', COALESCE(chat_messages_used, 0),
|
|
18
|
-
'assessment', COALESCE(assessments_used, 0),
|
|
19
|
-
'report', COALESCE(reports_used, 0)
|
|
20
|
-
) || COALESCE(usage, '{}'::jsonb);
|
|
21
|
-
|
|
22
|
-
ALTER TABLE user_quotas
|
|
23
|
-
DROP COLUMN IF EXISTS chat_messages_used,
|
|
24
|
-
DROP COLUMN IF EXISTS assessments_used,
|
|
25
|
-
DROP COLUMN IF EXISTS reports_used;
|