lurqrun 0.1.6 → 0.1.7
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/README.md +18 -10
- package/dist/auditHandler-JCOJSUYW.js +23 -0
- package/dist/bin/lurq.js +3090 -23306
- package/dist/browserAuth-B6G27USY.js +95 -0
- package/dist/cache-DKI34SVS.js +12 -0
- package/dist/check-2FDGUOV7.js +192 -0
- package/dist/checkUpgrade-F2WESBPM.js +103 -0
- package/dist/chunk-2VMOWSRY.js +300 -0
- package/dist/chunk-3GHJR7XR.js +2049 -0
- package/dist/chunk-3N3Q3DSW.js +214 -0
- package/dist/chunk-4ESO33J6.js +34 -0
- package/dist/chunk-4F7ZESPO.js +132 -0
- package/dist/chunk-4KCPOMG6.js +68 -0
- package/dist/chunk-4ZYCIMY4.js +155 -0
- package/dist/chunk-63MUJNZL.js +318 -0
- package/dist/chunk-6AAEVQ7I.js +6336 -0
- package/dist/chunk-6EQ3ARXA.js +304 -0
- package/dist/chunk-6L3U7DZ5.js +23 -0
- package/dist/chunk-AHBP533R.js +220 -0
- package/dist/chunk-B43LCXBM.js +223 -0
- package/dist/chunk-BCANRN5B.js +33 -0
- package/dist/chunk-BUALU27S.js +123 -0
- package/dist/chunk-BULZAX2U.js +1554 -0
- package/dist/chunk-BV32UNLL.js +154 -0
- package/dist/chunk-C6GLE626.js +160 -0
- package/dist/chunk-CIDWNUAP.js +145 -0
- package/dist/chunk-CUP36ND3.js +2126 -0
- package/dist/chunk-CW5HJ3LX.js +96 -0
- package/dist/chunk-DB2VF5UD.js +315 -0
- package/dist/chunk-DWAGCNEL.js +210 -0
- package/dist/chunk-EA3DP5HG.js +293 -0
- package/dist/chunk-ELGCAM7P.js +184 -0
- package/dist/chunk-FW6BD2NO.js +1915 -0
- package/dist/chunk-GE37NVLN.js +15 -0
- package/dist/chunk-GPTKSNR6.js +171 -0
- package/dist/chunk-GRJXQBQZ.js +793 -0
- package/dist/chunk-HWBBVLOT.js +92 -0
- package/dist/chunk-I2JUKN6Z.js +24 -0
- package/dist/chunk-I3M2KJXB.js +56 -0
- package/dist/chunk-IQ4SDKKY.js +733 -0
- package/dist/chunk-J5FZYN4A.js +116 -0
- package/dist/chunk-L6N4JFW2.js +263 -0
- package/dist/chunk-LBFGSSF2.js +126 -0
- package/dist/chunk-LEGPB7DO.js +81 -0
- package/dist/chunk-LO35HLQZ.js +219 -0
- package/dist/chunk-LRD4GBYE.js +73 -0
- package/dist/chunk-LUAKDHLZ.js +40 -0
- package/dist/chunk-LYMPYETA.js +965 -0
- package/dist/chunk-M6NYEXCW.js +38 -0
- package/dist/chunk-MHUEVBVO.js +35 -0
- package/dist/chunk-MYGSLK44.js +37 -0
- package/dist/chunk-NH5I4KHH.js +201 -0
- package/dist/chunk-OQS4GUSI.js +1391 -0
- package/dist/chunk-PSX3GIAN.js +176 -0
- package/dist/chunk-Q5VPF4WI.js +26 -0
- package/dist/chunk-QKGYDMWB.js +7409 -0
- package/dist/chunk-QSL6QN5X.js +115 -0
- package/dist/chunk-SHCEBP3J.js +107 -0
- package/dist/chunk-SJOVFF7B.js +201 -0
- package/dist/chunk-ST2X2GYN.js +373 -0
- package/dist/chunk-TNTXWSYA.js +19 -0
- package/dist/chunk-U5AT3TD4.js +2128 -0
- package/dist/chunk-UDVNA7EA.js +483 -0
- package/dist/chunk-VL2E5T2A.js +109 -0
- package/dist/chunk-VLRHFMGJ.js +58 -0
- package/dist/chunk-WHX2ZFCG.js +4048 -0
- package/dist/chunk-WQ23REYT.js +37 -0
- package/dist/chunk-XBIDMHSK.js +15425 -0
- package/dist/chunk-Y5GI7RL3.js +66 -0
- package/dist/client-IRKAMDYZ.js +15 -0
- package/dist/commands-FIL5ET6P.js +911 -0
- package/dist/compat-R3UTFQ5Q.js +201 -0
- package/dist/dashboardIssue-WYYMBFIB.js +192 -0
- package/dist/diff-GZA2774U.js +13 -0
- package/dist/dist-4XXIXHHZ.js +12945 -0
- package/dist/e2b-FVPHDULZ.js +172 -0
- package/dist/extract-NKGKLIVT.js +444 -0
- package/dist/fetch-QYTUJVG2.js +22 -0
- package/dist/firstTouch-QQTJH4QX.js +55 -0
- package/dist/handlers-GEJAVZDK.js +53 -0
- package/dist/http-ETPYMBGD.js +5360 -0
- package/dist/ingestQueue-VKN4KBIF.js +35 -0
- package/dist/install-EK3W2COX.js +20 -0
- package/dist/installSkill-VQJWJVCL.js +52 -0
- package/dist/inventory-5AWSLJYU.js +31 -0
- package/dist/local-XPZMRH5R.js +13 -0
- package/dist/mcp-3JHD5SUZ.js +472 -0
- package/dist/mcpHandlers-QFN4MCFL.js +22 -0
- package/dist/mcpScan-QZHWENIP.js +1871 -0
- package/dist/mcpScanWorkflow-JPYCBGC4.js +81 -0
- package/dist/mcpStack-BYJCZNIV.js +20 -0
- package/dist/packages-THVFMWFP.js +42 -0
- package/dist/plan-V4OEI3J4.js +463 -0
- package/dist/planView-JRXGCG2N.js +79 -0
- package/dist/policy-3P6BGRDN.js +115 -0
- package/dist/references-6N7VEPHT.js +14 -0
- package/dist/release-4U4ABNSJ.js +128 -0
- package/dist/remote-YGCXYI4V.js +32 -0
- package/dist/reportRuns-CKQQYLY4.js +64 -0
- package/dist/sandbox-MEZLAODF.js +39 -0
- package/dist/server-KFUD5X57.js +55 -0
- package/dist/surface-V62GE554.js +141 -0
- package/dist/surface-YL6O67W3.js +36 -0
- package/dist/surfaceHandlers-X2IZKA3E.js +20 -0
- package/dist/typecheck-X7U5ELMR.js +268 -0
- package/dist/types-M5JP2W3D.js +10 -0
- package/dist/uninstall-P7RGBX6G.js +174 -0
- package/dist/upgrade-NQ5IWFZB.js +596 -0
- package/dist/upgradePlan-A4LRKLEG.js +146 -0
- package/dist/userConfig-Z3GQE776.js +20 -0
- package/dist/watch-DGFMWUDL.js +214 -0
- package/package.json +26 -21
- package/templates/agent-rules.md +4 -4
- package/templates/skill-instructions.md +13 -14
- package/dist/bin/lurq.js.map +0 -1
- package/dist/index.d.ts +0 -805
- package/dist/index.js +0 -23570
- package/dist/index.js.map +0 -1
- package/drizzle/0000_confused_fabian_cortez.sql +0 -54
- package/drizzle/0001_aspiring_timeslip.sql +0 -15
- package/drizzle/0002_lyrical_lila_cheney.sql +0 -14
- package/drizzle/0003_violet_giant_girl.sql +0 -14
- package/drizzle/0004_slim_valeria_richards.sql +0 -15
- package/drizzle/0005_petite_luke_cage.sql +0 -12
- package/drizzle/0006_calm_nighthawk.sql +0 -3
- package/drizzle/0007_slimy_naoko.sql +0 -1
- package/drizzle/0008_peaceful_tigra.sql +0 -1
- package/drizzle/0009_smooth_harrier.sql +0 -10
- package/drizzle/0010_curved_amphibian.sql +0 -2
- package/drizzle/0011_compat_provenance_closures.sql +0 -11
- package/drizzle/0012_api_surfaces.sql +0 -9
- package/drizzle/0013_nice_thanos.sql +0 -1
- package/drizzle/0014_luxuriant_malcolm_colcord.sql +0 -10
- package/drizzle/0015_past_fat_cobra.sql +0 -11
- package/drizzle/0016_futuristic_junta.sql +0 -50
- package/drizzle/0017_absent_grandmaster.sql +0 -20
- package/drizzle/0018_rainy_proemial_gods.sql +0 -1
- package/drizzle/0019_dashing_korvac.sql +0 -11
- package/drizzle/0020_normal_vulture.sql +0 -3
- package/drizzle/0021_dazzling_blue_shield.sql +0 -17
- package/drizzle/0022_massive_ghost_rider.sql +0 -24
- package/drizzle/0023_next_shatterstar.sql +0 -1
- package/drizzle/0024_dusty_maelstrom.sql +0 -15
- package/drizzle/0025_gifted_harpoon.sql +0 -5
- package/drizzle/0026_awesome_mordo.sql +0 -1
- package/drizzle/0027_charming_ulik.sql +0 -2
- package/drizzle/0028_romantic_loners.sql +0 -2
- package/drizzle/0029_busy_korvac.sql +0 -16
- package/drizzle/0030_steady_mathemanic.sql +0 -6
- package/drizzle/0031_redundant_maginty.sql +0 -2
- package/drizzle/0032_stack_resolutions.sql +0 -14
- package/drizzle/0033_graceful_tyger_tiger.sql +0 -3
- package/drizzle/0034_uneven_thunderbird.sql +0 -1
- package/drizzle/0035_api_key_scopes.sql +0 -1
- package/drizzle/0036_policy_audit.sql +0 -21
- package/drizzle/0037_subscription_seats.sql +0 -1
- package/drizzle/0038_symbol_offsets.sql +0 -2
- package/drizzle/0039_mcp_runtime_scans.sql +0 -80
- package/drizzle/0040_subscription_overage_and_interval.sql +0 -4
- package/drizzle/0041_account_email.sql +0 -38
- package/drizzle/0042_alert_channels.sql +0 -21
- package/drizzle/meta/0000_snapshot.json +0 -370
- package/drizzle/meta/0001_snapshot.json +0 -482
- package/drizzle/meta/0002_snapshot.json +0 -575
- package/drizzle/meta/0003_snapshot.json +0 -667
- package/drizzle/meta/0004_snapshot.json +0 -769
- package/drizzle/meta/0005_snapshot.json +0 -864
- package/drizzle/meta/0006_snapshot.json +0 -882
- package/drizzle/meta/0007_snapshot.json +0 -876
- package/drizzle/meta/0008_snapshot.json +0 -882
- package/drizzle/meta/0009_snapshot.json +0 -948
- package/drizzle/meta/0010_snapshot.json +0 -969
- package/drizzle/meta/0011_snapshot.json +0 -1049
- package/drizzle/meta/0012_snapshot.json +0 -1115
- package/drizzle/meta/0013_snapshot.json +0 -1121
- package/drizzle/meta/0014_snapshot.json +0 -1190
- package/drizzle/meta/0015_snapshot.json +0 -1280
- package/drizzle/meta/0016_snapshot.json +0 -1683
- package/drizzle/meta/0017_snapshot.json +0 -1834
- package/drizzle/meta/0018_snapshot.json +0 -1834
- package/drizzle/meta/0019_snapshot.json +0 -1909
- package/drizzle/meta/0020_snapshot.json +0 -1921
- package/drizzle/meta/0021_snapshot.json +0 -2045
- package/drizzle/meta/0022_snapshot.json +0 -2246
- package/drizzle/meta/0023_snapshot.json +0 -2252
- package/drizzle/meta/0024_snapshot.json +0 -2375
- package/drizzle/meta/0025_snapshot.json +0 -2407
- package/drizzle/meta/0026_snapshot.json +0 -2413
- package/drizzle/meta/0027_snapshot.json +0 -2425
- package/drizzle/meta/0028_snapshot.json +0 -2438
- package/drizzle/meta/0029_snapshot.json +0 -2546
- package/drizzle/meta/0030_snapshot.json +0 -2586
- package/drizzle/meta/0031_snapshot.json +0 -2598
- package/drizzle/meta/0032_snapshot.json +0 -2699
- package/drizzle/meta/0033_snapshot.json +0 -2712
- package/drizzle/meta/0034_snapshot.json +0 -2719
- package/drizzle/meta/0035_snapshot.json +0 -2726
- package/drizzle/meta/0036_snapshot.json +0 -2876
- package/drizzle/meta/0037_snapshot.json +0 -2883
- package/drizzle/meta/0038_snapshot.json +0 -2895
- package/drizzle/meta/0039_snapshot.json +0 -3501
- package/drizzle/meta/0040_snapshot.json +0 -3527
- package/drizzle/meta/0041_snapshot.json +0 -3824
- package/drizzle/meta/0042_snapshot.json +0 -3960
- package/drizzle/meta/_journal.json +0 -307
- package/src/data/seed.json +0 -253
|
@@ -0,0 +1,965 @@
|
|
|
1
|
+
import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
EMBEDDING_DIM
|
|
4
|
+
} from "./chunk-GPTKSNR6.js";
|
|
5
|
+
import {
|
|
6
|
+
__export,
|
|
7
|
+
init_esm_shims
|
|
8
|
+
} from "./chunk-I3M2KJXB.js";
|
|
9
|
+
|
|
10
|
+
// src/db/schema.ts
|
|
11
|
+
var schema_exports = {};
|
|
12
|
+
__export(schema_exports, {
|
|
13
|
+
UNBOUNDED_ARITY: () => UNBOUNDED_ARITY,
|
|
14
|
+
apiKeys: () => apiKeys,
|
|
15
|
+
apiSurfaces: () => apiSurfaces,
|
|
16
|
+
askSpendDaily: () => askSpendDaily,
|
|
17
|
+
claims: () => claims,
|
|
18
|
+
compatEdges: () => compatEdges,
|
|
19
|
+
compatVerifyQueue: () => compatVerifyQueue,
|
|
20
|
+
discoveryQueue: () => discoveryQueue,
|
|
21
|
+
entities: () => entities,
|
|
22
|
+
environments: () => environments,
|
|
23
|
+
mcpChangeEvents: () => mcpChangeEvents,
|
|
24
|
+
mcpContracts: () => mcpContracts,
|
|
25
|
+
mcpDeployments: () => mcpDeployments,
|
|
26
|
+
mcpObservations: () => mcpObservations,
|
|
27
|
+
mcpPublicReports: () => mcpPublicReports,
|
|
28
|
+
notificationChannels: () => notificationChannels,
|
|
29
|
+
notificationDeliveries: () => notificationDeliveries,
|
|
30
|
+
notificationItems: () => notificationItems,
|
|
31
|
+
notificationPreferences: () => notificationPreferences,
|
|
32
|
+
observations: () => observations,
|
|
33
|
+
ownerUsageDaily: () => ownerUsageDaily,
|
|
34
|
+
packageVersions: () => packageVersions,
|
|
35
|
+
packages: () => packages,
|
|
36
|
+
policyDecisions: () => policyDecisions,
|
|
37
|
+
recommendationOutcomes: () => recommendationOutcomes,
|
|
38
|
+
repoAlerts: () => repoAlerts,
|
|
39
|
+
repos: () => repos,
|
|
40
|
+
resolvedClosures: () => resolvedClosures,
|
|
41
|
+
seedPackages: () => seedPackages,
|
|
42
|
+
selectionPolicies: () => selectionPolicies,
|
|
43
|
+
selectionPolicyChanges: () => selectionPolicyChanges,
|
|
44
|
+
stackResolutions: () => stackResolutions,
|
|
45
|
+
subscriptions: () => subscriptions,
|
|
46
|
+
surfaceQueue: () => surfaceQueue,
|
|
47
|
+
symbols: () => symbols,
|
|
48
|
+
syncRuns: () => syncRuns,
|
|
49
|
+
upgradeRuns: () => upgradeRuns,
|
|
50
|
+
verificationRuns: () => verificationRuns,
|
|
51
|
+
watchState: () => watchState
|
|
52
|
+
});
|
|
53
|
+
init_esm_shims();
|
|
54
|
+
import { sql } from "drizzle-orm";
|
|
55
|
+
import {
|
|
56
|
+
bigint,
|
|
57
|
+
boolean,
|
|
58
|
+
customType,
|
|
59
|
+
date,
|
|
60
|
+
index,
|
|
61
|
+
integer,
|
|
62
|
+
jsonb,
|
|
63
|
+
pgTable,
|
|
64
|
+
primaryKey,
|
|
65
|
+
real,
|
|
66
|
+
serial,
|
|
67
|
+
text,
|
|
68
|
+
timestamp,
|
|
69
|
+
uniqueIndex,
|
|
70
|
+
vector
|
|
71
|
+
} from "drizzle-orm/pg-core";
|
|
72
|
+
var tsvector = customType({
|
|
73
|
+
dataType() {
|
|
74
|
+
return "tsvector";
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
var ts = (name) => timestamp(name, { withTimezone: true, mode: "date" });
|
|
78
|
+
var packages = pgTable(
|
|
79
|
+
"packages",
|
|
80
|
+
{
|
|
81
|
+
id: serial("id").primaryKey(),
|
|
82
|
+
name: text("name").notNull(),
|
|
83
|
+
ecosystem: text("ecosystem").$type().notNull().default("npm"),
|
|
84
|
+
// Classification + descriptive text
|
|
85
|
+
category: text("category").$type(),
|
|
86
|
+
/** Whether `category` was hand-curated or inferred at ingest (§2A). */
|
|
87
|
+
categorySource: text("category_source").$type(),
|
|
88
|
+
description: text("description"),
|
|
89
|
+
summary: text("summary"),
|
|
90
|
+
repoUrl: text("repo_url"),
|
|
91
|
+
homepage: text("homepage"),
|
|
92
|
+
latestVersion: text("latest_version"),
|
|
93
|
+
license: text("license"),
|
|
94
|
+
// Lifecycle flags
|
|
95
|
+
deprecated: boolean("deprecated").notNull().default(false),
|
|
96
|
+
archived: boolean("archived").notNull().default(false),
|
|
97
|
+
// Age / maintenance signals
|
|
98
|
+
firstPublishedAt: ts("first_published_at"),
|
|
99
|
+
lastReleaseAt: ts("last_release_at"),
|
|
100
|
+
// Adoption signals
|
|
101
|
+
weeklyDownloads: bigint("weekly_downloads", { mode: "number" }),
|
|
102
|
+
downloadGrowth90d: real("download_growth_90d"),
|
|
103
|
+
stars: integer("stars"),
|
|
104
|
+
/**
|
|
105
|
+
* Dependent counts from deps.dev, kept split rather than summed.
|
|
106
|
+
*
|
|
107
|
+
* `direct_dependents` counts packages that name this one in their own
|
|
108
|
+
* manifest; `indirect_dependents` counts those that inherited it through
|
|
109
|
+
* someone else's tree. The ratio is what distinguishes a library a human
|
|
110
|
+
* chose from plumbing npm dragged in — a distinction weekly downloads and
|
|
111
|
+
* GitHub stars both fail to make, because a monorepo's internal utility
|
|
112
|
+
* inherits its parent's stars and every sibling's download volume.
|
|
113
|
+
*/
|
|
114
|
+
directDependents: integer("direct_dependents"),
|
|
115
|
+
indirectDependents: integer("indirect_dependents"),
|
|
116
|
+
openIssues: integer("open_issues"),
|
|
117
|
+
closedIssues: integer("closed_issues"),
|
|
118
|
+
// Reliability / efficiency signals
|
|
119
|
+
scorecard: real("scorecard"),
|
|
120
|
+
bundleMinGzipKb: real("bundle_min_gzip_kb"),
|
|
121
|
+
advisories: jsonb("advisories").$type(),
|
|
122
|
+
// Compatibility metadata (Tier-1): declared peer-deps + engines of the
|
|
123
|
+
// latest version, so a whole-stack peer-range check is one indexed query.
|
|
124
|
+
peerDependencies: jsonb("peer_dependencies").$type(),
|
|
125
|
+
peerDependenciesMeta: jsonb("peer_dependencies_meta").$type(),
|
|
126
|
+
engines: jsonb("engines").$type(),
|
|
127
|
+
/** Where this package runs, classified from its own manifest at ingest.
|
|
128
|
+
* Resolves the `framework` category's frontend/backend ambiguity for the
|
|
129
|
+
* architecture diagram. Null = the manifest did not say clearly enough. */
|
|
130
|
+
runtimeTarget: text("runtime_target").$type(),
|
|
131
|
+
// Computed outputs
|
|
132
|
+
healthScore: integer("health_score"),
|
|
133
|
+
/** Intrinsic-quality axis (§1), adoption-independent. Blends with health at
|
|
134
|
+
* ranking time (composite); never folded into health_score itself. */
|
|
135
|
+
qualityScore: integer("quality_score"),
|
|
136
|
+
confidence: text("confidence").$type(),
|
|
137
|
+
scoreBreakdown: jsonb("score_breakdown").$type(),
|
|
138
|
+
usageGuide: jsonb("usage_guide").$type(),
|
|
139
|
+
embedding: vector("embedding", { dimensions: EMBEDDING_DIM }),
|
|
140
|
+
// Identity of the vector space `embedding` was produced in (e.g.
|
|
141
|
+
// `openai:text-embedding-3-small`, `local`). Vector search filters on the
|
|
142
|
+
// active provider so switching models can't compare incompatible spaces.
|
|
143
|
+
embeddingProvider: text("embedding_provider"),
|
|
144
|
+
// Lexical search vector (§3): name weighted highest (A), then category (B),
|
|
145
|
+
// then summary/description (C). Generated + STORED so it stays in sync with
|
|
146
|
+
// the row automatically; indexed with GIN for fast `@@` matching.
|
|
147
|
+
searchVector: tsvector("search_vector").generatedAlwaysAs(
|
|
148
|
+
sql`setweight(to_tsvector('english', coalesce(name, '')), 'A') || setweight(to_tsvector('english', coalesce(category, '')), 'B') || setweight(to_tsvector('english', coalesce(summary, description, '')), 'C')`
|
|
149
|
+
),
|
|
150
|
+
// Freshness + bookkeeping
|
|
151
|
+
dataAsOf: timestamp("data_as_of", { withTimezone: true, mode: "date" }),
|
|
152
|
+
/** latest_version this package's direct deps were last expanded for by the
|
|
153
|
+
* discovery graph channel (§2B). Discovery re-scans a package only when this
|
|
154
|
+
* differs from latest_version — deps are version-pinned, so an unchanged
|
|
155
|
+
* version has unchanged neighbors. NULL = never scanned. */
|
|
156
|
+
graphScannedVersion: text("graph_scanned_version"),
|
|
157
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
158
|
+
updatedAt: ts("updated_at").notNull().defaultNow(),
|
|
159
|
+
/** The individual account (api_keys.owner_id) whose on-demand query first
|
|
160
|
+
* caused this package to be ingested — nobody had asked for it before them.
|
|
161
|
+
* Null for crawler/_changes-created packages, or ones ingested before
|
|
162
|
+
* dashboard accounts existed. Stamped once via a standalone WHERE ... IS NULL
|
|
163
|
+
* update kept out of upsertPackage, so re-syncs can never clobber it. */
|
|
164
|
+
firstRequestedByOwnerId: text("first_requested_by_owner_id")
|
|
165
|
+
},
|
|
166
|
+
(table) => [
|
|
167
|
+
uniqueIndex("packages_ecosystem_name_idx").on(table.ecosystem, table.name),
|
|
168
|
+
index("packages_category_idx").on(table.category),
|
|
169
|
+
index("packages_health_score_idx").on(table.healthScore),
|
|
170
|
+
// pgvector HNSW index for cosine similarity search (§11).
|
|
171
|
+
index("packages_embedding_idx").using("hnsw", table.embedding.op("vector_cosine_ops")),
|
|
172
|
+
// GIN index for lexical full-text search (§3).
|
|
173
|
+
index("packages_search_vector_idx").using("gin", table.searchVector),
|
|
174
|
+
index("packages_first_requested_by_idx").on(table.firstRequestedByOwnerId)
|
|
175
|
+
]
|
|
176
|
+
);
|
|
177
|
+
var syncRuns = pgTable("sync_runs", {
|
|
178
|
+
id: serial("id").primaryKey(),
|
|
179
|
+
startedAt: ts("started_at").notNull().defaultNow(),
|
|
180
|
+
finishedAt: ts("finished_at"),
|
|
181
|
+
packagesSeen: integer("packages_seen").notNull().default(0),
|
|
182
|
+
packagesUpdated: integer("packages_updated").notNull().default(0),
|
|
183
|
+
errors: jsonb("errors").$type().notNull().default([]),
|
|
184
|
+
status: text("status").$type().notNull().default("running"),
|
|
185
|
+
/** Which deployment started this run, `<environment>/<service>`, or null when
|
|
186
|
+
* the host injects neither (local runs). Diagnostic only: two rows in the
|
|
187
|
+
* same minute with *different* origins is a duplicate scheduler — a second
|
|
188
|
+
* environment or a second service tile running the same cron — which is
|
|
189
|
+
* otherwise invisible from the data and doubles the outbound request rate
|
|
190
|
+
* until npm starts answering 429. */
|
|
191
|
+
origin: text("origin")
|
|
192
|
+
});
|
|
193
|
+
var seedPackages = pgTable("seed_packages", {
|
|
194
|
+
name: text("name").primaryKey(),
|
|
195
|
+
category: text("category").$type(),
|
|
196
|
+
addedAt: ts("added_at").notNull().defaultNow()
|
|
197
|
+
});
|
|
198
|
+
var discoveryQueue = pgTable(
|
|
199
|
+
"discovery_queue",
|
|
200
|
+
{
|
|
201
|
+
id: serial("id").primaryKey(),
|
|
202
|
+
name: text("name").notNull().unique(),
|
|
203
|
+
discoveredVia: text("discovered_via").$type().notNull(),
|
|
204
|
+
/** Lightweight quality-only pre-score (§2B). Null until the gate runs. */
|
|
205
|
+
preScore: integer("pre_score"),
|
|
206
|
+
status: text("status").$type().notNull().default("pending"),
|
|
207
|
+
/** Failed ingests bump this; past DISCOVERY.maxIngestAttempts the candidate
|
|
208
|
+
* is marked `failed` and stops being retried. Without it a package that
|
|
209
|
+
* throws after its summary call — a malformed manifest, a constraint
|
|
210
|
+
* violation — is re-ingested every cycle forever, paying the LLM each time
|
|
211
|
+
* and never reaching the write that would take it off the queue. Same
|
|
212
|
+
* treatment `compat_verify_queue.attempts` already gives a failing set. */
|
|
213
|
+
attempts: integer("attempts").notNull().default(0),
|
|
214
|
+
discoveredAt: ts("discovered_at").notNull().defaultNow()
|
|
215
|
+
},
|
|
216
|
+
(table) => [index("discovery_queue_status_idx").on(table.status)]
|
|
217
|
+
);
|
|
218
|
+
var compatVerifyQueue = pgTable(
|
|
219
|
+
"compat_verify_queue",
|
|
220
|
+
{
|
|
221
|
+
id: serial("id").primaryKey(),
|
|
222
|
+
/** Canonical order-independent key of the package set — dedups pending requests. */
|
|
223
|
+
setKey: text("set_key").notNull().unique(),
|
|
224
|
+
/** The package names to co-install in the sandbox. */
|
|
225
|
+
packages: jsonb("packages").$type().notNull(),
|
|
226
|
+
/** Failed drains bump this; the worker drops a set that keeps failing. */
|
|
227
|
+
attempts: integer("attempts").notNull().default(0),
|
|
228
|
+
requestedAt: ts("requested_at").notNull().defaultNow()
|
|
229
|
+
},
|
|
230
|
+
(table) => [index("compat_verify_queue_requested_idx").on(table.requestedAt)]
|
|
231
|
+
);
|
|
232
|
+
var apiKeys = pgTable(
|
|
233
|
+
"api_keys",
|
|
234
|
+
{
|
|
235
|
+
id: serial("id").primaryKey(),
|
|
236
|
+
/** sha256 hex of the full key — the only form persisted. */
|
|
237
|
+
keyHash: text("key_hash").notNull().unique(),
|
|
238
|
+
/** Identifiable display prefix, e.g. `lurq_live_ab12cd` (safe to show/log). */
|
|
239
|
+
prefix: text("prefix").notNull(),
|
|
240
|
+
/** Free-text label (owner / org / purpose). */
|
|
241
|
+
label: text("label"),
|
|
242
|
+
/** Reserved for self-serve issuance: maps to a Clerk user id. */
|
|
243
|
+
ownerId: text("owner_id"),
|
|
244
|
+
tier: text("tier").notNull().default("free"),
|
|
245
|
+
/**
|
|
246
|
+
* Permissions beyond the default read-and-call access (see KEY_SCOPES).
|
|
247
|
+
* Empty by default: `lurq setup` writes a key into agent config files, and
|
|
248
|
+
* a key an agent holds must never be able to loosen the rules it runs under.
|
|
249
|
+
*/
|
|
250
|
+
scopes: text("scopes").array().notNull().default(sql`'{}'::text[]`),
|
|
251
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
252
|
+
lastUsedAt: ts("last_used_at"),
|
|
253
|
+
revokedAt: ts("revoked_at")
|
|
254
|
+
},
|
|
255
|
+
(table) => [index("api_keys_owner_idx").on(table.ownerId)]
|
|
256
|
+
);
|
|
257
|
+
var packageVersions = pgTable(
|
|
258
|
+
"package_versions",
|
|
259
|
+
{
|
|
260
|
+
packageName: text("package_name").notNull(),
|
|
261
|
+
version: text("version").notNull(),
|
|
262
|
+
publishedAt: ts("published_at"),
|
|
263
|
+
/** Peers/engines declared by this exact version. Lifted from the registry
|
|
264
|
+
* document at ingest (it already carries every version's manifest), so a
|
|
265
|
+
* conflict check against the versions a repo actually RUNS is one indexed
|
|
266
|
+
* query rather than a registry read per dependency. */
|
|
267
|
+
peerDependencies: jsonb("peer_dependencies").$type(),
|
|
268
|
+
engines: jsonb("engines").$type()
|
|
269
|
+
},
|
|
270
|
+
(table) => [
|
|
271
|
+
primaryKey({ columns: [table.packageName, table.version] }),
|
|
272
|
+
index("package_versions_name_published_idx").on(table.packageName, table.publishedAt)
|
|
273
|
+
]
|
|
274
|
+
);
|
|
275
|
+
var watchState = pgTable("watch_state", {
|
|
276
|
+
id: text("id").primaryKey(),
|
|
277
|
+
seq: text("seq").notNull(),
|
|
278
|
+
updatedAt: ts("updated_at")
|
|
279
|
+
});
|
|
280
|
+
var verificationRuns = pgTable(
|
|
281
|
+
"verification_runs",
|
|
282
|
+
{
|
|
283
|
+
id: serial("id").primaryKey(),
|
|
284
|
+
packageName: text("package_name").notNull(),
|
|
285
|
+
version: text("version").notNull(),
|
|
286
|
+
driver: text("driver").notNull(),
|
|
287
|
+
moduleSystem: text("module_system").notNull(),
|
|
288
|
+
installed: boolean("installed").notNull(),
|
|
289
|
+
imported: boolean("imported"),
|
|
290
|
+
ranScripts: boolean("ran_scripts").notNull().default(false),
|
|
291
|
+
durationMs: integer("duration_ms"),
|
|
292
|
+
error: text("error"),
|
|
293
|
+
ranAt: ts("ran_at")
|
|
294
|
+
},
|
|
295
|
+
(table) => [index("verification_runs_pkg_idx").on(table.packageName, table.version)]
|
|
296
|
+
);
|
|
297
|
+
var compatEdges = pgTable(
|
|
298
|
+
"compat_edges",
|
|
299
|
+
{
|
|
300
|
+
id: serial("id").primaryKey(),
|
|
301
|
+
packageA: text("package_a").notNull(),
|
|
302
|
+
versionA: text("version_a").notNull(),
|
|
303
|
+
packageB: text("package_b").notNull(),
|
|
304
|
+
versionB: text("version_b").notNull(),
|
|
305
|
+
status: text("status").$type().notNull(),
|
|
306
|
+
/** Evidence class (§4B). Existing rows are sandbox co-installs, so the column
|
|
307
|
+
* defaults to `verified` to preserve their meaning. */
|
|
308
|
+
provenance: text("provenance").$type().notNull().default("verified"),
|
|
309
|
+
/** Distinct resolved graphs an `observed` edge was witnessed in (confidence).
|
|
310
|
+
* Ignored for verified/conflict. Accumulates on conflict, never overwritten. */
|
|
311
|
+
witnessCount: integer("witness_count").notNull().default(0),
|
|
312
|
+
driver: text("driver").notNull(),
|
|
313
|
+
ranAt: ts("ran_at")
|
|
314
|
+
},
|
|
315
|
+
(table) => [
|
|
316
|
+
uniqueIndex("compat_edges_pair_idx").on(
|
|
317
|
+
table.packageA,
|
|
318
|
+
table.versionA,
|
|
319
|
+
table.packageB,
|
|
320
|
+
table.versionB
|
|
321
|
+
)
|
|
322
|
+
]
|
|
323
|
+
);
|
|
324
|
+
var resolvedClosures = pgTable(
|
|
325
|
+
"resolved_closures",
|
|
326
|
+
{
|
|
327
|
+
id: serial("id").primaryKey(),
|
|
328
|
+
packageName: text("package_name").notNull(),
|
|
329
|
+
version: text("version").notNull(),
|
|
330
|
+
/** Full closure: [{ name, version }, …] — every node in node_modules. */
|
|
331
|
+
nodes: jsonb("nodes").$type().notNull(),
|
|
332
|
+
fetchedAt: ts("fetched_at").notNull().defaultNow()
|
|
333
|
+
},
|
|
334
|
+
(table) => [uniqueIndex("resolved_closures_pkg_idx").on(table.packageName, table.version)]
|
|
335
|
+
);
|
|
336
|
+
var apiSurfaces = pgTable(
|
|
337
|
+
"api_surfaces",
|
|
338
|
+
{
|
|
339
|
+
id: serial("id").primaryKey(),
|
|
340
|
+
packageName: text("package_name").notNull(),
|
|
341
|
+
version: text("version").notNull(),
|
|
342
|
+
/** Normalized export list: [{ name, kind, signature }, …]. */
|
|
343
|
+
surface: jsonb("surface").$type().notNull(),
|
|
344
|
+
extractedAt: ts("extracted_at").notNull().defaultNow()
|
|
345
|
+
},
|
|
346
|
+
(table) => [uniqueIndex("api_surfaces_pkg_idx").on(table.packageName, table.version)]
|
|
347
|
+
);
|
|
348
|
+
var recommendationOutcomes = pgTable(
|
|
349
|
+
"recommendation_outcomes",
|
|
350
|
+
{
|
|
351
|
+
id: serial("id").primaryKey(),
|
|
352
|
+
/** The individual user this outcome belongs to (api_keys.owner_id). Null for
|
|
353
|
+
* anonymous/operator-issued keys. This is what turns the flywheel from a
|
|
354
|
+
* global blob into a per-user asset — "what did *this* person succeed
|
|
355
|
+
* with." Server-injected from the authenticated key, never caller-supplied. */
|
|
356
|
+
ownerId: text("owner_id"),
|
|
357
|
+
packageName: text("package_name").notNull(),
|
|
358
|
+
accepted: boolean("accepted").notNull(),
|
|
359
|
+
buildSignal: text("build_signal").$type(),
|
|
360
|
+
/** The original need text the recommendation was for — ties outcome back to
|
|
361
|
+
* the ask. Optional, length-capped at the trust boundary; never source code. */
|
|
362
|
+
need: text("need"),
|
|
363
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
364
|
+
},
|
|
365
|
+
(table) => [
|
|
366
|
+
index("recommendation_outcomes_pkg_idx").on(table.packageName),
|
|
367
|
+
index("recommendation_outcomes_owner_idx").on(table.ownerId)
|
|
368
|
+
]
|
|
369
|
+
);
|
|
370
|
+
var askSpendDaily = pgTable(
|
|
371
|
+
"ask_spend_daily",
|
|
372
|
+
{
|
|
373
|
+
ownerId: text("owner_id").notNull(),
|
|
374
|
+
/** UTC day, 'YYYY-MM-DD'. */
|
|
375
|
+
date: date("date").notNull(),
|
|
376
|
+
usdMicros: bigint("usd_micros", { mode: "number" }).notNull().default(0)
|
|
377
|
+
},
|
|
378
|
+
(table) => [primaryKey({ columns: [table.ownerId, table.date] })]
|
|
379
|
+
);
|
|
380
|
+
var ownerUsageDaily = pgTable(
|
|
381
|
+
"owner_usage_daily",
|
|
382
|
+
{
|
|
383
|
+
ownerId: text("owner_id").notNull(),
|
|
384
|
+
/** UTC day, 'YYYY-MM-DD'. */
|
|
385
|
+
date: date("date").notNull(),
|
|
386
|
+
/** recommend | evaluate | compare | compat | verify | usage | diagram | plan | report_outcome */
|
|
387
|
+
tool: text("tool").notNull(),
|
|
388
|
+
count: integer("count").notNull().default(0)
|
|
389
|
+
},
|
|
390
|
+
(table) => [
|
|
391
|
+
primaryKey({ columns: [table.ownerId, table.date, table.tool] }),
|
|
392
|
+
index("owner_usage_daily_owner_date_idx").on(table.ownerId, table.date)
|
|
393
|
+
]
|
|
394
|
+
);
|
|
395
|
+
var repos = pgTable(
|
|
396
|
+
"repos",
|
|
397
|
+
{
|
|
398
|
+
id: serial("id").primaryKey(),
|
|
399
|
+
/** Clerk user id — same identity as api_keys.owner_id. */
|
|
400
|
+
ownerId: text("owner_id").notNull(),
|
|
401
|
+
/** GitHub App installation this repo is reachable through. */
|
|
402
|
+
installationId: bigint("installation_id", { mode: "number" }).notNull(),
|
|
403
|
+
/** `owner/name`. */
|
|
404
|
+
fullName: text("full_name").notNull(),
|
|
405
|
+
defaultBranch: text("default_branch"),
|
|
406
|
+
isPrivate: boolean("is_private").notNull().default(false),
|
|
407
|
+
policy: jsonb("policy").$type().notNull(),
|
|
408
|
+
manifests: jsonb("manifests").$type(),
|
|
409
|
+
/** Install command detected from the lockfile at scan time, so the generated
|
|
410
|
+
* workflow uses the repo's actual package manager instead of assuming npm. */
|
|
411
|
+
installCommand: text("install_command"),
|
|
412
|
+
drift: jsonb("drift").$type(),
|
|
413
|
+
lastScanAt: ts("last_scan_at"),
|
|
414
|
+
/** Last scan failure, surfaced in the dashboard. Null once a scan succeeds —
|
|
415
|
+
* a stale error next to fresh drift numbers reads as a current outage. */
|
|
416
|
+
lastScanError: text("last_scan_error"),
|
|
417
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
418
|
+
},
|
|
419
|
+
(table) => [
|
|
420
|
+
uniqueIndex("repos_owner_full_name_idx").on(table.ownerId, table.fullName),
|
|
421
|
+
index("repos_installation_idx").on(table.installationId)
|
|
422
|
+
]
|
|
423
|
+
);
|
|
424
|
+
var upgradeRuns = pgTable(
|
|
425
|
+
"upgrade_runs",
|
|
426
|
+
{
|
|
427
|
+
id: serial("id").primaryKey(),
|
|
428
|
+
/** Resolved server-side from the authenticated API key. Never caller-supplied. */
|
|
429
|
+
ownerId: text("owner_id").notNull(),
|
|
430
|
+
/** Links to `repos` when the repo is also connected. Null when the workflow
|
|
431
|
+
* runs somewhere lurq has no GitHub App installation — the CLI works
|
|
432
|
+
* standalone, and losing those runs would bias every impact figure. */
|
|
433
|
+
repoId: integer("repo_id"),
|
|
434
|
+
/** `owner/name` from GITHUB_REPOSITORY. */
|
|
435
|
+
repoFullName: text("repo_full_name").notNull(),
|
|
436
|
+
packageName: text("package_name").notNull(),
|
|
437
|
+
fromVersion: text("from_version").notNull(),
|
|
438
|
+
toVersion: text("to_version").notNull(),
|
|
439
|
+
severity: text("severity").$type().notNull(),
|
|
440
|
+
status: text("status").$type().notNull(),
|
|
441
|
+
/** Referenced symbols the upgrade removes or re-shapes. */
|
|
442
|
+
symbolsAffected: jsonb("symbols_affected").$type().notNull().default([]),
|
|
443
|
+
/** How many references those symbols have in the repo. */
|
|
444
|
+
callSites: integer("call_sites").notNull().default(0),
|
|
445
|
+
/** Distinct files containing them. Opt-in per repo policy. */
|
|
446
|
+
callSiteFiles: jsonb("call_site_files").$type(),
|
|
447
|
+
filesChanged: integer("files_changed"),
|
|
448
|
+
/** Null when the repo has no test script — distinct from `false`, which
|
|
449
|
+
* means the suite ran and failed. */
|
|
450
|
+
testsPassed: boolean("tests_passed"),
|
|
451
|
+
prUrl: text("pr_url"),
|
|
452
|
+
/**
|
|
453
|
+
* The GitHub Actions run, so a dashboard row links back to real logs.
|
|
454
|
+
* NOT NULL with an empty-string default rather than nullable: it is part of
|
|
455
|
+
* the dedup key below, and Postgres treats NULLs as distinct — a nullable
|
|
456
|
+
* column there would silently let every re-post insert a duplicate. Empty
|
|
457
|
+
* means "posted outside Actions" (a local CLI run), which then dedups to one
|
|
458
|
+
* row per package+target and updates in place.
|
|
459
|
+
*/
|
|
460
|
+
runUrl: text("run_url").notNull().default(""),
|
|
461
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
462
|
+
},
|
|
463
|
+
(table) => [
|
|
464
|
+
index("upgrade_runs_owner_created_idx").on(table.ownerId, table.createdAt),
|
|
465
|
+
index("upgrade_runs_repo_idx").on(table.repoId),
|
|
466
|
+
// One row per package per Actions run: a re-post of the same run must update
|
|
467
|
+
// rather than duplicate, or a retried job would double every impact figure.
|
|
468
|
+
uniqueIndex("upgrade_runs_dedup_idx").on(
|
|
469
|
+
table.ownerId,
|
|
470
|
+
table.repoFullName,
|
|
471
|
+
table.packageName,
|
|
472
|
+
table.toVersion,
|
|
473
|
+
table.runUrl
|
|
474
|
+
)
|
|
475
|
+
]
|
|
476
|
+
);
|
|
477
|
+
var repoAlerts = pgTable(
|
|
478
|
+
"repo_alerts",
|
|
479
|
+
{
|
|
480
|
+
id: serial("id").primaryKey(),
|
|
481
|
+
/** Clerk user id, copied from the repo — alerts are read owner-scoped. */
|
|
482
|
+
ownerId: text("owner_id").notNull(),
|
|
483
|
+
repoId: integer("repo_id").notNull(),
|
|
484
|
+
/** Denormalized so the feed renders without a join, as in `upgrade_runs`. */
|
|
485
|
+
repoFullName: text("repo_full_name").notNull(),
|
|
486
|
+
packageName: text("package_name").notNull(),
|
|
487
|
+
/** The range this repo declared when the release landed. */
|
|
488
|
+
range: text("range").notNull(),
|
|
489
|
+
/** What that range resolved to at the last scan. Null when the index had no
|
|
490
|
+
* version timeline for the package yet — never guessed. */
|
|
491
|
+
fromVersion: text("from_version"),
|
|
492
|
+
/** The release that triggered this. */
|
|
493
|
+
toVersion: text("to_version").notNull(),
|
|
494
|
+
/**
|
|
495
|
+
* True when the declared range already admits `toVersion` — i.e. the next
|
|
496
|
+
* clean install silently takes the new major. That is the urgent case and the
|
|
497
|
+
* one no drift number expresses: the repo is not "behind", it is about to
|
|
498
|
+
* move on its own.
|
|
499
|
+
*/
|
|
500
|
+
inRange: boolean("in_range").notNull(),
|
|
501
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
502
|
+
},
|
|
503
|
+
(table) => [
|
|
504
|
+
index("repo_alerts_owner_created_idx").on(table.ownerId, table.createdAt),
|
|
505
|
+
// The notification sender scans recent alerts across every owner.
|
|
506
|
+
index("repo_alerts_created_idx").on(table.createdAt),
|
|
507
|
+
// One alert per repo per release. A re-sync of the same version — and the
|
|
508
|
+
// watcher re-syncs on every publish, including non-latest backports — must
|
|
509
|
+
// not re-notify.
|
|
510
|
+
uniqueIndex("repo_alerts_dedup_idx").on(table.repoId, table.packageName, table.toVersion)
|
|
511
|
+
]
|
|
512
|
+
);
|
|
513
|
+
var surfaceQueue = pgTable(
|
|
514
|
+
"surface_queue",
|
|
515
|
+
{
|
|
516
|
+
id: serial("id").primaryKey(),
|
|
517
|
+
packageName: text("package_name").notNull(),
|
|
518
|
+
/** Null means "whatever latest resolves to at extraction time". */
|
|
519
|
+
version: text("version"),
|
|
520
|
+
/**
|
|
521
|
+
* Which extractor services this row.
|
|
522
|
+
*
|
|
523
|
+
* One queue, two drains: `package_surface` rows are fetched as tarballs and
|
|
524
|
+
* read statically, `mcp_server` rows are installed and probed over stdio.
|
|
525
|
+
* The discriminator is not optional bookkeeping — without it the npm drain
|
|
526
|
+
* picks up MCP rows and tries to extract exports from a server it should
|
|
527
|
+
* have handshaked with, and the failure is silent because "no exports
|
|
528
|
+
* found" is a legitimate answer for a package that has none.
|
|
529
|
+
*/
|
|
530
|
+
kind: text("kind").$type().notNull().default("package_surface"),
|
|
531
|
+
/** Dedup key: `kind:name@version`. */
|
|
532
|
+
specKey: text("spec_key").notNull().unique(),
|
|
533
|
+
/** Failed drains bump this; the worker drops a spec that keeps failing. */
|
|
534
|
+
attempts: integer("attempts").notNull().default(0),
|
|
535
|
+
requestedAt: ts("requested_at").notNull().defaultNow()
|
|
536
|
+
},
|
|
537
|
+
(table) => [index("surface_queue_requested_idx").on(table.kind, table.requestedAt)]
|
|
538
|
+
);
|
|
539
|
+
var entities = pgTable(
|
|
540
|
+
"entities",
|
|
541
|
+
{
|
|
542
|
+
id: serial("id").primaryKey(),
|
|
543
|
+
kind: text("kind").$type().notNull(),
|
|
544
|
+
/** Registry or authority: npm, api.stripe.com, … */
|
|
545
|
+
namespace: text("namespace").notNull(),
|
|
546
|
+
name: text("name").notNull(),
|
|
547
|
+
/** Null for unversioned kinds. */
|
|
548
|
+
version: text("version"),
|
|
549
|
+
/** `kind:namespace:name:version` */
|
|
550
|
+
canonicalKey: text("canonical_key").notNull(),
|
|
551
|
+
/**
|
|
552
|
+
* 0 = the public graph; a real id = a private deployment's tenant. The spec
|
|
553
|
+
* models public as NULL, but Postgres UNIQUE treats NULLs as distinct, so
|
|
554
|
+
* (key, NULL) would insert unlimited duplicates and the dedup silently fails.
|
|
555
|
+
* A non-null sentinel is the cheap fix that works on every PG version.
|
|
556
|
+
*/
|
|
557
|
+
tenantId: bigint("tenant_id", { mode: "number" }).notNull().default(0),
|
|
558
|
+
/** Tarball digest. THE extraction cache key: unchanged digest, no re-extraction.
|
|
559
|
+
* This is what keeps cost sublinear as the index grows (§5, §6.5). */
|
|
560
|
+
artifactHash: text("artifact_hash"),
|
|
561
|
+
/** Dependent count. Drives sampling AND refresh priority — and note priority
|
|
562
|
+
* is NOT popularity: the study found drift concentrates at LOW in-degree
|
|
563
|
+
* (18.7% vs 8.3%), which is exactly where models have the weakest priors. */
|
|
564
|
+
inDegree: integer("in_degree"),
|
|
565
|
+
firstSeen: ts("first_seen").notNull().defaultNow()
|
|
566
|
+
},
|
|
567
|
+
(table) => [
|
|
568
|
+
uniqueIndex("entities_canonical_idx").on(table.canonicalKey, table.tenantId),
|
|
569
|
+
index("entities_kind_idx").on(table.kind, table.namespace, table.name),
|
|
570
|
+
index("entities_artifact_idx").on(table.artifactHash)
|
|
571
|
+
]
|
|
572
|
+
);
|
|
573
|
+
var UNBOUNDED_ARITY = -1;
|
|
574
|
+
var symbols = pgTable(
|
|
575
|
+
"symbols",
|
|
576
|
+
{
|
|
577
|
+
id: serial("id").primaryKey(),
|
|
578
|
+
entityId: integer("entity_id").notNull().references(() => entities.id),
|
|
579
|
+
/** 'default', 'foo', 'foo.bar' */
|
|
580
|
+
path: text("path").notNull(),
|
|
581
|
+
/** function | class | object | primitive | type_only */
|
|
582
|
+
kind: text("kind").$type().notNull(),
|
|
583
|
+
/** `fn.length` equivalent; null when not statically determinable. */
|
|
584
|
+
arity: integer("arity"),
|
|
585
|
+
/** 'local' | 'external:<pkg>' */
|
|
586
|
+
origin: text("origin").notNull().default("local"),
|
|
587
|
+
deprecated: boolean("deprecated").notNull().default(false),
|
|
588
|
+
tier: text("tier").$type().notNull(),
|
|
589
|
+
/** Full declaration text; tier C only (§6.2). */
|
|
590
|
+
signature: text("signature"),
|
|
591
|
+
sourceFile: text("source_file"),
|
|
592
|
+
sourceLine: integer("source_line"),
|
|
593
|
+
/** Character offset of the declaration. Two exports sharing file and offset
|
|
594
|
+
* are one value under two names, which is how a diff read from storage finds
|
|
595
|
+
* a proven rename. Null on rows extracted before it was recorded. */
|
|
596
|
+
sourceOffset: integer("source_offset"),
|
|
597
|
+
/** Most arguments the function reads: null when not measured, UNBOUNDED_ARITY
|
|
598
|
+
* for a rest parameter or `arguments`. See SurfaceSymbol.maxArity. */
|
|
599
|
+
maxArity: integer("max_arity")
|
|
600
|
+
},
|
|
601
|
+
// Keyed by TIER as well as path: a package version has one surface per tier and
|
|
602
|
+
// they are not interchangeable (§6.4.3). Without the tier in the key, storing a
|
|
603
|
+
// tier-C surface would silently overwrite the tier-A one that answers runtime
|
|
604
|
+
// existence — replacing the authoritative answer with a type-level guess.
|
|
605
|
+
(table) => [
|
|
606
|
+
uniqueIndex("symbols_entity_path_tier_idx").on(table.entityId, table.path, table.tier)
|
|
607
|
+
]
|
|
608
|
+
);
|
|
609
|
+
var environments = pgTable("environments", {
|
|
610
|
+
id: serial("id").primaryKey(),
|
|
611
|
+
os: text("os").notNull(),
|
|
612
|
+
arch: text("arch").notNull(),
|
|
613
|
+
runtime: text("runtime").notNull(),
|
|
614
|
+
runtimeVer: text("runtime_ver").notNull(),
|
|
615
|
+
resolver: text("resolver"),
|
|
616
|
+
/** Hash of the above; the dedup key. */
|
|
617
|
+
fingerprint: text("fingerprint").notNull().unique()
|
|
618
|
+
});
|
|
619
|
+
var claims = pgTable(
|
|
620
|
+
"claims",
|
|
621
|
+
{
|
|
622
|
+
id: serial("id").primaryKey(),
|
|
623
|
+
subjectId: integer("subject_id").notNull().references(() => entities.id),
|
|
624
|
+
/** Null for unary claims ("does this install at all"). */
|
|
625
|
+
objectId: integer("object_id").references(() => entities.id),
|
|
626
|
+
relation: text("relation").notNull(),
|
|
627
|
+
/** NULL for DECLARED claims: a shipped-JS surface reads the same on every
|
|
628
|
+
* machine, so there is no environment to fingerprint. Executed claims
|
|
629
|
+
* (co-install, conflict, behaviour) always carry one (§5). */
|
|
630
|
+
environmentId: integer("environment_id").references(() => environments.id),
|
|
631
|
+
tenantId: bigint("tenant_id", { mode: "number" }).notNull().default(0)
|
|
632
|
+
},
|
|
633
|
+
(table) => [
|
|
634
|
+
uniqueIndex("claims_tuple_idx").on(
|
|
635
|
+
table.subjectId,
|
|
636
|
+
table.objectId,
|
|
637
|
+
table.relation,
|
|
638
|
+
table.environmentId,
|
|
639
|
+
table.tenantId
|
|
640
|
+
)
|
|
641
|
+
]
|
|
642
|
+
);
|
|
643
|
+
var observations = pgTable(
|
|
644
|
+
"observations",
|
|
645
|
+
{
|
|
646
|
+
id: serial("id").primaryKey(),
|
|
647
|
+
claimId: integer("claim_id").notNull().references(() => claims.id),
|
|
648
|
+
verdict: text("verdict").$type().notNull(),
|
|
649
|
+
/** What KIND of evidence backs the verdict (§4.1) — orthogonal to the verdict
|
|
650
|
+
* itself. A declared surface fact must never read as behavioural proof. */
|
|
651
|
+
class: text("class").$type().notNull().default("executed"),
|
|
652
|
+
/** Which extraction tier produced it; null for executed claims. */
|
|
653
|
+
tier: text("tier").$type(),
|
|
654
|
+
/** Evidence that makes the verdict auditable. Null only for `unknown`. */
|
|
655
|
+
evidence: text("evidence"),
|
|
656
|
+
oracleId: text("oracle_id").notNull(),
|
|
657
|
+
oracleVer: text("oracle_ver").notNull(),
|
|
658
|
+
costMillis: integer("cost_millis"),
|
|
659
|
+
observedAt: ts("observed_at").notNull().defaultNow()
|
|
660
|
+
},
|
|
661
|
+
(table) => [index("observations_claim_idx").on(table.claimId, table.observedAt)]
|
|
662
|
+
);
|
|
663
|
+
var selectionPolicies = pgTable("selection_policies", {
|
|
664
|
+
ownerId: text("owner_id").primaryKey(),
|
|
665
|
+
policy: jsonb("policy").$type().notNull(),
|
|
666
|
+
updatedAt: ts("updated_at").notNull().defaultNow()
|
|
667
|
+
});
|
|
668
|
+
var selectionPolicyChanges = pgTable(
|
|
669
|
+
"selection_policy_changes",
|
|
670
|
+
{
|
|
671
|
+
id: serial("id").primaryKey(),
|
|
672
|
+
ownerId: text("owner_id").notNull(),
|
|
673
|
+
/** `dashboard`, or the display prefix of the API key that pushed it. */
|
|
674
|
+
actor: text("actor").notNull(),
|
|
675
|
+
before: jsonb("before").$type().notNull(),
|
|
676
|
+
after: jsonb("after").$type().notNull(),
|
|
677
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
678
|
+
},
|
|
679
|
+
(table) => [index("selection_policy_changes_owner_idx").on(table.ownerId, table.createdAt)]
|
|
680
|
+
);
|
|
681
|
+
var policyDecisions = pgTable(
|
|
682
|
+
"policy_decisions",
|
|
683
|
+
{
|
|
684
|
+
id: serial("id").primaryKey(),
|
|
685
|
+
ownerId: text("owner_id").notNull(),
|
|
686
|
+
packageName: text("package_name").notNull(),
|
|
687
|
+
rule: text("rule").$type().notNull(),
|
|
688
|
+
/** `blocked` under enforce, `warned` under warn. */
|
|
689
|
+
action: text("action").$type().notNull(),
|
|
690
|
+
/** The tool the agent called: recommend | evaluate. */
|
|
691
|
+
tool: text("tool").notNull(),
|
|
692
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
693
|
+
},
|
|
694
|
+
(table) => [index("policy_decisions_owner_idx").on(table.ownerId, table.createdAt)]
|
|
695
|
+
);
|
|
696
|
+
var subscriptions = pgTable(
|
|
697
|
+
"subscriptions",
|
|
698
|
+
{
|
|
699
|
+
/** Clerk user id. One subscription per account. */
|
|
700
|
+
ownerId: text("owner_id").primaryKey(),
|
|
701
|
+
/** Stable across subscriptions: a customer who cancels and returns reuses it. */
|
|
702
|
+
stripeCustomerId: text("stripe_customer_id").notNull().unique(),
|
|
703
|
+
/** Null between creating a customer and completing a first checkout. */
|
|
704
|
+
stripeSubscriptionId: text("stripe_subscription_id").unique(),
|
|
705
|
+
tier: text("tier").$type().notNull().default("free"),
|
|
706
|
+
/** Raw Stripe subscription status. `null` = never subscribed. */
|
|
707
|
+
status: text("status"),
|
|
708
|
+
/** When the paid period lapses. Display only; `status` is what gates access. */
|
|
709
|
+
currentPeriodEnd: ts("current_period_end"),
|
|
710
|
+
/** Set when the user cancels but has paid through the period. */
|
|
711
|
+
cancelAtPeriodEnd: boolean("cancel_at_period_end").notNull().default(false),
|
|
712
|
+
/**
|
|
713
|
+
* Seats bought, from the Stripe subscription quantity. Only per-seat plans
|
|
714
|
+
* read it, and `billedSeats` floors it at the plan's minimum, so a flat plan
|
|
715
|
+
* or a pre-seat row carrying the default 1 resolves correctly either way.
|
|
716
|
+
*/
|
|
717
|
+
seats: integer("seats").notNull().default(1),
|
|
718
|
+
/** The subscription carries the metered overage item, so calls past the pool bill. */
|
|
719
|
+
overageEnabled: boolean("overage_enabled").notNull().default(false),
|
|
720
|
+
/** Calendar month ('YYYY-MM') that `overageReported` counts. */
|
|
721
|
+
overageMonth: text("overage_month"),
|
|
722
|
+
/** Overage calls already sent to Stripe for `overageMonth`. */
|
|
723
|
+
overageReported: integer("overage_reported").notNull().default(0),
|
|
724
|
+
/** The plan item's Stripe interval ('month' | 'year'). Null for manual grants. */
|
|
725
|
+
billingInterval: text("billing_interval"),
|
|
726
|
+
/**
|
|
727
|
+
* Stripe delivers out of order and retries, so a late duplicate of an older
|
|
728
|
+
* event must not overwrite newer state. The webhook drops any event whose
|
|
729
|
+
* timestamp is older than the one that produced the current row.
|
|
730
|
+
*/
|
|
731
|
+
lastEventAt: ts("last_event_at"),
|
|
732
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
733
|
+
updatedAt: ts("updated_at").notNull().defaultNow()
|
|
734
|
+
},
|
|
735
|
+
(table) => [index("subscriptions_customer_idx").on(table.stripeCustomerId)]
|
|
736
|
+
);
|
|
737
|
+
var stackResolutions = pgTable(
|
|
738
|
+
"stack_resolutions",
|
|
739
|
+
{
|
|
740
|
+
id: serial("id").primaryKey(),
|
|
741
|
+
/** Canonical `name@version|name@version|…`, sorted. The cache key. */
|
|
742
|
+
setKey: text("set_key").notNull().unique(),
|
|
743
|
+
/** The exact members this verdict is about. */
|
|
744
|
+
packages: jsonb("packages").$type().notNull(),
|
|
745
|
+
/** Names only, for publish-driven invalidation. */
|
|
746
|
+
names: text("names").array().notNull(),
|
|
747
|
+
/** True when npm produced a lockfile for the set. */
|
|
748
|
+
resolved: boolean("resolved").notNull(),
|
|
749
|
+
/** 'ERESOLVE' for a proven conflict; null when it resolved. */
|
|
750
|
+
reason: text("reason"),
|
|
751
|
+
/** npm's own error text on a conflict — it names the packages and ranges. */
|
|
752
|
+
detail: text("detail"),
|
|
753
|
+
resolvedAt: ts("resolved_at").notNull().defaultNow()
|
|
754
|
+
},
|
|
755
|
+
(table) => [
|
|
756
|
+
index("stack_resolutions_names_idx").using("gin", table.names),
|
|
757
|
+
index("stack_resolutions_resolved_at_idx").on(table.resolvedAt)
|
|
758
|
+
]
|
|
759
|
+
);
|
|
760
|
+
var mcpContracts = pgTable(
|
|
761
|
+
"mcp_contracts",
|
|
762
|
+
{
|
|
763
|
+
contentHash: text("content_hash").primaryKey(),
|
|
764
|
+
/** Schema-only hash; equal means calls validate identically. */
|
|
765
|
+
contractHash: text("contract_hash").notNull(),
|
|
766
|
+
tools: jsonb("tools").$type().notNull(),
|
|
767
|
+
prompts: jsonb("prompts").$type().notNull(),
|
|
768
|
+
resourceTemplates: jsonb("resource_templates").$type().notNull(),
|
|
769
|
+
instructions: text("instructions"),
|
|
770
|
+
toolCount: integer("tool_count").notNull(),
|
|
771
|
+
bytes: integer("bytes").notNull(),
|
|
772
|
+
/** Computed server-side at insert, never taken from the client. */
|
|
773
|
+
analysis: jsonb("analysis").$type().notNull(),
|
|
774
|
+
analyzerVersion: text("analyzer_version").notNull(),
|
|
775
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
776
|
+
},
|
|
777
|
+
(table) => [index("mcp_contracts_contract_idx").on(table.contractHash)]
|
|
778
|
+
);
|
|
779
|
+
var mcpDeployments = pgTable(
|
|
780
|
+
"mcp_deployments",
|
|
781
|
+
{
|
|
782
|
+
id: serial("id").primaryKey(),
|
|
783
|
+
ownerId: text("owner_id").notNull(),
|
|
784
|
+
serverKey: text("server_key").notNull(),
|
|
785
|
+
configFingerprint: text("config_fingerprint").notNull(),
|
|
786
|
+
/** The name the user gave it, as last seen. Display only. */
|
|
787
|
+
alias: text("alias").notNull(),
|
|
788
|
+
registry: text("registry").$type().notNull(),
|
|
789
|
+
packageName: text("package_name"),
|
|
790
|
+
transport: text("transport").notNull(),
|
|
791
|
+
/** Self-reported by the server in its handshake. */
|
|
792
|
+
serverName: text("server_name"),
|
|
793
|
+
serverVersion: text("server_version"),
|
|
794
|
+
lastStatus: text("last_status").$type().notNull(),
|
|
795
|
+
lastError: text("last_error"),
|
|
796
|
+
/** The last contract actually read. Kept when a later scan fails. */
|
|
797
|
+
lastContentHash: text("last_content_hash"),
|
|
798
|
+
worstSeverity: text("worst_severity").$type(),
|
|
799
|
+
firstSeenAt: ts("first_seen_at").notNull().defaultNow(),
|
|
800
|
+
lastScannedAt: ts("last_scanned_at").notNull().defaultNow(),
|
|
801
|
+
lastChangedAt: ts("last_changed_at")
|
|
802
|
+
},
|
|
803
|
+
(table) => [
|
|
804
|
+
uniqueIndex("mcp_deployments_identity_idx").on(table.ownerId, table.serverKey, table.configFingerprint),
|
|
805
|
+
index("mcp_deployments_owner_idx").on(table.ownerId, table.lastScannedAt)
|
|
806
|
+
]
|
|
807
|
+
);
|
|
808
|
+
var mcpObservations = pgTable(
|
|
809
|
+
"mcp_observations",
|
|
810
|
+
{
|
|
811
|
+
id: serial("id").primaryKey(),
|
|
812
|
+
deploymentId: integer("deployment_id").notNull().references(() => mcpDeployments.id),
|
|
813
|
+
ownerId: text("owner_id").notNull(),
|
|
814
|
+
status: text("status").$type().notNull(),
|
|
815
|
+
contentHash: text("content_hash"),
|
|
816
|
+
serverVersion: text("server_version"),
|
|
817
|
+
error: text("error"),
|
|
818
|
+
/** `cli` or `ci`: who ran the scan that opened this interval. */
|
|
819
|
+
source: text("source").notNull(),
|
|
820
|
+
scanCount: integer("scan_count").notNull().default(1),
|
|
821
|
+
firstSeenAt: ts("first_seen_at").notNull().defaultNow(),
|
|
822
|
+
lastSeenAt: ts("last_seen_at").notNull().defaultNow()
|
|
823
|
+
},
|
|
824
|
+
(table) => [index("mcp_observations_deployment_idx").on(table.deploymentId, table.firstSeenAt)]
|
|
825
|
+
);
|
|
826
|
+
var mcpChangeEvents = pgTable(
|
|
827
|
+
"mcp_change_events",
|
|
828
|
+
{
|
|
829
|
+
id: serial("id").primaryKey(),
|
|
830
|
+
deploymentId: integer("deployment_id").notNull().references(() => mcpDeployments.id),
|
|
831
|
+
ownerId: text("owner_id").notNull(),
|
|
832
|
+
fromHash: text("from_hash").notNull(),
|
|
833
|
+
toHash: text("to_hash").notNull(),
|
|
834
|
+
severity: text("severity").$type().notNull(),
|
|
835
|
+
summary: text("summary").notNull(),
|
|
836
|
+
diff: jsonb("diff").$type().notNull(),
|
|
837
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
838
|
+
acknowledgedAt: ts("acknowledged_at")
|
|
839
|
+
},
|
|
840
|
+
(table) => [
|
|
841
|
+
uniqueIndex("mcp_change_events_pair_idx").on(table.deploymentId, table.fromHash, table.toHash),
|
|
842
|
+
index("mcp_change_events_owner_idx").on(table.ownerId, table.createdAt),
|
|
843
|
+
index("mcp_change_events_created_idx").on(table.createdAt)
|
|
844
|
+
]
|
|
845
|
+
);
|
|
846
|
+
var mcpPublicReports = pgTable(
|
|
847
|
+
"mcp_public_reports",
|
|
848
|
+
{
|
|
849
|
+
registry: text("registry").notNull(),
|
|
850
|
+
packageName: text("package_name").notNull(),
|
|
851
|
+
version: text("version").notNull(),
|
|
852
|
+
contentHash: text("content_hash").notNull(),
|
|
853
|
+
ownerId: text("owner_id").notNull(),
|
|
854
|
+
reportedAt: ts("reported_at").notNull().defaultNow()
|
|
855
|
+
},
|
|
856
|
+
(table) => [
|
|
857
|
+
primaryKey({ columns: [table.registry, table.packageName, table.version, table.contentHash, table.ownerId] }),
|
|
858
|
+
index("mcp_public_reports_version_idx").on(table.registry, table.packageName, table.version)
|
|
859
|
+
]
|
|
860
|
+
);
|
|
861
|
+
var notificationPreferences = pgTable("notification_preferences", {
|
|
862
|
+
ownerId: text("owner_id").primaryKey(),
|
|
863
|
+
urgentEmail: boolean("urgent_email").notNull().default(true),
|
|
864
|
+
weeklyDigest: boolean("weekly_digest").notNull().default(false),
|
|
865
|
+
unsubscribeToken: text("unsubscribe_token").notNull().unique(),
|
|
866
|
+
lastDigestAt: ts("last_digest_at"),
|
|
867
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
868
|
+
updatedAt: ts("updated_at").notNull().defaultNow()
|
|
869
|
+
});
|
|
870
|
+
var notificationDeliveries = pgTable(
|
|
871
|
+
"notification_deliveries",
|
|
872
|
+
{
|
|
873
|
+
id: serial("id").primaryKey(),
|
|
874
|
+
ownerId: text("owner_id").notNull(),
|
|
875
|
+
kind: text("kind").$type().notNull(),
|
|
876
|
+
/** Set on a channel delivery: the Slack/Discord/Teams/webhook it went to. */
|
|
877
|
+
channelId: integer("channel_id"),
|
|
878
|
+
status: text("status").$type().notNull(),
|
|
879
|
+
idempotencyKey: text("idempotency_key").notNull().unique(),
|
|
880
|
+
attempts: integer("attempts").notNull().default(0),
|
|
881
|
+
/** Why it failed or was skipped. Our own words, never a recipient address. */
|
|
882
|
+
error: text("error"),
|
|
883
|
+
providerId: text("provider_id"),
|
|
884
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
885
|
+
sentAt: ts("sent_at")
|
|
886
|
+
},
|
|
887
|
+
(table) => [
|
|
888
|
+
index("notification_deliveries_owner_idx").on(table.ownerId, table.kind, table.createdAt),
|
|
889
|
+
index("notification_deliveries_status_idx").on(table.status, table.createdAt)
|
|
890
|
+
]
|
|
891
|
+
);
|
|
892
|
+
var notificationItems = pgTable(
|
|
893
|
+
"notification_items",
|
|
894
|
+
{
|
|
895
|
+
itemKey: text("item_key").primaryKey(),
|
|
896
|
+
ownerId: text("owner_id").notNull(),
|
|
897
|
+
deliveryId: integer("delivery_id").notNull().references(() => notificationDeliveries.id),
|
|
898
|
+
createdAt: ts("created_at").notNull().defaultNow()
|
|
899
|
+
},
|
|
900
|
+
(table) => [index("notification_items_delivery_idx").on(table.deliveryId)]
|
|
901
|
+
);
|
|
902
|
+
var notificationChannels = pgTable(
|
|
903
|
+
"notification_channels",
|
|
904
|
+
{
|
|
905
|
+
id: serial("id").primaryKey(),
|
|
906
|
+
ownerId: text("owner_id").notNull(),
|
|
907
|
+
kind: text("kind").$type().notNull(),
|
|
908
|
+
label: text("label"),
|
|
909
|
+
urlCiphertext: text("url_ciphertext").notNull(),
|
|
910
|
+
/** Enough of the URL to recognise it: host and the last four characters. */
|
|
911
|
+
urlHint: text("url_hint").notNull(),
|
|
912
|
+
/** Webhook kind only: the HMAC secret receivers verify with. Encrypted. */
|
|
913
|
+
signingSecretCiphertext: text("signing_secret_ciphertext"),
|
|
914
|
+
minSeverity: text("min_severity").$type().notNull().default("high"),
|
|
915
|
+
enabled: boolean("enabled").notNull().default(true),
|
|
916
|
+
consecutiveFailures: integer("consecutive_failures").notNull().default(0),
|
|
917
|
+
/** Why lurq switched it off, in words for the owner. Cleared on re-enable. */
|
|
918
|
+
disabledReason: text("disabled_reason"),
|
|
919
|
+
lastDeliveredAt: ts("last_delivered_at"),
|
|
920
|
+
lastError: text("last_error"),
|
|
921
|
+
createdAt: ts("created_at").notNull().defaultNow(),
|
|
922
|
+
updatedAt: ts("updated_at").notNull().defaultNow(),
|
|
923
|
+
deletedAt: ts("deleted_at")
|
|
924
|
+
},
|
|
925
|
+
(table) => [index("notification_channels_owner_idx").on(table.ownerId)]
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
export {
|
|
929
|
+
packages,
|
|
930
|
+
syncRuns,
|
|
931
|
+
seedPackages,
|
|
932
|
+
discoveryQueue,
|
|
933
|
+
compatVerifyQueue,
|
|
934
|
+
apiKeys,
|
|
935
|
+
packageVersions,
|
|
936
|
+
watchState,
|
|
937
|
+
verificationRuns,
|
|
938
|
+
compatEdges,
|
|
939
|
+
apiSurfaces,
|
|
940
|
+
recommendationOutcomes,
|
|
941
|
+
askSpendDaily,
|
|
942
|
+
ownerUsageDaily,
|
|
943
|
+
repos,
|
|
944
|
+
upgradeRuns,
|
|
945
|
+
repoAlerts,
|
|
946
|
+
surfaceQueue,
|
|
947
|
+
entities,
|
|
948
|
+
UNBOUNDED_ARITY,
|
|
949
|
+
symbols,
|
|
950
|
+
claims,
|
|
951
|
+
observations,
|
|
952
|
+
selectionPolicies,
|
|
953
|
+
selectionPolicyChanges,
|
|
954
|
+
policyDecisions,
|
|
955
|
+
subscriptions,
|
|
956
|
+
stackResolutions,
|
|
957
|
+
mcpContracts,
|
|
958
|
+
mcpDeployments,
|
|
959
|
+
mcpObservations,
|
|
960
|
+
mcpChangeEvents,
|
|
961
|
+
mcpPublicReports,
|
|
962
|
+
notificationPreferences,
|
|
963
|
+
notificationChannels,
|
|
964
|
+
schema_exports
|
|
965
|
+
};
|