@minion-stack/db 0.7.0 → 0.9.0
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/dist/pg/schema/auth.d.ts +1591 -0
- package/dist/pg/schema/auth.d.ts.map +1 -0
- package/dist/pg/schema/auth.js +160 -0
- package/dist/pg/schema/auth.js.map +1 -0
- package/dist/pg/schema/builder.d.ts +1 -1
- package/dist/pg/schema/builder.d.ts.map +1 -1
- package/dist/pg/schema/builder.js +3 -1
- package/dist/pg/schema/builder.js.map +1 -1
- package/dist/pg/schema/channels.d.ts +336 -0
- package/dist/pg/schema/channels.d.ts.map +1 -1
- package/dist/pg/schema/channels.js +45 -1
- package/dist/pg/schema/channels.js.map +1 -1
- package/dist/pg/schema/gateway.d.ts +17 -0
- package/dist/pg/schema/gateway.d.ts.map +1 -1
- package/dist/pg/schema/gateway.js +4 -0
- package/dist/pg/schema/gateway.js.map +1 -1
- package/dist/pg/schema/index.d.ts +2 -1
- package/dist/pg/schema/index.d.ts.map +1 -1
- package/dist/pg/schema/index.js +5 -1
- package/dist/pg/schema/index.js.map +1 -1
- package/dist/pg/schema/missions.d.ts +2 -2
- package/dist/pg/schema/personal-agents.d.ts +1 -1
- package/dist/pg/schema/server-ops.d.ts +1 -1
- package/dist/pg/schema/sessions.d.ts +1 -1
- package/dist/schema/bugs.d.ts.map +1 -1
- package/dist/schema/bugs.js +7 -1
- package/dist/schema/bugs.js.map +1 -1
- package/dist/schema/connection-events.js +5 -4
- package/dist/schema/connection-events.js.map +1 -1
- package/dist/schema/index.d.ts +0 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +0 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/personal-agents.d.ts +1 -1
- package/dist/schema/reliability-events.d.ts +2 -2
- package/dist/schema/reliability-events.d.ts.map +1 -1
- package/dist/schema/reliability-events.js +6 -6
- package/dist/schema/reliability-events.js.map +1 -1
- package/dist/schema/skill-execution-stats.d.ts +1 -1
- package/dist/schema/unified-events.d.ts.map +1 -1
- package/dist/schema/unified-events.js +3 -0
- package/dist/schema/unified-events.js.map +1 -1
- package/package.json +12 -11
- package/src/pg/schema/auth.ts +198 -0
- package/src/pg/schema/builder.ts +3 -1
- package/src/pg/schema/channels.ts +62 -1
- package/src/pg/schema/gateway.ts +4 -0
- package/src/pg/schema/index.ts +22 -1
- package/src/schema/bugs.ts +7 -1
- package/src/schema/connection-events.ts +4 -4
- package/src/schema/index.ts +0 -1
- package/src/schema/reliability-events.ts +5 -6
- package/src/schema/unified-events.ts +3 -0
- package/src/schema/flows.ts +0 -14
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Better Auth schema tables — Postgres variant.
|
|
3
|
+
*
|
|
4
|
+
* Faithful 1:1 port of `../../schema/auth/index.ts` (sqlite) for the Turso→Supabase
|
|
5
|
+
* Better Auth cutover (Stage 5 / Track B). Export NAMES must match Better Auth's
|
|
6
|
+
* model names (`user`, `session`, …) because the auth factory passes this module
|
|
7
|
+
* straight to the drizzle adapter. Ids stay `text` (Better Auth generates string
|
|
8
|
+
* ids — keeping them text preserves existing ids across the store migration, so
|
|
9
|
+
* `profiles.legacy_user_id` keeps mapping). sqlite `integer{mode:timestamp}` →
|
|
10
|
+
* `timestamptz`; `integer{mode:boolean}` → `boolean`.
|
|
11
|
+
*
|
|
12
|
+
* Provider: pg, plugins: emailAndPassword, google OAuth, jwt, organization, oidc.
|
|
13
|
+
*/
|
|
14
|
+
import { pgTable, text, timestamp, boolean, index } from 'drizzle-orm/pg-core';
|
|
15
|
+
|
|
16
|
+
// ── Core: user ──────────────────────────────────────────────────────────────
|
|
17
|
+
export const user = pgTable('user', {
|
|
18
|
+
id: text('id').primaryKey(),
|
|
19
|
+
name: text('name').notNull(),
|
|
20
|
+
email: text('email').notNull().unique(),
|
|
21
|
+
emailVerified: boolean('email_verified').notNull(),
|
|
22
|
+
image: text('image'),
|
|
23
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
24
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
25
|
+
role: text('role', { enum: ['user', 'admin'] })
|
|
26
|
+
.notNull()
|
|
27
|
+
.default('user'),
|
|
28
|
+
personalAgentId: text('personal_agent_id'),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// ── Core: session ────────────────────────────────────────────────────────────
|
|
32
|
+
export const session = pgTable(
|
|
33
|
+
'session',
|
|
34
|
+
{
|
|
35
|
+
id: text('id').primaryKey(),
|
|
36
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
37
|
+
token: text('token').notNull().unique(),
|
|
38
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
39
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
40
|
+
ipAddress: text('ip_address'),
|
|
41
|
+
userAgent: text('user_agent'),
|
|
42
|
+
userId: text('user_id')
|
|
43
|
+
.notNull()
|
|
44
|
+
.references(() => user.id, { onDelete: 'cascade' }),
|
|
45
|
+
// Added by organization plugin
|
|
46
|
+
activeOrganizationId: text('active_organization_id'),
|
|
47
|
+
},
|
|
48
|
+
(t) => [index('idx_session_user').on(t.userId)],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// ── Core: account ────────────────────────────────────────────────────────────
|
|
52
|
+
export const account = pgTable(
|
|
53
|
+
'account',
|
|
54
|
+
{
|
|
55
|
+
id: text('id').primaryKey(),
|
|
56
|
+
accountId: text('account_id').notNull(),
|
|
57
|
+
providerId: text('provider_id').notNull(),
|
|
58
|
+
userId: text('user_id')
|
|
59
|
+
.notNull()
|
|
60
|
+
.references(() => user.id, { onDelete: 'cascade' }),
|
|
61
|
+
accessToken: text('access_token'),
|
|
62
|
+
refreshToken: text('refresh_token'),
|
|
63
|
+
idToken: text('id_token'),
|
|
64
|
+
accessTokenExpiresAt: timestamp('access_token_expires_at', { withTimezone: true }),
|
|
65
|
+
refreshTokenExpiresAt: timestamp('refresh_token_expires_at', { withTimezone: true }),
|
|
66
|
+
scope: text('scope'),
|
|
67
|
+
password: text('password'),
|
|
68
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
69
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
70
|
+
},
|
|
71
|
+
(t) => [index('idx_account_user').on(t.userId)],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// ── Core: verification ────────────────────────────────────────────────────────
|
|
75
|
+
export const verification = pgTable(
|
|
76
|
+
'verification',
|
|
77
|
+
{
|
|
78
|
+
id: text('id').primaryKey(),
|
|
79
|
+
identifier: text('identifier').notNull(),
|
|
80
|
+
value: text('value').notNull(),
|
|
81
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
82
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
83
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
84
|
+
},
|
|
85
|
+
(t) => [index('idx_verification_identifier').on(t.identifier)],
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// ── JWT plugin: jwks ─────────────────────────────────────────────────────────
|
|
89
|
+
export const jwks = pgTable('jwks', {
|
|
90
|
+
id: text('id').primaryKey(),
|
|
91
|
+
publicKey: text('public_key').notNull(),
|
|
92
|
+
privateKey: text('private_key').notNull(),
|
|
93
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// ── Organization plugin: organization ────────────────────────────────────────
|
|
97
|
+
export const organization = pgTable('organization', {
|
|
98
|
+
id: text('id').primaryKey(),
|
|
99
|
+
name: text('name').notNull(),
|
|
100
|
+
slug: text('slug').unique(),
|
|
101
|
+
logo: text('logo'),
|
|
102
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
103
|
+
metadata: text('metadata'),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// ── Organization plugin: member ───────────────────────────────────────────────
|
|
107
|
+
export const member = pgTable(
|
|
108
|
+
'member',
|
|
109
|
+
{
|
|
110
|
+
id: text('id').primaryKey(),
|
|
111
|
+
organizationId: text('organization_id')
|
|
112
|
+
.notNull()
|
|
113
|
+
.references(() => organization.id, { onDelete: 'cascade' }),
|
|
114
|
+
userId: text('user_id')
|
|
115
|
+
.notNull()
|
|
116
|
+
.references(() => user.id, { onDelete: 'cascade' }),
|
|
117
|
+
role: text('role').notNull(),
|
|
118
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
119
|
+
},
|
|
120
|
+
(t) => [index('idx_member_org').on(t.organizationId), index('idx_member_user').on(t.userId)],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// ── Organization plugin: invitation ──────────────────────────────────────────
|
|
124
|
+
export const invitation = pgTable(
|
|
125
|
+
'invitation',
|
|
126
|
+
{
|
|
127
|
+
id: text('id').primaryKey(),
|
|
128
|
+
organizationId: text('organization_id')
|
|
129
|
+
.notNull()
|
|
130
|
+
.references(() => organization.id, { onDelete: 'cascade' }),
|
|
131
|
+
email: text('email').notNull(),
|
|
132
|
+
role: text('role'),
|
|
133
|
+
status: text('status').notNull(),
|
|
134
|
+
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
|
135
|
+
inviterId: text('inviter_id')
|
|
136
|
+
.notNull()
|
|
137
|
+
.references(() => user.id, { onDelete: 'cascade' }),
|
|
138
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
139
|
+
},
|
|
140
|
+
(t) => [index('idx_invitation_org').on(t.organizationId)],
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// ── OIDC provider plugin: oauthApplication ──────────────────────────────────
|
|
144
|
+
export const oauthApplication = pgTable('oauth_application', {
|
|
145
|
+
id: text('id').primaryKey(),
|
|
146
|
+
name: text('name').notNull(),
|
|
147
|
+
icon: text('icon'),
|
|
148
|
+
metadata: text('metadata'),
|
|
149
|
+
clientId: text('client_id').notNull().unique(),
|
|
150
|
+
clientSecret: text('client_secret'),
|
|
151
|
+
redirectUrls: text('redirect_urls').notNull(),
|
|
152
|
+
type: text('type').notNull(),
|
|
153
|
+
disabled: boolean('disabled').default(false),
|
|
154
|
+
userId: text('user_id').references(() => user.id, { onDelete: 'cascade' }),
|
|
155
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
156
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// ── OIDC provider plugin: oauthAccessToken ──────────────────────────────────
|
|
160
|
+
export const oauthAccessToken = pgTable(
|
|
161
|
+
'oauth_access_token',
|
|
162
|
+
{
|
|
163
|
+
id: text('id').primaryKey(),
|
|
164
|
+
accessToken: text('access_token').notNull().unique(),
|
|
165
|
+
refreshToken: text('refresh_token').notNull().unique(),
|
|
166
|
+
accessTokenExpiresAt: timestamp('access_token_expires_at', { withTimezone: true }).notNull(),
|
|
167
|
+
refreshTokenExpiresAt: timestamp('refresh_token_expires_at', { withTimezone: true }).notNull(),
|
|
168
|
+
clientId: text('client_id').notNull(),
|
|
169
|
+
userId: text('user_id').references(() => user.id, { onDelete: 'cascade' }),
|
|
170
|
+
scopes: text('scopes').notNull(),
|
|
171
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
172
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
173
|
+
},
|
|
174
|
+
(t) => [
|
|
175
|
+
index('idx_oauth_access_token_client').on(t.clientId),
|
|
176
|
+
index('idx_oauth_access_token_user').on(t.userId),
|
|
177
|
+
],
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
// ── OIDC provider plugin: oauthConsent ──────────────────────────────────────
|
|
181
|
+
export const oauthConsent = pgTable(
|
|
182
|
+
'oauth_consent',
|
|
183
|
+
{
|
|
184
|
+
id: text('id').primaryKey(),
|
|
185
|
+
clientId: text('client_id').notNull(),
|
|
186
|
+
userId: text('user_id')
|
|
187
|
+
.notNull()
|
|
188
|
+
.references(() => user.id, { onDelete: 'cascade' }),
|
|
189
|
+
scopes: text('scopes').notNull(),
|
|
190
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull(),
|
|
191
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),
|
|
192
|
+
consentGiven: boolean('consent_given').notNull(),
|
|
193
|
+
},
|
|
194
|
+
(t) => [
|
|
195
|
+
index('idx_oauth_consent_client').on(t.clientId),
|
|
196
|
+
index('idx_oauth_consent_user').on(t.userId),
|
|
197
|
+
],
|
|
198
|
+
);
|
package/src/pg/schema/builder.ts
CHANGED
|
@@ -123,7 +123,9 @@ export const builtAgents = pgTable(
|
|
|
123
123
|
.notNull()
|
|
124
124
|
.default('draft'),
|
|
125
125
|
gatewayId: uuid('gateway_id').references(() => gateway.id, { onDelete: 'cascade' }),
|
|
126
|
-
|
|
126
|
+
// Org-owned (Phase 4: no global drafts). Matches the NOT NULL constraint in
|
|
127
|
+
// 20260606224238_built_agents_tenant_not_null.sql.
|
|
128
|
+
tenantId: uuid('tenant_id').notNull(),
|
|
127
129
|
createdBy: text('created_by'),
|
|
128
130
|
publishedAt: timestamp('published_at', { withTimezone: true }),
|
|
129
131
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
pgTable,
|
|
3
|
+
uuid,
|
|
4
|
+
text,
|
|
5
|
+
timestamp,
|
|
6
|
+
boolean,
|
|
7
|
+
integer,
|
|
8
|
+
index,
|
|
9
|
+
uniqueIndex,
|
|
10
|
+
} from 'drizzle-orm/pg-core';
|
|
11
|
+
import { sql } from 'drizzle-orm';
|
|
2
12
|
import { gateway } from './gateway.js';
|
|
3
13
|
import { profiles } from './profiles.js';
|
|
4
14
|
|
|
@@ -19,19 +29,70 @@ export const channels = pgTable(
|
|
|
19
29
|
.notNull()
|
|
20
30
|
.references(() => gateway.id, { onDelete: 'cascade' }),
|
|
21
31
|
type: text('type', { enum: ['discord', 'whatsapp', 'telegram'] }).notNull(),
|
|
32
|
+
// Gateway account key (phone/handle, e.g. '+51906090526') — the join to the
|
|
33
|
+
// gateway's per-account config. Nullable for legacy rows; the natural upsert
|
|
34
|
+
// key for a linked account is (tenant_id, gateway_id, type, account_id).
|
|
35
|
+
accountId: text('account_id'),
|
|
22
36
|
label: text('label').notNull(),
|
|
23
37
|
credentials: text('credentials').notNull().default(''),
|
|
24
38
|
credentialsIv: text('credentials_iv').notNull().default(''),
|
|
25
39
|
credentialsMeta: text('credentials_meta').notNull().default('{}'),
|
|
40
|
+
// Observed coarse status (kept for existing consumers / hub badge).
|
|
26
41
|
status: text('status', { enum: ['active', 'inactive', 'pairing'] })
|
|
27
42
|
.notNull()
|
|
28
43
|
.default('inactive'),
|
|
44
|
+
|
|
45
|
+
// --- Intent (user-configured rules; one concern per column). See
|
|
46
|
+
// specs/2026-06-19-linked-channels-config-restructure.md ---
|
|
47
|
+
// Should the gateway hold a live session (runtime enable/disable).
|
|
48
|
+
enabled: boolean('enabled').notNull().default(true),
|
|
49
|
+
// Reply behavior. 'none' = noAgent (never reply, even owner/self); 'bound' =
|
|
50
|
+
// reply only where a channel_bindings row matches. No 'auto' on purpose.
|
|
51
|
+
replies: text('replies', { enum: ['none', 'bound'] }).notNull().default('none'),
|
|
52
|
+
// DM sender access gate (consulted only when replies='bound'). [] = nobody,
|
|
53
|
+
// ['*'] = anyone. Replaces the old dm_policy enum (derivable from this).
|
|
54
|
+
allowFrom: text('allow_from').array().notNull().default(sql`'{}'`),
|
|
55
|
+
groupAllowFrom: text('group_allow_from').array().notNull().default(sql`'{}'`),
|
|
56
|
+
// Groups reply only when @-mentioned.
|
|
57
|
+
requireMention: boolean('require_mention').notNull().default(true),
|
|
58
|
+
|
|
59
|
+
// --- Observed (gateway-reported, read-only) ---
|
|
60
|
+
reconnectCount: integer('reconnect_count').notNull().default(0),
|
|
61
|
+
lastSeenAt: timestamp('last_seen_at', { withTimezone: true }),
|
|
62
|
+
lastError: text('last_error'),
|
|
63
|
+
|
|
29
64
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
30
65
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
31
66
|
},
|
|
32
67
|
(t) => [
|
|
33
68
|
index('idx_channels_tenant_gateway').on(t.tenantId, t.gatewayId),
|
|
34
69
|
uniqueIndex('channels_uniq_type_label').on(t.tenantId, t.gatewayId, t.type, t.label),
|
|
70
|
+
// Upsert key for gateway-account sync (account_id is the gateway account key).
|
|
71
|
+
uniqueIndex('channels_uniq_type_account').on(t.tenantId, t.gatewayId, t.type, t.accountId),
|
|
72
|
+
],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Agent routing for a channel. A channel with NO rows here resolves to no agent
|
|
77
|
+
* (receive-only). agent_id NULL on a row is an explicit noAgent binding. Match
|
|
78
|
+
* specificity orders resolution: dm_peer > group > catchall (no priority column).
|
|
79
|
+
*/
|
|
80
|
+
export const channelBindings = pgTable(
|
|
81
|
+
'channel_bindings',
|
|
82
|
+
{
|
|
83
|
+
id: uuid('id').primaryKey().defaultRandom(),
|
|
84
|
+
tenantId: uuid('tenant_id').notNull(),
|
|
85
|
+
channelId: text('channel_id')
|
|
86
|
+
.notNull()
|
|
87
|
+
.references(() => channels.id, { onDelete: 'cascade' }),
|
|
88
|
+
matchKind: text('match_kind', { enum: ['catchall', 'dm_peer', 'group'] }).notNull(),
|
|
89
|
+
matchPeer: text('match_peer'),
|
|
90
|
+
agentId: text('agent_id'), // null = explicit noAgent
|
|
91
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
92
|
+
},
|
|
93
|
+
(t) => [
|
|
94
|
+
index('idx_channel_bindings_channel').on(t.channelId),
|
|
95
|
+
uniqueIndex('channel_bindings_uniq').on(t.channelId, t.matchKind, t.matchPeer),
|
|
35
96
|
],
|
|
36
97
|
);
|
|
37
98
|
|
package/src/pg/schema/gateway.ts
CHANGED
|
@@ -9,6 +9,10 @@ import { profiles } from './profiles.js';
|
|
|
9
9
|
export const gateway = pgTable('gateway', {
|
|
10
10
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
11
11
|
legacyServerId: text('legacy_server_id'),
|
|
12
|
+
// Owning org (soft ref to organizations.id). Used by server-token ingest auth
|
|
13
|
+
// (resolveServerTokenAuth) to resolve the tenant — the Turso `servers.tenant_id`
|
|
14
|
+
// equivalent. Nullable during the Turso→Supabase gateway-token cutover bake.
|
|
15
|
+
orgId: uuid('org_id'),
|
|
12
16
|
name: text('name').notNull(),
|
|
13
17
|
url: text('url').notNull(),
|
|
14
18
|
tokenCiphertext: text('token_ciphertext').notNull().default(''),
|
package/src/pg/schema/index.ts
CHANGED
|
@@ -34,7 +34,12 @@ export {
|
|
|
34
34
|
agentBuiltSkills,
|
|
35
35
|
builtTools,
|
|
36
36
|
} from './builder.js';
|
|
37
|
-
export {
|
|
37
|
+
export {
|
|
38
|
+
channels,
|
|
39
|
+
channelAssignments,
|
|
40
|
+
channelIdentities,
|
|
41
|
+
channelBindings,
|
|
42
|
+
} from './channels.js';
|
|
38
43
|
export { sessions, sessionTasks } from './sessions.js';
|
|
39
44
|
export { missions, tasks } from './missions.js';
|
|
40
45
|
export { chatMessages } from './chat-messages.js';
|
|
@@ -50,3 +55,19 @@ export { workspaceMembership } from './workspace-membership.js';
|
|
|
50
55
|
export type { WorkspaceMembership, NewWorkspaceMembership } from './workspace-membership.js';
|
|
51
56
|
// Org-scoped agent memory corpus (pgvector) — RAG retrieval + hub visualization.
|
|
52
57
|
export { agentMemories } from './agent-memories.js';
|
|
58
|
+
// Better Auth tables (Postgres) — Turso→Supabase Better Auth cutover (Track B).
|
|
59
|
+
// Export names mirror Better Auth's model names so the auth factory can pass
|
|
60
|
+
// this module straight to the drizzle adapter (provider: 'pg').
|
|
61
|
+
export {
|
|
62
|
+
user,
|
|
63
|
+
session,
|
|
64
|
+
account,
|
|
65
|
+
verification,
|
|
66
|
+
jwks,
|
|
67
|
+
organization,
|
|
68
|
+
member,
|
|
69
|
+
invitation,
|
|
70
|
+
oauthApplication,
|
|
71
|
+
oauthAccessToken,
|
|
72
|
+
oauthConsent,
|
|
73
|
+
} from './auth.js';
|
package/src/schema/bugs.ts
CHANGED
|
@@ -26,5 +26,11 @@ export const bugs = sqliteTable(
|
|
|
26
26
|
createdAt: integer('created_at').notNull(),
|
|
27
27
|
updatedAt: integer('updated_at').notNull(),
|
|
28
28
|
},
|
|
29
|
-
(t) => [
|
|
29
|
+
(t) => [
|
|
30
|
+
index('idx_bugs_tenant').on(t.tenantId),
|
|
31
|
+
index('idx_bugs_server').on(t.serverId),
|
|
32
|
+
// Covers the tenant-scoped bug list (bug.service.ts listBugs): tenant_id,
|
|
33
|
+
// ordered by created_at desc.
|
|
34
|
+
index('idx_bugs_tenant_created').on(t.tenantId, t.createdAt),
|
|
35
|
+
],
|
|
30
36
|
);
|
|
@@ -19,8 +19,8 @@ export const connectionEvents = sqliteTable(
|
|
|
19
19
|
reason: text('reason'),
|
|
20
20
|
occurredAt: integer('occurred_at').notNull(),
|
|
21
21
|
},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
],
|
|
22
|
+
// No service reads or writes this table. The server index was pure write-tax for
|
|
23
|
+
// a query pattern that never runs — dropped. The tenant index is retained so the
|
|
24
|
+
// organization onDelete: cascade stays cheap.
|
|
25
|
+
(t) => [index('idx_conn_events_tenant').on(t.tenantId)],
|
|
26
26
|
);
|
package/src/schema/index.ts
CHANGED
|
@@ -33,7 +33,6 @@ export { marketplaceAgents } from './marketplace-agents.js';
|
|
|
33
33
|
export { marketplaceInstalls } from './marketplace-installs.js';
|
|
34
34
|
export { workshopSaves } from './workshop-saves.js';
|
|
35
35
|
export { deviceIdentities } from './device-identities.js';
|
|
36
|
-
export { flows } from './flows.js';
|
|
37
36
|
export { userServers } from './user-servers.js';
|
|
38
37
|
export { userAgents } from './user-agents.js';
|
|
39
38
|
export { channels } from './channels.js';
|
|
@@ -23,10 +23,9 @@ export const reliabilityEvents = sqliteTable(
|
|
|
23
23
|
occurredAt: integer('occurred_at').notNull(),
|
|
24
24
|
createdAt: integer('created_at').notNull(),
|
|
25
25
|
},
|
|
26
|
-
(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
],
|
|
26
|
+
// No service reads or writes this table (the reliability dashboard streams live
|
|
27
|
+
// data over WS from the gateway, not from the DB). The three server_* composite
|
|
28
|
+
// indexes were pure write-tax for query patterns that never run — dropped. The
|
|
29
|
+
// tenant index is retained so the organization onDelete: cascade stays cheap.
|
|
30
|
+
(t) => [index('idx_rel_events_tenant').on(t.tenantId)],
|
|
32
31
|
);
|
|
@@ -27,6 +27,9 @@ export const unifiedEvents = sqliteTable(
|
|
|
27
27
|
index('idx_unified_events_tenant').on(t.tenantId),
|
|
28
28
|
index('idx_unified_events_server_cat_time').on(t.serverId, t.category, t.occurredAt),
|
|
29
29
|
index('idx_unified_events_server_time').on(t.serverId, t.occurredAt),
|
|
30
|
+
// Covers the severity-filtered event list (events.service.ts listEvents):
|
|
31
|
+
// server_id + severity, ordered by occurred_at desc.
|
|
32
|
+
index('idx_unified_events_server_sev_time').on(t.serverId, t.severity, t.occurredAt),
|
|
30
33
|
index('idx_unified_events_correlation').on(t.correlationId),
|
|
31
34
|
uniqueIndex('idx_unified_events_dedup').on(t.tenantId, t.serverId, t.localEventId),
|
|
32
35
|
],
|
package/src/schema/flows.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
|
|
2
|
-
|
|
3
|
-
export const flows = sqliteTable('flows', {
|
|
4
|
-
id: text('id').primaryKey(),
|
|
5
|
-
name: text('name').notNull(),
|
|
6
|
-
nodes: text('nodes').notNull().default('[]'), // JSON string of FlowNode[]
|
|
7
|
-
edges: text('edges').notNull().default('[]'), // JSON string of FlowEdge[]
|
|
8
|
-
userId: text('user_id'), // owner — null for pre-migration rows (treated as shared)
|
|
9
|
-
tenantId: text('tenant_id'), // tenant scope — null for pre-migration rows
|
|
10
|
-
createdAt: integer('created_at').notNull(),
|
|
11
|
-
updatedAt: integer('updated_at').notNull(),
|
|
12
|
-
active: integer('active', { mode: 'boolean' }).notNull().default(false),
|
|
13
|
-
config: text('config').notNull().default('{}'),
|
|
14
|
-
});
|