@happyvertical/smrt-cli 0.51.15 → 0.51.17

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.
Files changed (27) hide show
  1. package/AGENTS.md +1 -0
  2. package/dist/ApiKey-BZmbOTnL-D3HXUD48.js +157 -0
  3. package/dist/ApiKeyCollection-Bfb_nw81-iisJ_4LE.js +2 -0
  4. package/dist/AuditLogCollection-B1YonCAP-BSaKxHp3.js +2 -0
  5. package/dist/NostrIdentity-n70E0vck-jJyb_ar3.js +4189 -0
  6. package/dist/NostrIdentityCollection-Ca74dkaL-M4K0-Bkw.js +2 -0
  7. package/dist/OidcIdentity-CChQnYNH-Cnye-7CI.js +117 -0
  8. package/dist/OidcIdentityCollection-D3L0WYbM-BOje5aiS.js +2 -0
  9. package/dist/ProfileAssetCollection-V8u4wqSL-DDnGXiJl.js +2 -0
  10. package/dist/ProfileCollection-BvhD2cfL-P9hC9GcP.js +1753 -0
  11. package/dist/ProfileMetadataCollection-DxX_BJKV-ZbSkGI11.js +2 -0
  12. package/dist/ProfileMetafieldCollection-CMKhVi2I-BrAonTjE.js +2 -0
  13. package/dist/ProfileRelationshipCollection-DUVgaIqf-0E090hxE.js +2 -0
  14. package/dist/ProfileRelationshipTermCollection-DtA9OM23-EGZ4UVpV.js +2 -0
  15. package/dist/ProfileRelationshipType-BRiRka6t-W3qx1WVa.js +101 -0
  16. package/dist/ProfileRelationshipTypeCollection-BdXwd7Kf-mvIAf7RC.js +2 -0
  17. package/dist/{commands-BhDS-TVS.js → commands-C3O2NOMh.js} +96 -22
  18. package/dist/{config-DfBo4hHU.js → config-hqNo4lzH.js} +1 -13
  19. package/dist/dist-A0mO7r3F.js +142 -0
  20. package/dist/dist-DNf1dFwn.js +1487 -0
  21. package/dist/dist-DrGZRXfi.js +3712 -0
  22. package/dist/index.js +14 -14
  23. package/dist/{json-validator-CjX8fHx9.js → json-validator-oEN7eUI3.js} +1 -1
  24. package/dist/oidcProvisioningPrimitives-CjOkg3Zd-BtqRL7sX.js +161 -0
  25. package/dist/resolveIdentity-73HQnTlT-C4CQBrRn.js +2 -0
  26. package/dist/rolldown-runtime-8H4AJuhK.js +14 -0
  27. package/package.json +8 -7
@@ -0,0 +1,3712 @@
1
+ import { a as verifyAuthEvent, i as generateNostrKeypair, n as __exportAll$1, r as encryptPrivkey, t as NostrIdentity } from "./NostrIdentity-n70E0vck-jJyb_ar3.js";
2
+ import { t as ApiKey } from "./ApiKey-BZmbOTnL-D3HXUD48.js";
3
+ import { n as tenantId, s as withSystemContext, t as TenantScoped } from "./dist-A0mO7r3F.js";
4
+ import { t as OidcIdentity } from "./OidcIdentity-CChQnYNH-Cnye-7CI.js";
5
+ import { a as removeOwnedAssetFromCollection, i as getOwnedAssetsFromCollection, t as addOwnedAssetFromCollection } from "./dist-DNf1dFwn.js";
6
+ import { a as coordinateOidcProvisioning, o as isOidcProvisioningRaceConflict, s as normalizeIdentityEmail } from "./ProfileCollection-BvhD2cfL-P9hC9GcP.js";
7
+ import { t as ProfileRelationshipType } from "./ProfileRelationshipType-BRiRka6t-W3qx1WVa.js";
8
+ import { n as insertOidcProvisioningIdentity, t as createOidcProvisioningPerson } from "./oidcProvisioningPrimitives-CjOkg3Zd-BtqRL7sX.js";
9
+ import { ObjectRegistry, SmrtCollection, SmrtJunction, SmrtObject, bumpChangeFeed, crossPackageRef, field, foreignKey, oneToMany, registerRetentionTask, resolveDatabase, smrt } from "@happyvertical/smrt-core";
10
+ import { createLogger } from "@happyvertical/logger";
11
+ import { createHash, randomBytes } from "node:crypto";
12
+ import "@happyvertical/smrt-config";
13
+ import "@happyvertical/smrt-core/migrations";
14
+ import { AsyncLocalStorage } from "node:async_hooks";
15
+ import { AccessRequestStatus, MembershipStatus, OverrideEffect, SessionStatus, TenantPermissionEffect, TenantStatus, UserStatus } from "@happyvertical/smrt-types";
16
+ //#region ../profiles/dist/chunks/ApiKeyCollection-Bfb_nw81.js
17
+ var ApiKeyCollection_exports = /* @__PURE__ */ __exportAll$1({ ApiKeyCollection: () => ApiKeyCollection });
18
+ var ApiKeyCollection = class extends SmrtCollection {
19
+ static _itemClass = ApiKey;
20
+ /**
21
+ * Find all keys for a profile
22
+ */
23
+ async findByProfile(profileId) {
24
+ return await this.list({ where: { profileId } });
25
+ }
26
+ /**
27
+ * Find active (non-revoked, non-expired) keys for a profile
28
+ */
29
+ async findActiveByProfile(profileId) {
30
+ return (await this.findByProfile(profileId)).filter((key) => key.isValid());
31
+ }
32
+ /**
33
+ * Find key by hash
34
+ */
35
+ async findByHash(keyHash) {
36
+ return await this.findOne({ where: { keyHash } });
37
+ }
38
+ /**
39
+ * Verify an API key string and return the record if valid
40
+ */
41
+ async verify(key) {
42
+ const keyHash = ApiKey.hashKey(key);
43
+ const apiKey = await this.findByHash(keyHash);
44
+ if (!apiKey) return null;
45
+ if (!apiKey.isValid()) return null;
46
+ await apiKey.recordUsage();
47
+ if (!apiKey.isValid()) return null;
48
+ return apiKey;
49
+ }
50
+ /**
51
+ * Generate a new key for a profile
52
+ */
53
+ async generateForProfile(profile, options) {
54
+ return await ApiKey.generate(profile, {
55
+ ...options,
56
+ db: this.options.db
57
+ });
58
+ }
59
+ /**
60
+ * Revoke all keys for a profile
61
+ */
62
+ async revokeAllForProfile(profileId) {
63
+ const keys = await this.findActiveByProfile(profileId);
64
+ for (const key of keys) await key.revoke();
65
+ return keys.length;
66
+ }
67
+ /**
68
+ * Revoke a specific key by prefix
69
+ */
70
+ async revokeByPrefix(keyPrefix) {
71
+ const key = await this.findOne({ where: { keyPrefix } });
72
+ if (key?.isValid()) {
73
+ await key.revoke();
74
+ return true;
75
+ }
76
+ return false;
77
+ }
78
+ /**
79
+ * Clean up expired keys (soft delete by setting revokedAt)
80
+ */
81
+ async cleanupExpired() {
82
+ const now = /* @__PURE__ */ new Date();
83
+ const allKeys = await this.list({});
84
+ let cleaned = 0;
85
+ for (const key of allKeys) if (key.expiresAt && key.expiresAt < now && !key.revokedAt) {
86
+ key.revokedAt = now;
87
+ await key.save();
88
+ cleaned++;
89
+ }
90
+ return cleaned;
91
+ }
92
+ };
93
+ //#endregion
94
+ //#region ../profiles/dist/chunks/AuditLogCollection-B1YonCAP.js
95
+ var __defProp$22 = Object.defineProperty;
96
+ var __getOwnPropDesc$21 = Object.getOwnPropertyDescriptor;
97
+ var __decorateClass$21 = (decorators, target, key, kind) => {
98
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$21(target, key) : target;
99
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
100
+ if (kind && result) __defProp$22(target, key, result);
101
+ return result;
102
+ };
103
+ var AuditLog = class extends SmrtObject {
104
+ tenantId = null;
105
+ profileId;
106
+ /**
107
+ * Action performed (e.g., 'issue.update', 'feedback.incorporate')
108
+ */
109
+ action = "";
110
+ /**
111
+ * Type of resource affected (e.g., 'Issue', 'Repository')
112
+ */
113
+ resourceType = "";
114
+ /**
115
+ * ID of the affected resource
116
+ */
117
+ resourceId = "";
118
+ /**
119
+ * Source of the action
120
+ */
121
+ source = "web";
122
+ /**
123
+ * Additional context (CI run ID, request ID, etc.)
124
+ */
125
+ metadata = {};
126
+ onBehalfOfId;
127
+ constructor(options = {}) {
128
+ super(options);
129
+ if (options.profileId) this.profileId = options.profileId;
130
+ if (options.action) this.action = options.action;
131
+ if (options.resourceType) this.resourceType = options.resourceType;
132
+ if (options.resourceId) this.resourceId = options.resourceId;
133
+ if (options.source) this.source = options.source;
134
+ if (options.metadata) this.metadata = options.metadata;
135
+ if (options.onBehalfOfId !== void 0) this.onBehalfOfId = options.onBehalfOfId;
136
+ }
137
+ /**
138
+ * Get the profile who performed the action
139
+ */
140
+ async getProfile() {
141
+ return await this.getRelated("profileId");
142
+ }
143
+ /**
144
+ * Get the profile on whose behalf the action was performed (if any)
145
+ */
146
+ async getOnBehalfOf() {
147
+ if (!this.onBehalfOfId) return null;
148
+ return await this.getRelated("onBehalfOfId");
149
+ }
150
+ /**
151
+ * Get the effective actor (onBehalfOf if set, otherwise profile)
152
+ */
153
+ async getEffectiveActor() {
154
+ const onBehalfOf = await this.getOnBehalfOf();
155
+ if (onBehalfOf) return onBehalfOf;
156
+ return await this.getProfile();
157
+ }
158
+ /**
159
+ * Create an audit log entry
160
+ */
161
+ static async record(options) {
162
+ const log = new AuditLog({
163
+ ...options,
164
+ profileId: options.profile.id,
165
+ onBehalfOfId: options.onBehalfOf?.id
166
+ });
167
+ await log.initialize();
168
+ await log.save();
169
+ return log;
170
+ }
171
+ };
172
+ __decorateClass$21([tenantId({ nullable: true })], AuditLog.prototype, "tenantId", 2);
173
+ __decorateClass$21([foreignKey("Profile", { required: true })], AuditLog.prototype, "profileId", 2);
174
+ __decorateClass$21([foreignKey("Profile", { nullable: true })], AuditLog.prototype, "onBehalfOfId", 2);
175
+ AuditLog = __decorateClass$21([TenantScoped({
176
+ mode: "optional",
177
+ allowSuperAdminBypass: true
178
+ }), smrt({
179
+ tableName: "audit_logs",
180
+ api: { include: ["list", "get"] },
181
+ mcp: { include: ["list", "get"] },
182
+ cli: { include: ["list"] }
183
+ })], AuditLog);
184
+ var AuditLogCollection_exports = /* @__PURE__ */ __exportAll$1({ AuditLogCollection: () => AuditLogCollection });
185
+ var AuditLogCollection = class extends SmrtCollection {
186
+ static _itemClass = AuditLog;
187
+ /**
188
+ * Find logs for a profile (actions they performed)
189
+ */
190
+ async findByProfile(profileId) {
191
+ return await this.list({
192
+ where: { profileId },
193
+ orderBy: "createdAt DESC"
194
+ });
195
+ }
196
+ /**
197
+ * Find logs for a resource
198
+ */
199
+ async findByResource(resourceType, resourceId) {
200
+ return await this.list({
201
+ where: {
202
+ resourceType,
203
+ resourceId
204
+ },
205
+ orderBy: "createdAt DESC"
206
+ });
207
+ }
208
+ /**
209
+ * Find logs by action type
210
+ */
211
+ async findByAction(action) {
212
+ return await this.list({
213
+ where: { action },
214
+ orderBy: "createdAt DESC"
215
+ });
216
+ }
217
+ /**
218
+ * Find logs by source
219
+ */
220
+ async findBySource(source) {
221
+ return await this.list({
222
+ where: { source },
223
+ orderBy: "createdAt DESC"
224
+ });
225
+ }
226
+ /**
227
+ * Find logs where actions were performed on behalf of someone
228
+ */
229
+ async findOnBehalfOf(profileId) {
230
+ return await this.list({
231
+ where: { onBehalfOfId: profileId },
232
+ orderBy: "createdAt DESC"
233
+ });
234
+ }
235
+ /**
236
+ * Record a new audit log entry
237
+ */
238
+ async record(options) {
239
+ const log = new AuditLog({
240
+ ...this.options,
241
+ profileId: options.profile.id,
242
+ action: options.action,
243
+ resourceType: options.resourceType,
244
+ resourceId: options.resourceId,
245
+ source: options.source || "web",
246
+ metadata: options.metadata || {},
247
+ onBehalfOfId: options.onBehalfOf?.id
248
+ });
249
+ await log.initialize();
250
+ await log.save();
251
+ return log;
252
+ }
253
+ /**
254
+ * Get recent activity for a profile
255
+ */
256
+ async getRecentActivity(profileId, limit = 50) {
257
+ return await this.list({
258
+ where: { profileId },
259
+ orderBy: "createdAt DESC",
260
+ limit
261
+ });
262
+ }
263
+ /**
264
+ * Get activity timeline for a resource
265
+ */
266
+ async getResourceTimeline(resourceType, resourceId) {
267
+ return await this.list({
268
+ where: {
269
+ resourceType,
270
+ resourceId
271
+ },
272
+ orderBy: "createdAt ASC"
273
+ });
274
+ }
275
+ };
276
+ //#endregion
277
+ //#region ../profiles/dist/chunks/NostrIdentityCollection-Ca74dkaL.js
278
+ var NostrIdentityCollection_exports = /* @__PURE__ */ __exportAll$1({ NostrIdentityCollection: () => NostrIdentityCollection });
279
+ var NostrIdentityCollection = class extends SmrtCollection {
280
+ static _itemClass = NostrIdentity;
281
+ /**
282
+ * Find identities for a profile
283
+ */
284
+ async findByProfile(profileId) {
285
+ return await this.list({ where: { profileId } });
286
+ }
287
+ /**
288
+ * Find identity by public key
289
+ */
290
+ async findByPubkey(pubkey) {
291
+ return await this.findOne({ where: { pubkey } });
292
+ }
293
+ /**
294
+ * Find identity by email
295
+ */
296
+ async findByEmail(email) {
297
+ return await this.findOne({ where: { email: email.toLowerCase() } });
298
+ }
299
+ /**
300
+ * Find identity by NIP-05 username
301
+ */
302
+ async findByNip05(username) {
303
+ return await this.findOne({ where: { nip05Username: username.toLowerCase() } });
304
+ }
305
+ /**
306
+ * Link a new Nostr identity to a profile with a new keypair
307
+ * @param profile - The profile to link to
308
+ * @param email - Email address for this identity
309
+ * @param masterSecret - Server master secret for encryption
310
+ * @param nip05Username - Optional NIP-05 username (defaults to email local part)
311
+ */
312
+ async createForProfile(profile, email, masterSecret, nip05Username) {
313
+ const normalizedEmail = email.toLowerCase();
314
+ if (await this.findByEmail(normalizedEmail)) throw new Error(`Nostr identity already exists for email: ${email}`);
315
+ const keypair = generateNostrKeypair();
316
+ const encrypted = encryptPrivkey(keypair.privkey, masterSecret);
317
+ const username = nip05Username?.toLowerCase() || normalizedEmail.split("@")[0];
318
+ const identity = new NostrIdentity({
319
+ ...this.options,
320
+ profileId: profile.id,
321
+ pubkey: keypair.pubkey,
322
+ encryptedPrivkey: encrypted.ciphertext,
323
+ encryptionIv: encrypted.iv,
324
+ encryptionTag: encrypted.tag,
325
+ email: normalizedEmail,
326
+ nip05Username: username
327
+ });
328
+ await identity.initialize();
329
+ await identity.save();
330
+ return identity;
331
+ }
332
+ /**
333
+ * Link an existing Nostr identity (with encrypted keypair) to a profile
334
+ */
335
+ async linkToProfile(profile, nostrData) {
336
+ if (await this.findByPubkey(nostrData.pubkey)) throw new Error("Nostr identity with this public key already exists");
337
+ if (await this.findByEmail(nostrData.email)) throw new Error("Nostr identity with this email already exists");
338
+ const identity = new NostrIdentity({
339
+ ...this.options,
340
+ profileId: profile.id,
341
+ pubkey: nostrData.pubkey,
342
+ encryptedPrivkey: nostrData.encryptedPrivkey,
343
+ encryptionIv: nostrData.encryptionIv,
344
+ encryptionTag: nostrData.encryptionTag,
345
+ email: nostrData.email.toLowerCase(),
346
+ nip05Username: nostrData.nip05Username?.toLowerCase() || nostrData.email.toLowerCase().split("@")[0]
347
+ });
348
+ await identity.initialize();
349
+ await identity.save();
350
+ return identity;
351
+ }
352
+ /**
353
+ * Unlink a Nostr identity from a profile
354
+ */
355
+ async unlinkFromProfile(profileId, pubkey) {
356
+ const identity = await this.findOne({ where: {
357
+ profileId,
358
+ pubkey
359
+ } });
360
+ if (identity) {
361
+ await identity.delete();
362
+ return true;
363
+ }
364
+ return false;
365
+ }
366
+ /**
367
+ * Get NIP-05 response data for the /.well-known/nostr.json endpoint
368
+ * @param username - Optional username filter, returns all if not provided
369
+ */
370
+ async getNip05Response(username) {
371
+ const where = username ? { nip05Username: username.toLowerCase() } : {};
372
+ const identities = await this.list({ where });
373
+ const names = {};
374
+ for (const identity of identities) if (identity.nip05Username && identity.pubkey) names[identity.nip05Username] = identity.pubkey;
375
+ return { names };
376
+ }
377
+ /**
378
+ * Check if a NIP-05 username is available
379
+ */
380
+ async isNip05Available(username) {
381
+ return await this.findByNip05(username) === null;
382
+ }
383
+ /**
384
+ * Update NIP-05 username for an identity
385
+ */
386
+ async updateNip05Username(identity, newUsername) {
387
+ const normalizedUsername = newUsername.toLowerCase();
388
+ const existing = await this.findByNip05(normalizedUsername);
389
+ if (existing && existing.id !== identity.id) throw new Error(`NIP-05 username "${newUsername}" is already taken`);
390
+ identity.nip05Username = normalizedUsername;
391
+ await identity.save();
392
+ return identity;
393
+ }
394
+ };
395
+ //#endregion
396
+ //#region ../profiles/dist/chunks/OidcIdentityCollection-D3L0WYbM.js
397
+ var OidcIdentityCollection_exports = /* @__PURE__ */ __exportAll$1({
398
+ AmbiguousOidcIdentityError: () => AmbiguousOidcIdentityError,
399
+ OidcIdentityCollection: () => OidcIdentityCollection
400
+ });
401
+ var AmbiguousOidcIdentityError = class extends Error {
402
+ constructor(issuer, subject) {
403
+ super("Multiple OIDC identities match the same issuer and subject.");
404
+ this.issuer = issuer;
405
+ this.subject = subject;
406
+ this.name = "AmbiguousOidcIdentityError";
407
+ }
408
+ issuer;
409
+ subject;
410
+ };
411
+ var OidcIdentityCollection = class extends SmrtCollection {
412
+ static _itemClass = OidcIdentity;
413
+ /**
414
+ * Find identities for a profile
415
+ */
416
+ async findByProfile(profileId) {
417
+ return await this.list({ where: { profileId } });
418
+ }
419
+ /**
420
+ * Find identity by issuer and subject
421
+ */
422
+ async findBySubject(issuer, subject) {
423
+ const result = await this.db.query(`SELECT CAST(id AS VARCHAR) AS id,
424
+ CAST(profile_id AS VARCHAR) AS profile_id
425
+ FROM oidc_identities
426
+ WHERE issuer = ? AND subject = ?
427
+ LIMIT 2`, issuer, subject);
428
+ if (result.rows.length > 1) throw new AmbiguousOidcIdentityError(issuer, subject);
429
+ const row = result.rows[0];
430
+ const id = row?.id;
431
+ const profileId = row?.profile_id;
432
+ if (typeof id !== "string" || typeof profileId !== "string") return null;
433
+ const identity = await this.get({ id });
434
+ if (!identity) return null;
435
+ identity.id = id;
436
+ identity.profileId = profileId;
437
+ return identity;
438
+ }
439
+ /**
440
+ * Find identities by provider
441
+ */
442
+ async findByProvider(provider) {
443
+ return await this.list({ where: { provider } });
444
+ }
445
+ /**
446
+ * Reuse an existing exact OIDC identity for its unchanged Profile.
447
+ *
448
+ * @deprecated New authentication links require the owner-aware,
449
+ * transactional provisioning APIs. This compatibility helper may refresh a
450
+ * legacy Profile type, but refuses to create or rebind authority.
451
+ */
452
+ async linkToProfile(profile, oidcData) {
453
+ return OidcIdentity.findOrCreate(profile, oidcData, this.options);
454
+ }
455
+ /**
456
+ * Unlink an OIDC identity from a profile
457
+ */
458
+ async unlinkFromProfile(profileId, issuer, subject) {
459
+ const identity = await this.findOne({ where: {
460
+ profileId,
461
+ issuer,
462
+ subject
463
+ } });
464
+ if (identity) {
465
+ await identity.delete();
466
+ return true;
467
+ }
468
+ return false;
469
+ }
470
+ };
471
+ //#endregion
472
+ //#region ../profiles/dist/chunks/ProfileAssetCollection-V8u4wqSL.js
473
+ var __defProp$1$19 = Object.defineProperty;
474
+ var __getOwnPropDesc$1$18 = Object.getOwnPropertyDescriptor;
475
+ var __decorateClass$1$18 = (decorators, target, key, kind) => {
476
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1$18(target, key) : target;
477
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
478
+ if (kind && result) __defProp$1$19(target, key, result);
479
+ return result;
480
+ };
481
+ var ProfileAsset = class extends SmrtObject {
482
+ tenantId = null;
483
+ profileId = "";
484
+ assetId = "";
485
+ relationship = "attachment";
486
+ sortOrder = 0;
487
+ constructor(options = {}) {
488
+ super(options);
489
+ if (options.profileId) this.profileId = options.profileId;
490
+ if (options.assetId) this.assetId = options.assetId;
491
+ if (options.relationship) this.relationship = options.relationship;
492
+ if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
493
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
494
+ }
495
+ };
496
+ __decorateClass$1$18([tenantId({ nullable: true })], ProfileAsset.prototype, "tenantId", 2);
497
+ __decorateClass$1$18([foreignKey("Profile", { required: true })], ProfileAsset.prototype, "profileId", 2);
498
+ __decorateClass$1$18([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], ProfileAsset.prototype, "assetId", 2);
499
+ __decorateClass$1$18([field({ required: true })], ProfileAsset.prototype, "relationship", 2);
500
+ __decorateClass$1$18([field()], ProfileAsset.prototype, "sortOrder", 2);
501
+ ProfileAsset = __decorateClass$1$18([TenantScoped({ mode: "optional" }), smrt({
502
+ tableName: "profile_assets",
503
+ conflictColumns: [
504
+ "profile_id",
505
+ "asset_id",
506
+ "relationship"
507
+ ],
508
+ api: false,
509
+ mcp: false,
510
+ cli: false
511
+ })], ProfileAsset);
512
+ var ProfileAssetCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileAssetCollection: () => ProfileAssetCollection });
513
+ var __defProp$21 = Object.defineProperty;
514
+ var __getOwnPropDesc$20 = Object.getOwnPropertyDescriptor;
515
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp$21(obj, key, {
516
+ enumerable: true,
517
+ configurable: true,
518
+ writable: true,
519
+ value
520
+ }) : obj[key] = value;
521
+ var __decorateClass$20 = (decorators, target, key, kind) => {
522
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$20(target, key) : target;
523
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
524
+ if (kind && result) __defProp$21(target, key, result);
525
+ return result;
526
+ };
527
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
528
+ var ProfileAssetCollection = class extends SmrtJunction {
529
+ leftField = "profileId";
530
+ rightField = "assetId";
531
+ profileCollectionPromise = null;
532
+ async getProfileCollection() {
533
+ if (!this.profileCollectionPromise) {
534
+ const { ProfileCollection } = await import("./ProfileCollection-BvhD2cfL-P9hC9GcP.js").then((n) => n.r).then((n) => n.r);
535
+ this.profileCollectionPromise = ProfileCollection.create({ db: this.db });
536
+ }
537
+ return this.profileCollectionPromise;
538
+ }
539
+ async getAssets(profileId, relationship) {
540
+ return getOwnedAssetsFromCollection(await this.getProfileCollection(), profileId, relationship);
541
+ }
542
+ async addAsset(profileId, asset, relationship = "attachment", sortOrder = 0) {
543
+ await addOwnedAssetFromCollection(await this.getProfileCollection(), "Profile", profileId, asset, relationship, sortOrder);
544
+ }
545
+ async removeAsset(profileId, assetId, relationship) {
546
+ await removeOwnedAssetFromCollection(await this.getProfileCollection(), "Profile", profileId, assetId, relationship);
547
+ }
548
+ };
549
+ __publicField(ProfileAssetCollection, "_itemClass", ProfileAsset);
550
+ ProfileAssetCollection = __decorateClass$20([smrt({
551
+ api: false,
552
+ mcp: false,
553
+ cli: false
554
+ })], ProfileAssetCollection);
555
+ //#endregion
556
+ //#region ../profiles/dist/chunks/ProfileMetadataCollection-DxX_BJKV.js
557
+ var __defProp$20 = Object.defineProperty;
558
+ var __getOwnPropDesc$19 = Object.getOwnPropertyDescriptor;
559
+ var __decorateClass$19 = (decorators, target, key, kind) => {
560
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$19(target, key) : target;
561
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
562
+ if (kind && result) __defProp$20(target, key, result);
563
+ return result;
564
+ };
565
+ var ProfileMetadata = class extends SmrtObject {
566
+ tenantId = null;
567
+ profileId;
568
+ metafieldId;
569
+ value = "";
570
+ constructor(options = {}) {
571
+ super(options);
572
+ if (options.profileId !== void 0) this.profileId = options.profileId;
573
+ if (options.metafieldId !== void 0) this.metafieldId = options.metafieldId;
574
+ if (options.value) this.value = options.value;
575
+ }
576
+ /**
577
+ * Validate this metadata value against the metafield's validation schema
578
+ *
579
+ * @returns True if valid, throws error if invalid
580
+ */
581
+ async validate() {
582
+ const metafield = await this.loadRelated("metafieldId");
583
+ if (!metafield) throw new Error("Metafield not found");
584
+ return await metafield.validateValue(this.value);
585
+ }
586
+ /**
587
+ * Get the metafield slug for this metadata
588
+ *
589
+ * @returns The slug of the metafield
590
+ */
591
+ async getMetafieldSlug() {
592
+ return (await this.loadRelated("metafieldId"))?.slug || "";
593
+ }
594
+ };
595
+ __decorateClass$19([tenantId({ nullable: true })], ProfileMetadata.prototype, "tenantId", 2);
596
+ __decorateClass$19([foreignKey("Profile", { required: true })], ProfileMetadata.prototype, "profileId", 2);
597
+ __decorateClass$19([foreignKey("ProfileMetafield", { required: true })], ProfileMetadata.prototype, "metafieldId", 2);
598
+ __decorateClass$19([field({ required: true })], ProfileMetadata.prototype, "value", 2);
599
+ ProfileMetadata = __decorateClass$19([TenantScoped({ mode: "optional" }), smrt({
600
+ tableStrategy: "sti",
601
+ api: { include: [
602
+ "list",
603
+ "get",
604
+ "create",
605
+ "update",
606
+ "delete"
607
+ ] },
608
+ mcp: { include: ["list", "get"] },
609
+ cli: { skipApiCheck: true }
610
+ })], ProfileMetadata);
611
+ var ProfileMetadataCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileMetadataCollection: () => ProfileMetadataCollection });
612
+ var ProfileMetadataCollection = class extends SmrtCollection {
613
+ static _itemClass = ProfileMetadata;
614
+ /**
615
+ * Get all metadata for a profile
616
+ *
617
+ * @param profileId - The profile UUID
618
+ * @returns Array of ProfileMetadata instances
619
+ */
620
+ async getByProfile(profileId) {
621
+ return await this.list({ where: { profileId } });
622
+ }
623
+ /**
624
+ * Get metadata as key-value object for a profile
625
+ *
626
+ * @param profileId - The profile UUID
627
+ * @returns Object with metafield slugs as keys
628
+ */
629
+ async getMetadataObject(profileId) {
630
+ const metadata = await this.getByProfile(profileId);
631
+ const result = {};
632
+ for (const item of metadata) {
633
+ const slug = await item.getMetafieldSlug();
634
+ if (slug) result[slug] = item.value;
635
+ }
636
+ return result;
637
+ }
638
+ /**
639
+ * Find all profiles with a specific metadata key-value pair
640
+ *
641
+ * @param metafieldId - The metafield UUID
642
+ * @param value - The value to match
643
+ * @returns Array of profile UUIDs
644
+ */
645
+ async findProfilesByMetadata(metafieldId, value) {
646
+ return (await this.list({ where: {
647
+ metafieldId,
648
+ value: String(value)
649
+ } })).map((m) => m.profileId).filter((id) => typeof id === "string");
650
+ }
651
+ };
652
+ //#endregion
653
+ //#region ../profiles/dist/chunks/ProfileMetafieldCollection-CMKhVi2I.js
654
+ var __defProp$19 = Object.defineProperty;
655
+ var __getOwnPropDesc$18 = Object.getOwnPropertyDescriptor;
656
+ var __decorateClass$18 = (decorators, target, key, kind) => {
657
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$18(target, key) : target;
658
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
659
+ if (kind && result) __defProp$19(target, key, result);
660
+ return result;
661
+ };
662
+ function getCustomValidators() {
663
+ if (!globalThis.__smrtProfileMetafieldValidators) globalThis.__smrtProfileMetafieldValidators = /* @__PURE__ */ new Map();
664
+ return globalThis.__smrtProfileMetafieldValidators;
665
+ }
666
+ var ProfileMetafield = class extends SmrtObject {
667
+ tenantId = null;
668
+ name = "";
669
+ description;
670
+ validation;
671
+ constructor(options = {}) {
672
+ super(options);
673
+ if (options.name) this.name = options.name;
674
+ if (options.description !== void 0) this.description = options.description;
675
+ if (options.validation !== void 0) this.validation = options.validation;
676
+ }
677
+ /**
678
+ * Convenience method for slug-based lookup
679
+ *
680
+ * @param slug - The slug to search for
681
+ * @returns ProfileMetafield instance or null if not found
682
+ */
683
+ static async getBySlug(_slug) {
684
+ return null;
685
+ }
686
+ /**
687
+ * Register a custom validator function
688
+ *
689
+ * @param name - Name of the validator (used in validation.custom field)
690
+ * @param validator - The validator function
691
+ */
692
+ static registerValidator(name, validator) {
693
+ getCustomValidators().set(name, validator);
694
+ }
695
+ /**
696
+ * Get a registered custom validator
697
+ *
698
+ * @param name - Name of the validator
699
+ * @returns The validator function or undefined
700
+ */
701
+ static getValidator(name) {
702
+ return getCustomValidators().get(name);
703
+ }
704
+ /**
705
+ * Validate a value against this metafield's validation schema
706
+ *
707
+ * @param value - The value to validate
708
+ * @returns True if valid, throws ValidationError if invalid
709
+ */
710
+ async validateValue(value) {
711
+ if (!this.validation) return true;
712
+ const schema = this.validation;
713
+ if (schema.type) {
714
+ const actualType = typeof value;
715
+ const expectedType = schema.type;
716
+ if (expectedType === "number" && actualType !== "number") throw new Error(schema.message || `Expected ${expectedType}, got ${actualType}`);
717
+ if (expectedType === "string" && actualType !== "string") throw new Error(schema.message || `Expected ${expectedType}, got ${actualType}`);
718
+ if (expectedType === "boolean" && actualType !== "boolean") throw new Error(schema.message || `Expected ${expectedType}, got ${actualType}`);
719
+ }
720
+ if (schema.pattern && typeof value === "string") {
721
+ if (!new RegExp(schema.pattern).test(value)) throw new Error(schema.message || "Pattern validation failed");
722
+ }
723
+ if (schema.minLength && typeof value === "string") {
724
+ if (value.length < schema.minLength) throw new Error(schema.message || `Minimum length is ${schema.minLength}, got ${value.length}`);
725
+ }
726
+ if (schema.maxLength && typeof value === "string") {
727
+ if (value.length > schema.maxLength) throw new Error(schema.message || `Maximum length is ${schema.maxLength}, got ${value.length}`);
728
+ }
729
+ if (schema.min !== void 0 && typeof value === "number") {
730
+ if (value < schema.min) throw new Error(schema.message || `Value must be at least ${schema.min}`);
731
+ }
732
+ if (schema.max !== void 0 && typeof value === "number") {
733
+ if (value > schema.max) throw new Error(schema.message || `Value must be at most ${schema.max}`);
734
+ }
735
+ if (schema.custom) {
736
+ const validator = ProfileMetafield.getValidator(schema.custom);
737
+ if (!validator) throw new Error(`Custom validator '${schema.custom}' not registered`);
738
+ if (!await validator(value)) throw new Error(schema.message || "Custom validation failed");
739
+ }
740
+ return true;
741
+ }
742
+ };
743
+ __decorateClass$18([tenantId({ nullable: true })], ProfileMetafield.prototype, "tenantId", 2);
744
+ __decorateClass$18([field({ required: true })], ProfileMetafield.prototype, "name", 2);
745
+ ProfileMetafield = __decorateClass$18([TenantScoped({ mode: "optional" }), smrt({
746
+ tableStrategy: "sti",
747
+ api: { include: [
748
+ "list",
749
+ "get",
750
+ "create",
751
+ "update"
752
+ ] },
753
+ mcp: { include: ["list", "get"] },
754
+ cli: { skipApiCheck: true }
755
+ })], ProfileMetafield);
756
+ var ProfileMetafieldCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileMetafieldCollection: () => ProfileMetafieldCollection });
757
+ var ProfileMetafieldCollection = class extends SmrtCollection {
758
+ static _itemClass = ProfileMetafield;
759
+ /**
760
+ * Get metafield by slug
761
+ *
762
+ * @param slug - The slug to search for
763
+ * @returns ProfileMetafield instance or null
764
+ */
765
+ async getBySlug(slug) {
766
+ return await this.get({ slug });
767
+ }
768
+ /**
769
+ * Get or create a metafield by slug
770
+ *
771
+ * @param slug - The slug to search for
772
+ * @param defaults - Default values if creating
773
+ * @returns ProfileMetafield instance
774
+ */
775
+ async getOrCreateBySlug(slug, defaults) {
776
+ const existing = await this.getBySlug(slug);
777
+ if (existing) return existing;
778
+ const metafield = await this.create({
779
+ slug,
780
+ ...defaults
781
+ });
782
+ await metafield.save();
783
+ return metafield;
784
+ }
785
+ };
786
+ //#endregion
787
+ //#region ../profiles/dist/chunks/ProfileRelationshipCollection-DUVgaIqf.js
788
+ var __defProp$18 = Object.defineProperty;
789
+ var __getOwnPropDesc$17 = Object.getOwnPropertyDescriptor;
790
+ var __decorateClass$17 = (decorators, target, key, kind) => {
791
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$17(target, key) : target;
792
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
793
+ if (kind && result) __defProp$18(target, key, result);
794
+ return result;
795
+ };
796
+ var ProfileRelationship = class extends SmrtObject {
797
+ tenantId = null;
798
+ fromProfileId;
799
+ toProfileId;
800
+ typeId;
801
+ contextProfileId;
802
+ terms = [];
803
+ constructor(options = {}) {
804
+ super(options);
805
+ if (options.fromProfileId !== void 0) this.fromProfileId = options.fromProfileId;
806
+ if (options.toProfileId !== void 0) this.toProfileId = options.toProfileId;
807
+ if (options.typeId !== void 0) this.typeId = options.typeId;
808
+ if (options.contextProfileId !== void 0) this.contextProfileId = options.contextProfileId;
809
+ }
810
+ /**
811
+ * Get the relationship type slug
812
+ *
813
+ * @returns The slug of the relationship type
814
+ */
815
+ async getTypeSlug() {
816
+ return (await this.loadRelated("typeId"))?.slug || "";
817
+ }
818
+ /**
819
+ * Add a term (time period) to this relationship
820
+ *
821
+ * @param startedAt - Start date of the term
822
+ * @param endedAt - Optional end date of the term
823
+ */
824
+ async addTerm(startedAt, endedAt) {
825
+ if (!this.id) throw new Error("ProfileRelationship.addTerm requires a persisted relationship (missing id)");
826
+ const relationshipId = this.id;
827
+ const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-DtA9OM23-EGZ4UVpV.js").then((n) => n.n);
828
+ await (await (await ProfileRelationshipTermCollection.create(this.options)).create({
829
+ relationshipId,
830
+ startedAt,
831
+ endedAt
832
+ })).save();
833
+ }
834
+ /**
835
+ * End the current active term
836
+ *
837
+ * @param endedAt - End date for the term
838
+ */
839
+ async endCurrentTerm(endedAt) {
840
+ const activeTerm = await this.getActiveTerm();
841
+ if (activeTerm) await activeTerm.end(endedAt);
842
+ }
843
+ /**
844
+ * Get all terms for this relationship
845
+ *
846
+ * @returns Array of ProfileRelationshipTerm instances
847
+ */
848
+ async getTerms() {
849
+ const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-DtA9OM23-EGZ4UVpV.js").then((n) => n.n);
850
+ return await (await ProfileRelationshipTermCollection.create(this.options)).getByRelationship(this.id);
851
+ }
852
+ /**
853
+ * Get the active term (no end date)
854
+ *
855
+ * @returns Current term or null if none active
856
+ */
857
+ async getActiveTerm() {
858
+ const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-DtA9OM23-EGZ4UVpV.js").then((n) => n.n);
859
+ return await (await ProfileRelationshipTermCollection.create(this.options)).getActiveTerm(this.id);
860
+ }
861
+ };
862
+ __decorateClass$17([tenantId({ nullable: true })], ProfileRelationship.prototype, "tenantId", 2);
863
+ __decorateClass$17([foreignKey("Profile", { required: true })], ProfileRelationship.prototype, "fromProfileId", 2);
864
+ __decorateClass$17([foreignKey("Profile", { required: true })], ProfileRelationship.prototype, "toProfileId", 2);
865
+ __decorateClass$17([foreignKey("ProfileRelationshipType", { required: true })], ProfileRelationship.prototype, "typeId", 2);
866
+ __decorateClass$17([foreignKey("Profile")], ProfileRelationship.prototype, "contextProfileId", 2);
867
+ __decorateClass$17([oneToMany("ProfileRelationshipTerm")], ProfileRelationship.prototype, "terms", 2);
868
+ ProfileRelationship = __decorateClass$17([TenantScoped({ mode: "optional" }), smrt({
869
+ tableStrategy: "sti",
870
+ api: { include: [
871
+ "list",
872
+ "get",
873
+ "create",
874
+ "delete"
875
+ ] },
876
+ mcp: { include: ["list", "get"] },
877
+ cli: { skipApiCheck: true }
878
+ })], ProfileRelationship);
879
+ var ProfileRelationshipCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileRelationshipCollection: () => ProfileRelationshipCollection });
880
+ var ProfileRelationshipCollection = class extends SmrtCollection {
881
+ static _itemClass = ProfileRelationship;
882
+ /**
883
+ * Get all relationships from a profile
884
+ *
885
+ * @param fromProfileId - The origin profile UUID
886
+ * @param typeId - Optional filter by relationship type UUID
887
+ * @returns Array of ProfileRelationship instances
888
+ */
889
+ async getFromProfile(fromProfileId, typeId) {
890
+ const where = { fromProfileId };
891
+ if (typeId) where.typeId = typeId;
892
+ return await this.list({ where });
893
+ }
894
+ /**
895
+ * Get all relationships to a profile
896
+ *
897
+ * @param toProfileId - The target profile UUID
898
+ * @param typeId - Optional filter by relationship type UUID
899
+ * @returns Array of ProfileRelationship instances
900
+ */
901
+ async getToProfile(toProfileId, typeId) {
902
+ const where = { toProfileId };
903
+ if (typeId) where.typeId = typeId;
904
+ return await this.list({ where });
905
+ }
906
+ /**
907
+ * Get all relationships for a profile (both directions)
908
+ *
909
+ * @param profileId - The profile UUID
910
+ * @param typeId - Optional filter by relationship type UUID
911
+ * @returns Array of ProfileRelationship instances
912
+ */
913
+ async getForProfile(profileId, typeId) {
914
+ const fromRelationships = await this.getFromProfile(profileId, typeId);
915
+ const toRelationships = await this.getToProfile(profileId, typeId);
916
+ return [...fromRelationships, ...toRelationships];
917
+ }
918
+ /**
919
+ * Check if a relationship exists between two profiles
920
+ *
921
+ * @param fromProfileId - The origin profile UUID
922
+ * @param toProfileId - The target profile UUID
923
+ * @param typeId - The relationship type UUID
924
+ * @returns True if relationship exists
925
+ */
926
+ async exists(fromProfileId, toProfileId, typeId) {
927
+ return (await this.list({
928
+ where: {
929
+ fromProfileId,
930
+ toProfileId,
931
+ typeId
932
+ },
933
+ limit: 1
934
+ })).length > 0;
935
+ }
936
+ };
937
+ //#endregion
938
+ //#region ../profiles/dist/chunks/ProfileRelationshipTermCollection-DtA9OM23.js
939
+ var __defProp$17 = Object.defineProperty;
940
+ var __getOwnPropDesc$16 = Object.getOwnPropertyDescriptor;
941
+ var __decorateClass$16 = (decorators, target, key, kind) => {
942
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$16(target, key) : target;
943
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
944
+ if (kind && result) __defProp$17(target, key, result);
945
+ return result;
946
+ };
947
+ var ProfileRelationshipTerm = class extends SmrtObject {
948
+ relationshipId;
949
+ startedAt = /* @__PURE__ */ new Date();
950
+ endedAt;
951
+ constructor(options = {}) {
952
+ super(options);
953
+ if (options.relationshipId !== void 0) this.relationshipId = options.relationshipId;
954
+ if (options.startedAt) this.startedAt = options.startedAt;
955
+ if (options.endedAt !== void 0) this.endedAt = options.endedAt;
956
+ }
957
+ /**
958
+ * Check if this term is currently active
959
+ *
960
+ * @returns True if active (no end date or end date in future)
961
+ */
962
+ isActive() {
963
+ if (!this.endedAt) return true;
964
+ return this.endedAt > /* @__PURE__ */ new Date();
965
+ }
966
+ /**
967
+ * End this term
968
+ *
969
+ * @param endedAt - End date for the term (defaults to now)
970
+ */
971
+ async end(endedAt = /* @__PURE__ */ new Date()) {
972
+ this.endedAt = endedAt;
973
+ await this.save();
974
+ }
975
+ /**
976
+ * Get the duration of this term in days
977
+ *
978
+ * @returns Duration in days
979
+ */
980
+ getDurationDays() {
981
+ const diffMs = (this.endedAt || /* @__PURE__ */ new Date()).getTime() - this.startedAt.getTime();
982
+ return Math.floor(diffMs / (1e3 * 60 * 60 * 24));
983
+ }
984
+ };
985
+ __decorateClass$16([foreignKey("ProfileRelationship", { required: true })], ProfileRelationshipTerm.prototype, "relationshipId", 2);
986
+ __decorateClass$16([field({ required: true })], ProfileRelationshipTerm.prototype, "startedAt", 2);
987
+ ProfileRelationshipTerm = __decorateClass$16([smrt({
988
+ tableStrategy: "sti",
989
+ api: { include: [
990
+ "list",
991
+ "get",
992
+ "create",
993
+ "update",
994
+ "delete"
995
+ ] },
996
+ mcp: { include: ["list", "get"] },
997
+ cli: { skipApiCheck: true }
998
+ })], ProfileRelationshipTerm);
999
+ var ProfileRelationshipTermCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileRelationshipTermCollection: () => ProfileRelationshipTermCollection });
1000
+ var ProfileRelationshipTermCollection = class extends SmrtCollection {
1001
+ static _itemClass = ProfileRelationshipTerm;
1002
+ /**
1003
+ * Get all terms for a relationship
1004
+ *
1005
+ * @param relationshipId - The relationship UUID
1006
+ * @returns Array of ProfileRelationshipTerm instances
1007
+ */
1008
+ async getByRelationship(relationshipId) {
1009
+ return await this.list({
1010
+ where: { relationshipId },
1011
+ orderBy: ["startedAt DESC"]
1012
+ });
1013
+ }
1014
+ /**
1015
+ * Get the active term for a relationship (no end date or future end date)
1016
+ *
1017
+ * @param relationshipId - The relationship UUID
1018
+ * @returns Active term or null
1019
+ */
1020
+ async getActiveTerm(relationshipId) {
1021
+ const terms = await this.getByRelationship(relationshipId);
1022
+ for (const term of terms) if (term.isActive()) return term;
1023
+ return null;
1024
+ }
1025
+ /**
1026
+ * Get all historical (ended) terms for a relationship
1027
+ *
1028
+ * @param relationshipId - The relationship UUID
1029
+ * @returns Array of ended ProfileRelationshipTerm instances
1030
+ */
1031
+ async getHistoricalTerms(relationshipId) {
1032
+ return (await this.getByRelationship(relationshipId)).filter((term) => !term.isActive());
1033
+ }
1034
+ };
1035
+ //#endregion
1036
+ //#region ../profiles/dist/chunks/ProfileRelationshipTypeCollection-BdXwd7Kf.js
1037
+ var ProfileRelationshipTypeCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileRelationshipTypeCollection: () => ProfileRelationshipTypeCollection });
1038
+ var ProfileRelationshipTypeCollection = class extends SmrtCollection {
1039
+ static _itemClass = ProfileRelationshipType;
1040
+ /**
1041
+ * Get relationship type by slug
1042
+ *
1043
+ * @param slug - The slug to search for
1044
+ * @returns ProfileRelationshipType instance or null
1045
+ */
1046
+ async getBySlug(slug) {
1047
+ return await this.get({ slug });
1048
+ }
1049
+ /**
1050
+ * Get or create a relationship type by slug
1051
+ *
1052
+ * @param slug - The slug to search for
1053
+ * @param defaults - Default values if creating
1054
+ * @returns ProfileRelationshipType instance
1055
+ */
1056
+ async getOrCreateBySlug(slug, defaults) {
1057
+ const existing = await this.getBySlug(slug);
1058
+ if (existing) return existing;
1059
+ const relationshipType = await this.create({
1060
+ slug,
1061
+ ...defaults
1062
+ });
1063
+ await relationshipType.save();
1064
+ return relationshipType;
1065
+ }
1066
+ /**
1067
+ * Get all reciprocal relationship types
1068
+ *
1069
+ * @returns Array of reciprocal ProfileRelationshipType instances
1070
+ */
1071
+ async getReciprocal() {
1072
+ return await this.list({ where: { reciprocal: true } });
1073
+ }
1074
+ /**
1075
+ * Get all directional (non-reciprocal) relationship types
1076
+ *
1077
+ * @returns Array of directional ProfileRelationshipType instances
1078
+ */
1079
+ async getDirectional() {
1080
+ return await this.list({ where: { reciprocal: false } });
1081
+ }
1082
+ };
1083
+ //#endregion
1084
+ //#region ../profiles/dist/chunks/resolveIdentity-73HQnTlT.js
1085
+ var resolveIdentity_exports = /* @__PURE__ */ __exportAll$1({
1086
+ createProfileFromNostr: () => createProfileFromNostr,
1087
+ createProfileFromOidc: () => createProfileFromOidc,
1088
+ resolveIdentity: () => resolveIdentity,
1089
+ reuseExistingOidcIdentityForProfile: () => reuseExistingOidcIdentityForProfile
1090
+ });
1091
+ async function resolveIdentity(context) {
1092
+ const options = { db: context.db };
1093
+ if (context.apiKey) {
1094
+ const apiKey = await ApiKey.verify(context.apiKey, options);
1095
+ if (apiKey) {
1096
+ const profile = await apiKey.getProfile();
1097
+ if (profile) return {
1098
+ profile,
1099
+ source: "api_key",
1100
+ apiKey
1101
+ };
1102
+ }
1103
+ }
1104
+ if (context.oidcSession?.sub && context.oidcSession?.iss) {
1105
+ const oidcIdentity = await OidcIdentity.findBySubject(context.oidcSession.iss, context.oidcSession.sub, options);
1106
+ if (oidcIdentity) {
1107
+ await oidcIdentity.recordUsage();
1108
+ const profile = await oidcIdentity.getProfile();
1109
+ if (profile) return {
1110
+ profile,
1111
+ source: "oidc",
1112
+ oidcIdentity
1113
+ };
1114
+ }
1115
+ }
1116
+ if (context.nostrAuth?.event && context.nostrAuth?.challenge) {
1117
+ const { event, challenge } = context.nostrAuth;
1118
+ if (verifyAuthEvent(event, challenge).valid) {
1119
+ const nostrIdentity = await NostrIdentity.findByPubkey(event.pubkey, options);
1120
+ if (nostrIdentity) {
1121
+ await nostrIdentity.recordUsage();
1122
+ const profile = await nostrIdentity.getProfile();
1123
+ if (profile) return {
1124
+ profile,
1125
+ source: "nostr",
1126
+ nostrIdentity
1127
+ };
1128
+ }
1129
+ }
1130
+ }
1131
+ if (context.actor) {
1132
+ const profile = await findProfileByExternalId("github", context.actor, options);
1133
+ if (profile) return {
1134
+ profile,
1135
+ source: "actor"
1136
+ };
1137
+ }
1138
+ return {
1139
+ profile: null,
1140
+ source: "none"
1141
+ };
1142
+ }
1143
+ async function findProfileByExternalId(provider, externalId, options) {
1144
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-D3L0WYbM-BOje5aiS.js").then((n) => n.r);
1145
+ const identities = await (await OidcIdentityCollection.create(options)).findByProvider(provider);
1146
+ for (const identity of identities) if (identity.subject === externalId || identity.email?.includes(externalId)) {
1147
+ const profile = await identity.getProfile();
1148
+ if (profile) return profile;
1149
+ }
1150
+ const { ProfileCollection } = await import("./ProfileCollection-BvhD2cfL-P9hC9GcP.js").then((n) => n.r).then((n) => n.r);
1151
+ const profiles = await (await ProfileCollection.create(options)).list({
1152
+ where: { email: `${externalId}@users.noreply.github.com` },
1153
+ limit: 1
1154
+ });
1155
+ if (profiles.length > 0) return profiles[0];
1156
+ return null;
1157
+ }
1158
+ async function createProfileFromOidc(claims, provider, options) {
1159
+ return coordinateProfileOidcProvisioning(claims, provider, options);
1160
+ }
1161
+ async function reuseExistingOidcIdentityForProfile(profileId, claims, provider, options) {
1162
+ const normalizedClaims = normalizeOidcProfileClaims(claims);
1163
+ return coordinateOidcProvisioning({
1164
+ db: await resolveOidcProfileDatabase(options.db),
1165
+ lockKeys: [`identity:${OidcIdentity.buildIdentityKey(normalizedClaims.iss, normalizedClaims.sub)}`],
1166
+ isRaceConflict: isOidcProvisioningRaceConflict,
1167
+ createTransactionError: (message, cause) => new Error(message, cause === void 0 ? void 0 : { cause }),
1168
+ createConcurrencyError: (cause) => new Error("Concurrent exact OIDC identity reuse did not converge.", cause === void 0 ? void 0 : { cause }),
1169
+ rebindRootResult: rebindOidcProfileResult,
1170
+ provision: (tx) => withSystemContext(async () => {
1171
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-D3L0WYbM-BOje5aiS.js").then((n) => n.r);
1172
+ const identity = await (await OidcIdentityCollection.create({ db: tx })).findBySubject(normalizedClaims.iss, normalizedClaims.sub);
1173
+ if (!identity) throw new Error("OidcIdentity.findOrCreate() no longer creates authentication links; use UserCollection.getOrCreateFromOidc() or createProfileFromOidc().");
1174
+ if (identity.profileId !== profileId) throw new Error(`OIDC identity ${normalizedClaims.iss} subject ${normalizedClaims.sub} belongs to a different Profile.`);
1175
+ const profile = await identity.getProfile();
1176
+ if (!profile) throw new Error("The exact OIDC identity has no linked Profile.");
1177
+ identity.provider = provider;
1178
+ if (normalizedClaims.email) identity.email = normalizedClaims.email;
1179
+ identity.lastUsedAt = /* @__PURE__ */ new Date();
1180
+ await identity.save();
1181
+ return {
1182
+ profile,
1183
+ oidcIdentity: identity,
1184
+ created: false
1185
+ };
1186
+ })
1187
+ });
1188
+ }
1189
+ async function coordinateProfileOidcProvisioning(claims, provider, options) {
1190
+ const normalizedClaims = normalizeOidcProfileClaims(claims);
1191
+ return coordinateOidcProvisioning({
1192
+ db: await resolveOidcProfileDatabase(options.db),
1193
+ lockKeys: [`identity:${OidcIdentity.buildIdentityKey(normalizedClaims.iss, normalizedClaims.sub)}`, ...normalizedClaims.email ? [`email:${normalizedClaims.email}`] : []],
1194
+ isRaceConflict: isOidcProvisioningRaceConflict,
1195
+ createTransactionError: (message, cause) => new Error(message, cause === void 0 ? void 0 : { cause }),
1196
+ createConcurrencyError: (cause) => new Error("Concurrent OIDC Profile provisioning did not converge.", cause === void 0 ? void 0 : { cause }),
1197
+ rebindRootResult: rebindOidcProfileResult,
1198
+ provision: (tx) => withSystemContext(() => provisionOidcProfile(normalizedClaims, provider, {
1199
+ ...options,
1200
+ db: tx
1201
+ }))
1202
+ });
1203
+ }
1204
+ async function provisionOidcProfile(claims, provider, options) {
1205
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-D3L0WYbM-BOje5aiS.js").then((n) => n.r);
1206
+ const existingIdentity = await (await OidcIdentityCollection.create(options)).findBySubject(claims.iss, claims.sub);
1207
+ if (existingIdentity) {
1208
+ const profile2 = await existingIdentity.getProfile();
1209
+ if (!profile2) throw new Error("The exact OIDC identity has no linked Profile.");
1210
+ profile2.id = requireOidcProfileId(existingIdentity.profileId);
1211
+ if (claims.email) existingIdentity.email = claims.email;
1212
+ existingIdentity.lastUsedAt = /* @__PURE__ */ new Date();
1213
+ await existingIdentity.save();
1214
+ return {
1215
+ profile: profile2,
1216
+ oidcIdentity: existingIdentity,
1217
+ created: false
1218
+ };
1219
+ }
1220
+ const { ProfileCollection } = await import("./ProfileCollection-BvhD2cfL-P9hC9GcP.js").then((n) => n.r).then((n) => n.r);
1221
+ const profileCollection = await ProfileCollection.create(options);
1222
+ if (claims.email) {
1223
+ if (await profileCollection.findUniqueGlobalPersonByEmail(claims.email)) {
1224
+ if (claims.email_verified !== true) throw new Error(`OIDC email ${claims.email} is not verified and already belongs to a Profile.`);
1225
+ throw new Error(`OIDC email ${claims.email} already belongs to a Profile; createProfileFromOidc() cannot prove that Profile is unowned. Use UserCollection.getOrCreateFromOidc() for owner-aware linking.`);
1226
+ }
1227
+ }
1228
+ const profile = await createOidcProvisioningPerson(options.db, {
1229
+ email: claims.email ?? "",
1230
+ name: claims.name,
1231
+ preferredUsername: claims.preferred_username,
1232
+ subject: claims.sub
1233
+ });
1234
+ return {
1235
+ profile,
1236
+ oidcIdentity: await insertOidcProvisioningIdentity(options.db, {
1237
+ email: claims.email,
1238
+ issuer: claims.iss,
1239
+ profileId: requireOidcProfileId(profile.id),
1240
+ provider,
1241
+ subject: claims.sub
1242
+ }),
1243
+ created: true
1244
+ };
1245
+ }
1246
+ async function rebindOidcProfileResult(result, rootDb) {
1247
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-D3L0WYbM-BOje5aiS.js").then((n) => n.r);
1248
+ const { ProfileCollection } = await import("./ProfileCollection-BvhD2cfL-P9hC9GcP.js").then((n) => n.r).then((n) => n.r);
1249
+ const profileId = requireOidcProfileId(result.profile.id);
1250
+ const identityId = requireOidcProfileId(result.oidcIdentity.id);
1251
+ const [profile, oidcIdentity] = await withSystemContext(async () => {
1252
+ const profiles = await ProfileCollection.create({ db: rootDb });
1253
+ const identities = await OidcIdentityCollection.create({ db: rootDb });
1254
+ return [await profiles.get({ id: profileId }), await identities.get({ id: identityId })];
1255
+ });
1256
+ if (!profile || !oidcIdentity) throw new Error("Committed OIDC Profile provisioning result was not found.");
1257
+ profile.id = profileId;
1258
+ oidcIdentity.id = identityId;
1259
+ oidcIdentity.profileId = profileId;
1260
+ return {
1261
+ ...result,
1262
+ profile,
1263
+ oidcIdentity
1264
+ };
1265
+ }
1266
+ function normalizeOidcProfileClaims(claims) {
1267
+ const sub = claims?.sub;
1268
+ const iss = claims?.iss;
1269
+ if (typeof sub !== "string" || sub.trim().length === 0 || typeof iss !== "string" || iss.trim().length === 0) throw new Error("Invalid OIDC claims: both \"sub\" and \"iss\" must be non-empty strings.");
1270
+ const suppliedEmail = claims.email;
1271
+ return {
1272
+ ...claims,
1273
+ sub,
1274
+ iss,
1275
+ email: typeof suppliedEmail === "string" && suppliedEmail.trim() ? normalizeIdentityEmail(suppliedEmail) : void 0
1276
+ };
1277
+ }
1278
+ function requireOidcProfileId(value) {
1279
+ if (typeof value !== "string" || !value) throw new Error("OIDC Profile provisioning did not produce an id.");
1280
+ return value;
1281
+ }
1282
+ async function resolveOidcProfileDatabase(db) {
1283
+ if (!db) throw new Error("OIDC Profile provisioning requires an initialized database.");
1284
+ return resolveDatabase(db);
1285
+ }
1286
+ async function createProfileFromNostr(email, nostrData, options) {
1287
+ const normalizedEmail = normalizeIdentityEmail(email);
1288
+ const existingIdentity = await NostrIdentity.findByEmail(normalizedEmail, options);
1289
+ if (existingIdentity) {
1290
+ const profile2 = await existingIdentity.getProfile();
1291
+ if (profile2) return {
1292
+ profile: profile2,
1293
+ nostrIdentity: existingIdentity,
1294
+ created: false
1295
+ };
1296
+ }
1297
+ const { Person } = await import("./oidcProvisioningPrimitives-CjOkg3Zd-BtqRL7sX.js").then((n) => n.r).then((n) => n.o);
1298
+ const { ProfileTypeCollection } = await import("./oidcProvisioningPrimitives-CjOkg3Zd-BtqRL7sX.js").then((n) => n.r).then((n) => n.c);
1299
+ let personType = await (await ProfileTypeCollection.create(options)).getBySlug("person");
1300
+ if (!personType) {
1301
+ const { ProfileType } = await import("./ProfileCollection-BvhD2cfL-P9hC9GcP.js").then((n) => n.r).then((n) => n.h);
1302
+ personType = new ProfileType({
1303
+ ...options,
1304
+ slug: "person",
1305
+ name: "Person",
1306
+ description: "Individual person profile"
1307
+ });
1308
+ await personType.initialize();
1309
+ await personType.save();
1310
+ }
1311
+ const profile = new Person({
1312
+ ...options,
1313
+ typeId: personType.id,
1314
+ email: normalizedEmail,
1315
+ name: normalizedEmail.split("@")[0]
1316
+ });
1317
+ await profile.initialize();
1318
+ await profile.save();
1319
+ const nostrIdentity = new NostrIdentity({
1320
+ ...options,
1321
+ profileId: profile.id,
1322
+ pubkey: nostrData.pubkey,
1323
+ encryptedPrivkey: nostrData.encryptedPrivkey,
1324
+ encryptionIv: nostrData.encryptionIv,
1325
+ encryptionTag: nostrData.encryptionTag,
1326
+ email: normalizedEmail,
1327
+ nip05Username: nostrData.nip05Username?.toLowerCase() || normalizedEmail.split("@")[0]
1328
+ });
1329
+ await nostrIdentity.initialize();
1330
+ await nostrIdentity.save();
1331
+ return {
1332
+ profile,
1333
+ nostrIdentity,
1334
+ created: true
1335
+ };
1336
+ }
1337
+ //#endregion
1338
+ //#region ../profiles/dist/index.js
1339
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-profiles\",\"packageVersion\":\"0.51.17\",\"objects\":{\"@happyvertical/smrt-profiles:ApiKeyCollection\":{\"name\":\"apikeycollection\",\"className\":\"ApiKeyCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ApiKeyCollection\",\"collection\":\"apikeys\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ApiKeyCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"findByProfile\":{\"name\":\"findByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"findActiveByProfile\":{\"name\":\"findActiveByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"findByHash\":{\"name\":\"findByHash\",\"async\":true,\"parameters\":[{\"name\":\"keyHash\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ApiKey | null>\",\"isStatic\":false,\"isPublic\":true},\"verify\":{\"name\":\"verify\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ApiKey | null>\",\"isStatic\":false,\"isPublic\":true},\"generateForProfile\":{\"name\":\"generateForProfile\",\"async\":true,\"parameters\":[{\"name\":\"profile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string[]\",\"Date | null\"]}],\"returnType\":\"Promise<GenerateKeyResult>\",\"isStatic\":false,\"isPublic\":true},\"revokeAllForProfile\":{\"name\":\"revokeAllForProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"revokeByPrefix\":{\"name\":\"revokeByPrefix\",\"async\":true,\"parameters\":[{\"name\":\"keyPrefix\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"cleanupExpired\":{\"name\":\"cleanupExpired\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"api_keys\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ApiKey\",\"exportName\":\"ApiKeyCollection\",\"collectionExportName\":\"ApiKeyCollectionCollection\",\"schema\":{\"tableName\":\"api_keys\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"api_keys\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"key_hash\\\" TEXT DEFAULT '',\\n \\\"key_prefix\\\" TEXT DEFAULT '',\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"scopes\\\" JSON DEFAULT '[]',\\n \\\"last_used_at\\\" TIMESTAMP,\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"revoked_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"key_hash\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"key_prefix\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"scopes\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":[]},\"last_used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"revoked_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"api_keys_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"api_keys_key_hash_idx\",\"columns\":[\"key_hash\"]},{\"name\":\"api_keys_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"api_keys_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"9b0d49e8\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:AuditLogCollection\":{\"name\":\"auditlogcollection\",\"className\":\"AuditLogCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:AuditLogCollection\",\"collection\":\"auditlogs\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/AuditLogCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"findByProfile\":{\"name\":\"findByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"findByResource\":{\"name\":\"findByResource\",\"async\":true,\"parameters\":[{\"name\":\"resourceType\",\"type\":\"string\",\"optional\":false},{\"name\":\"resourceId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"findByAction\":{\"name\":\"findByAction\",\"async\":true,\"parameters\":[{\"name\":\"action\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySource\":{\"name\":\"findBySource\",\"async\":true,\"parameters\":[{\"name\":\"source\",\"type\":\"AuditSource\",\"optional\":false}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"findOnBehalfOf\":{\"name\":\"findOnBehalfOf\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"record\":{\"name\":\"record\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"Profile\",\"string\",\"AuditSource\",\"Record<string, unknown>\",\"Profile | null\"]}],\"returnType\":\"Promise<AuditLog>\",\"isStatic\":false,\"isPublic\":true},\"getRecentActivity\":{\"name\":\"getRecentActivity\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"limit\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"getResourceTimeline\":{\"name\":\"getResourceTimeline\",\"async\":true,\"parameters\":[{\"name\":\"resourceType\",\"type\":\"string\",\"optional\":false},{\"name\":\"resourceId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"audit_logs\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"AuditLog\",\"exportName\":\"AuditLogCollection\",\"collectionExportName\":\"AuditLogCollectionCollection\",\"schema\":{\"tableName\":\"audit_logs\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"audit_logs\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"action\\\" TEXT DEFAULT '',\\n \\\"resource_type\\\" TEXT DEFAULT '',\\n \\\"resource_id\\\" TEXT DEFAULT '',\\n \\\"source\\\" TEXT DEFAULT 'web',\\n \\\"metadata\\\" JSON DEFAULT '{}',\\n \\\"on_behalf_of_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"action\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"resource_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"resource_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"source\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"web\"},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":{}},\"on_behalf_of_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"audit_logs_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"audit_logs_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"audit_logs_profile_id_idx\",\"columns\":[\"profile_id\"]},{\"name\":\"audit_logs_on_behalf_of_id_idx\",\"columns\":[\"on_behalf_of_id\"]}],\"version\":\"d2b35971\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:MagicLinkTokenCollection\":{\"name\":\"magiclinktokencollection\",\"className\":\"MagicLinkTokenCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:MagicLinkTokenCollection\",\"collection\":\"magiclinktokens\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/MagicLinkTokenCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"findByTokenHash\":{\"name\":\"findByTokenHash\",\"async\":true,\"parameters\":[{\"name\":\"tokenHash\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MagicLinkToken | null>\",\"isStatic\":false,\"isPublic\":true},\"findActiveForEmail\":{\"name\":\"findActiveForEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MagicLinkToken[]>\",\"isStatic\":false,\"isPublic\":true},\"findByIdentity\":{\"name\":\"findByIdentity\",\"async\":true,\"parameters\":[{\"name\":\"nostrIdentityId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MagicLinkToken[]>\",\"isStatic\":false,\"isPublic\":true},\"countRecentByEmail\":{\"name\":\"countRecentByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false},{\"name\":\"withinMinutes\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"countRecentByIp\":{\"name\":\"countRecentByIp\",\"async\":true,\"parameters\":[{\"name\":\"ip\",\"type\":\"string\",\"optional\":false},{\"name\":\"withinMinutes\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"verify\":{\"name\":\"verify\",\"async\":true,\"parameters\":[{\"name\":\"token\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MagicLinkToken | null>\",\"isStatic\":false,\"isPublic\":true},\"cleanupExpired\":{\"name\":\"cleanupExpired\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"revokeForIdentity\":{\"name\":\"revokeForIdentity\",\"async\":true,\"parameters\":[{\"name\":\"nostrIdentityId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"isRateLimitedByEmail\":{\"name\":\"isRateLimitedByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false},{\"name\":\"maxPerHour\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isRateLimitedByIp\":{\"name\":\"isRateLimitedByIp\",\"async\":true,\"parameters\":[{\"name\":\"ip\",\"type\":\"string\",\"optional\":false},{\"name\":\"maxPerHour\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"magic_link_tokens\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"MagicLinkToken\",\"exportName\":\"MagicLinkTokenCollection\",\"collectionExportName\":\"MagicLinkTokenCollectionCollection\",\"schema\":{\"tableName\":\"magic_link_tokens\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"magic_link_tokens\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"nostr_identity_id\\\" UUID NOT NULL,\\n \\\"token_hash\\\" TEXT DEFAULT '',\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"used_at\\\" TIMESTAMP,\\n \\\"requested_from_ip\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"nostr_identity_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"nostr_identities\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"token_hash\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"requested_from_ip\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"magic_link_tokens_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"magic_link_tokens_token_hash_idx\",\"columns\":[\"token_hash\"]},{\"name\":\"magic_link_tokens_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"magic_link_tokens_nostr_identity_id_idx\",\"columns\":[\"nostr_identity_id\"]}],\"version\":\"d60748fe\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:NostrIdentityCollection\":{\"name\":\"nostridentitycollection\",\"className\":\"NostrIdentityCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:NostrIdentityCollection\",\"collection\":\"nostridentities\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/NostrIdentityCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"findByProfile\":{\"name\":\"findByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<NostrIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"findByPubkey\":{\"name\":\"findByPubkey\",\"async\":true,\"parameters\":[{\"name\":\"pubkey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":false,\"isPublic\":true},\"findByEmail\":{\"name\":\"findByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":false,\"isPublic\":true},\"findByNip05\":{\"name\":\"findByNip05\",\"async\":true,\"parameters\":[{\"name\":\"username\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":false,\"isPublic\":true},\"createForProfile\":{\"name\":\"createForProfile\",\"async\":true,\"parameters\":[{\"name\":\"profile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"email\",\"type\":\"string\",\"optional\":false},{\"name\":\"masterSecret\",\"type\":\"string\",\"optional\":false},{\"name\":\"nip05Username\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true},\"linkToProfile\":{\"name\":\"linkToProfile\",\"async\":true,\"parameters\":[{\"name\":\"profile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"nostrData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true},\"unlinkFromProfile\":{\"name\":\"unlinkFromProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"pubkey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getNip05Response\":{\"name\":\"getNip05Response\",\"async\":true,\"parameters\":[{\"name\":\"username\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Nip05Response>\",\"isStatic\":false,\"isPublic\":true},\"isNip05Available\":{\"name\":\"isNip05Available\",\"async\":true,\"parameters\":[{\"name\":\"username\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"updateNip05Username\":{\"name\":\"updateNip05Username\",\"async\":true,\"parameters\":[{\"name\":\"identity\",\"type\":\"NostrIdentity\",\"optional\":false},{\"name\":\"newUsername\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"nostr_identities\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"NostrIdentity\",\"exportName\":\"NostrIdentityCollection\",\"collectionExportName\":\"NostrIdentityCollectionCollection\",\"schema\":{\"tableName\":\"nostr_identities\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"nostr_identities\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"pubkey\\\" TEXT DEFAULT '',\\n \\\"encrypted_privkey\\\" TEXT DEFAULT '',\\n \\\"encryption_iv\\\" TEXT DEFAULT '',\\n \\\"encryption_tag\\\" TEXT DEFAULT '',\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"nip05_username\\\" TEXT DEFAULT '',\\n \\\"last_used_at\\\" TIMESTAMP,\\n \\\"verified_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"pubkey\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"encrypted_privkey\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"encryption_iv\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"encryption_tag\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"nip05_username\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"last_used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"verified_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"nostr_identities_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"nostr_identities_pubkey_idx\",\"columns\":[\"pubkey\"]},{\"name\":\"nostr_identities_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"nostr_identities_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"92eda375\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:OidcIdentityCollection\":{\"name\":\"oidcidentitycollection\",\"className\":\"OidcIdentityCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:OidcIdentityCollection\",\"collection\":\"oidcidentities\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/OidcIdentityCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"findByProfile\":{\"name\":\"findByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<OidcIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySubject\":{\"name\":\"findBySubject\",\"async\":true,\"parameters\":[{\"name\":\"issuer\",\"type\":\"string\",\"optional\":false},{\"name\":\"subject\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<OidcIdentity | null>\",\"isStatic\":false,\"isPublic\":true},\"findByProvider\":{\"name\":\"findByProvider\",\"async\":true,\"parameters\":[{\"name\":\"provider\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<OidcIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkToProfile\":{\"name\":\"linkToProfile\",\"async\":true,\"parameters\":[{\"name\":\"profile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"oidcData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<OidcIdentity>\",\"isStatic\":false,\"isPublic\":true},\"unlinkFromProfile\":{\"name\":\"unlinkFromProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"issuer\",\"type\":\"string\",\"optional\":false},{\"name\":\"subject\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"oidc_identities\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"OidcIdentity\",\"exportName\":\"OidcIdentityCollection\",\"collectionExportName\":\"OidcIdentityCollectionCollection\",\"schema\":{\"tableName\":\"oidc_identities\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oidc_identities\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"provider\\\" TEXT,\\n \\\"issuer\\\" TEXT,\\n \\\"subject\\\" TEXT,\\n \\\"identity_key\\\" TEXT UNIQUE,\\n \\\"email\\\" TEXT,\\n \\\"last_used_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"provider\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"issuer\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"subject\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"identity_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":true},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"oidc_identities_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"oidc_identities_issuer_idx\",\"columns\":[\"issuer\"]},{\"name\":\"oidc_identities_subject_idx\",\"columns\":[\"subject\"]},{\"name\":\"oidc_identities_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"oidc_identities_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"925387ea\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:OidcProfileEmailReservationCollection\":{\"name\":\"oidcprofileemailreservationcollection\",\"className\":\"OidcProfileEmailReservationCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:OidcProfileEmailReservationCollection\",\"collection\":\"oidcprofileemailreservations\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/OidcProfileEmailReservationCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"oidc_profile_email_reservations\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"OidcProfileEmailReservation\",\"exportName\":\"OidcProfileEmailReservationCollection\",\"collectionExportName\":\"OidcProfileEmailReservationCollectionCollection\",\"schema\":{\"tableName\":\"oidc_profile_email_reservations\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oidc_profile_email_reservations\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL UNIQUE,\\n \\\"email_key\\\" TEXT NOT NULL UNIQUE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":true,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email_key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true}},\"indexes\":[{\"name\":\"oidc_profile_email_reservations_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"oidc_profile_email_reservations_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"01586e67\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileAssetCollection\":{\"name\":\"profileassetcollection\",\"className\":\"ProfileAssetCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileAssetCollection\",\"collection\":\"profileassets\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileAssetCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"byLeft\":{\"name\":\"byLeft\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"byRight\":{\"name\":\"byRight\",\"async\":true,\"parameters\":[{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"attach\":{\"name\":\"attach\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem>\",\"isStatic\":false,\"isPublic\":true},\"detach\":{\"name\":\"detach\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"setLinks\":{\"name\":\"setLinks\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":false,\"mcp\":false,\"cli\":false,\"tableName\":\"profile_assets\"},\"extends\":\"SmrtJunction\",\"extendsTypeArg\":\"ProfileAsset\",\"exportName\":\"ProfileAssetCollection\",\"collectionExportName\":\"ProfileAssetCollectionCollection\",\"schema\":{\"tableName\":\"profile_assets\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_assets\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"asset_id\\\" UUID NOT NULL,\\n \\\"relationship\\\" TEXT NOT NULL,\\n \\\"sort_order\\\" INTEGER NOT NULL DEFAULT 0\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":true,\"unique\":false},\"relationship\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"sort_order\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0}},\"indexes\":[{\"name\":\"profile_assets_profile_id_asset_id_idx\",\"columns\":[\"profile_id\",\"asset_id\",\"relationship\"],\"unique\":true},{\"name\":\"profile_assets_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"profile_assets_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profile_assets_asset_id_idx\",\"columns\":[\"asset_id\"]}],\"version\":\"d0d7c2a2\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileCollection\":{\"name\":\"profilecollection\",\"className\":\"ProfileCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileCollection\",\"collection\":\"profiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"findByEmail\":{\"name\":\"findByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"findUniqueGlobalPersonByEmail\":{\"name\":\"findUniqueGlobalPersonByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"requireCanonicalGlobalPerson\":{\"name\":\"requireCanonicalGlobalPerson\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"email\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile>\",\"isStatic\":false,\"isPublic\":true},\"reserveCanonicalIdentityEmail\":{\"name\":\"reserveCanonicalIdentityEmail\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"email\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile>\",\"isStatic\":false,\"isPublic\":true},\"findByType\":{\"name\":\"findByType\",\"async\":true,\"parameters\":[{\"name\":\"typeSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"batchGetMetadata\":{\"name\":\"batchGetMetadata\",\"async\":true,\"parameters\":[{\"name\":\"profileIds\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<Map<string, Record<string, string>>>\",\"isStatic\":false,\"isPublic\":true},\"batchUpdateMetadata\":{\"name\":\"batchUpdateMetadata\",\"async\":true,\"parameters\":[{\"name\":\"updates\",\"type\":\"Array<object>\",\"optional\":false,\"memberTypes\":[\"string\",\"Record<string, unknown>\"]}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"findRelated\":{\"name\":\"findRelated\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRelationshipNetwork\":{\"name\":\"getRelationshipNetwork\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\"]}],\"returnType\":\"Promise<Map<string, number>>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Profile\",\"exportName\":\"ProfileCollection\",\"collectionExportName\":\"ProfileCollectionCollection\",\"schema\":{\"tableName\":\"profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"email\\\" TEXT,\\n \\\"email_key\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email\":{\"type\":\"TEXT\",\"notNull\":false},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profiles_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profiles_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profiles_email_key_idx\",\"columns\":[\"email_key\"]},{\"name\":\"profiles_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profiles_type_id_idx\",\"columns\":[\"type_id\"]}],\"version\":\"fd4497fb\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileMetadataCollection\":{\"name\":\"profilemetadatacollection\",\"className\":\"ProfileMetadataCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileMetadataCollection\",\"collection\":\"profilemetadatas\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileMetadataCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"getByProfile\":{\"name\":\"getByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileMetadata[]>\",\"isStatic\":false,\"isPublic\":true},\"getMetadataObject\":{\"name\":\"getMetadataObject\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Record<string, string>>\",\"isStatic\":false,\"isPublic\":true},\"findProfilesByMetadata\":{\"name\":\"findProfilesByMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldId\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ProfileMetadata\",\"exportName\":\"ProfileMetadataCollection\",\"collectionExportName\":\"ProfileMetadataCollectionCollection\",\"schema\":{\"tableName\":\"profile_metadata\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_metadata\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"profile_id\\\" UUID,\\n \\\"metafield_id\\\" UUID,\\n \\\"value\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"metafield_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_metafields\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"value\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"profile_metadata_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_metadata_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_metadata_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profile_metadata_profile_id_idx\",\"columns\":[\"profile_id\"]},{\"name\":\"profile_metadata_metafield_id_idx\",\"columns\":[\"metafield_id\"]}],\"version\":\"d3ab1b70\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileMetafieldCollection\":{\"name\":\"profilemetafieldcollection\",\"className\":\"ProfileMetafieldCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileMetafieldCollection\",\"collection\":\"profilemetafields\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileMetafieldCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileMetafield | null>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreateBySlug\":{\"name\":\"getOrCreateBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"defaults\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"ValidationSchema\"]}],\"returnType\":\"Promise<ProfileMetafield>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ProfileMetafield\",\"exportName\":\"ProfileMetafieldCollection\",\"collectionExportName\":\"ProfileMetafieldCollectionCollection\",\"schema\":{\"tableName\":\"profile_metafields\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_metafields\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT,\\n \\\"validation\\\" JSON\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"validation\":{\"type\":\"JSON\",\"notNull\":false}},\"indexes\":[{\"name\":\"profile_metafields_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_metafields_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_metafields_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"afe420df\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileRelationshipCollection\":{\"name\":\"profilerelationshipcollection\",\"className\":\"ProfileRelationshipCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileRelationshipCollection\",\"collection\":\"profilerelationships\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileRelationshipCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"getFromProfile\":{\"name\":\"getFromProfile\",\"async\":true,\"parameters\":[{\"name\":\"fromProfileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"typeId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"getToProfile\":{\"name\":\"getToProfile\",\"async\":true,\"parameters\":[{\"name\":\"toProfileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"typeId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"getForProfile\":{\"name\":\"getForProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"typeId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"exists\":{\"name\":\"exists\",\"async\":true,\"parameters\":[{\"name\":\"fromProfileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"toProfileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"typeId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ProfileRelationship\",\"exportName\":\"ProfileRelationshipCollection\",\"collectionExportName\":\"ProfileRelationshipCollectionCollection\",\"schema\":{\"tableName\":\"profile_relationships\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_relationships\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"from_profile_id\\\" UUID,\\n \\\"to_profile_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"context_profile_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"from_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"to_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_relationship_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"context_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"profile_relationships_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_relationships_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_relationships_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profile_relationships_from_profile_id_idx\",\"columns\":[\"from_profile_id\"]},{\"name\":\"profile_relationships_to_profile_id_idx\",\"columns\":[\"to_profile_id\"]},{\"name\":\"profile_relationships_type_id_idx\",\"columns\":[\"type_id\"]},{\"name\":\"profile_relationships_context_profile_id_idx\",\"columns\":[\"context_profile_id\"]}],\"version\":\"48878dba\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileRelationshipTermCollection\":{\"name\":\"profilerelationshiptermcollection\",\"className\":\"ProfileRelationshipTermCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileRelationshipTermCollection\",\"collection\":\"profilerelationshipterms\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileRelationshipTermCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"getByRelationship\":{\"name\":\"getByRelationship\",\"async\":true,\"parameters\":[{\"name\":\"relationshipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileRelationshipTerm[]>\",\"isStatic\":false,\"isPublic\":true},\"getActiveTerm\":{\"name\":\"getActiveTerm\",\"async\":true,\"parameters\":[{\"name\":\"relationshipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileRelationshipTerm | null>\",\"isStatic\":false,\"isPublic\":true},\"getHistoricalTerms\":{\"name\":\"getHistoricalTerms\",\"async\":true,\"parameters\":[{\"name\":\"relationshipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileRelationshipTerm[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ProfileRelationshipTerm\",\"exportName\":\"ProfileRelationshipTermCollection\",\"collectionExportName\":\"ProfileRelationshipTermCollectionCollection\",\"schema\":{\"tableName\":\"profile_relationship_terms\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_relationship_terms\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"relationship_id\\\" UUID,\\n \\\"started_at\\\" TIMESTAMP,\\n \\\"ended_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"relationship_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_relationships\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"started_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"ended_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"profile_relationship_terms_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"profile_relationship_terms_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_relationship_terms_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"profile_relationship_terms_relationship_id_idx\",\"columns\":[\"relationship_id\"]}],\"version\":\"ef299102\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileRelationshipTypeCollection\":{\"name\":\"profilerelationshiptypecollection\",\"className\":\"ProfileRelationshipTypeCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileRelationshipTypeCollection\",\"collection\":\"profilerelationshiptypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileRelationshipTypeCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileRelationshipType | null>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreateBySlug\":{\"name\":\"getOrCreateBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"defaults\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"boolean\"]}],\"returnType\":\"Promise<ProfileRelationshipType>\",\"isStatic\":false,\"isPublic\":true},\"getReciprocal\":{\"name\":\"getReciprocal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ProfileRelationshipType[]>\",\"isStatic\":false,\"isPublic\":true},\"getDirectional\":{\"name\":\"getDirectional\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ProfileRelationshipType[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ProfileRelationshipType\",\"exportName\":\"ProfileRelationshipTypeCollection\",\"collectionExportName\":\"ProfileRelationshipTypeCollectionCollection\",\"schema\":{\"tableName\":\"profile_relationship_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_relationship_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"reciprocal\\\" BOOLEAN DEFAULT TRUE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"reciprocal\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true}},\"indexes\":[{\"name\":\"profile_relationship_types_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"profile_relationship_types_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_relationship_types_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"719fe0d9\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileTypeCollection\":{\"name\":\"profiletypecollection\",\"className\":\"ProfileTypeCollection\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileTypeCollection\",\"collection\":\"profiletypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/collections/ProfileTypeCollection.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileType | null>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreateBySlug\":{\"name\":\"getOrCreateBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"defaults\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<ProfileType>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreateGlobalBySlug\":{\"name\":\"getOrCreateGlobalBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"defaults\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<ProfileType>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ProfileType\",\"exportName\":\"ProfileTypeCollection\",\"collectionExportName\":\"ProfileTypeCollectionCollection\",\"schema\":{\"tableName\":\"profile_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profile_types_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_types_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_types_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"0fb37aeb\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ApiKey\":{\"name\":\"apikey\",\"className\":\"ApiKey\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ApiKey\",\"collection\":\"apikeys\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ApiKey.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"keyHash\":{\"type\":\"text\",\"required\":false,\"default\":\"\",\"_meta\":{\"indexed\":true}},\"keyPrefix\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"scopes\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"lastUsedAt\":{\"type\":\"datetime\",\"required\":false},\"expiresAt\":{\"type\":\"datetime\",\"required\":false},\"revokedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getProfile\":{\"name\":\"getProfile\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"isValid\":{\"name\":\"isValid\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"hasScope\":{\"name\":\"hasScope\",\"async\":false,\"parameters\":[{\"name\":\"scope\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"revoke\":{\"name\":\"revoke\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recordUsage\":{\"name\":\"recordUsage\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"hashKey\":{\"name\":\"hashKey\",\"async\":false,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"generate\":{\"name\":\"generate\",\"async\":true,\"parameters\":[{\"name\":\"profile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"typeUnresolved\":true,\"memberTypes\":[\"string\",\"string[]\",\"Date | null\"]}],\"returnType\":\"Promise<GenerateKeyResult>\",\"isStatic\":true,\"isPublic\":true},\"verify\":{\"name\":\"verify\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<ApiKey | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"api_keys\",\"sensitive\":true,\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"include\":[\"list\",\"get\",\"create\",\"revoke\"],\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"ApiKey\",\"collectionExportName\":\"ApiKeyCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"api_keys\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"api_keys\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"key_hash\\\" TEXT DEFAULT '',\\n \\\"key_prefix\\\" TEXT DEFAULT '',\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"scopes\\\" JSON DEFAULT '[]',\\n \\\"last_used_at\\\" TIMESTAMP,\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"revoked_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"key_hash\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"key_prefix\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"scopes\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":[]},\"last_used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"revoked_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"api_keys_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"api_keys_key_hash_idx\",\"columns\":[\"key_hash\"]},{\"name\":\"api_keys_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"api_keys_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"9b0d49e8\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:AuditLog\":{\"name\":\"auditlog\",\"className\":\"AuditLog\",\"qualifiedName\":\"@happyvertical/smrt-profiles:AuditLog\",\"collection\":\"auditlogs\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/AuditLog.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":true}}},\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"action\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"resourceType\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"resourceId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"source\":{\"type\":\"text\",\"required\":false,\"default\":\"web\"},\"metadata\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"onBehalfOfId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Profile\",\"_meta\":{\"nullable\":true}}},\"methods\":{\"getProfile\":{\"name\":\"getProfile\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"getOnBehalfOf\":{\"name\":\"getOnBehalfOf\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"getEffectiveActor\":{\"name\":\"getEffectiveActor\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"record\":{\"name\":\"record\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"any\",\"optional\":false,\"typeUnresolved\":true}],\"returnType\":\"Promise<AuditLog>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"audit_logs\",\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"include\":[\"list\"]},\"tenantScoped\":{\"mode\":\"optional\",\"allowSuperAdminBypass\":true},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\"]},\"extends\":\"SmrtObject\",\"exportName\":\"AuditLog\",\"collectionExportName\":\"AuditLogCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"audit_logs\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"audit_logs\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"action\\\" TEXT DEFAULT '',\\n \\\"resource_type\\\" TEXT DEFAULT '',\\n \\\"resource_id\\\" TEXT DEFAULT '',\\n \\\"source\\\" TEXT DEFAULT 'web',\\n \\\"metadata\\\" JSON DEFAULT '{}',\\n \\\"on_behalf_of_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"action\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"resource_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"resource_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"source\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"web\"},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":{}},\"on_behalf_of_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"audit_logs_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"audit_logs_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"audit_logs_profile_id_idx\",\"columns\":[\"profile_id\"]},{\"name\":\"audit_logs_on_behalf_of_id_idx\",\"columns\":[\"on_behalf_of_id\"]}],\"version\":\"d2b35971\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:MagicLinkToken\":{\"name\":\"magiclinktoken\",\"className\":\"MagicLinkToken\",\"qualifiedName\":\"@happyvertical/smrt-profiles:MagicLinkToken\",\"collection\":\"magiclinktokens\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/MagicLinkToken.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"nostrIdentityId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"NostrIdentity\",\"_meta\":{\"required\":true}},\"tokenHash\":{\"type\":\"text\",\"required\":false,\"default\":\"\",\"_meta\":{\"indexed\":true}},\"email\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"expiresAt\":{\"type\":\"datetime\",\"required\":false},\"usedAt\":{\"type\":\"datetime\",\"required\":false},\"requestedFromIp\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"createdAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"hashToken\":{\"name\":\"hashToken\",\"async\":false,\"parameters\":[{\"name\":\"token\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"generate\":{\"name\":\"generate\",\"async\":true,\"parameters\":[{\"name\":\"nostrIdentity\",\"type\":\"NostrIdentity\",\"optional\":false},{\"name\":\"email\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"typeUnresolved\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"Promise<GenerateTokenResult>\",\"isStatic\":true,\"isPublic\":true},\"verify\":{\"name\":\"verify\",\"async\":true,\"parameters\":[{\"name\":\"token\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<MagicLinkToken | null>\",\"isStatic\":true,\"isPublic\":true},\"isValid\":{\"name\":\"isValid\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isExpired\":{\"name\":\"isExpired\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isUsed\":{\"name\":\"isUsed\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"markUsed\":{\"name\":\"markUsed\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getNostrIdentity\":{\"name\":\"getNostrIdentity\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":false,\"isPublic\":true},\"getTimeRemainingSeconds\":{\"name\":\"getTimeRemainingSeconds\",\"async\":false,\"parameters\":[],\"returnType\":\"number\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"magic_link_tokens\",\"sensitive\":true,\"api\":{\"exclude\":[\"*\"]},\"mcp\":{\"exclude\":[\"*\"]},\"cli\":{\"include\":[\"list\"]}},\"extends\":\"SmrtObject\",\"exportName\":\"MagicLinkToken\",\"collectionExportName\":\"MagicLinkTokenCollection\",\"validationRules\":[{\"field\":\"nostrIdentityId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"magic_link_tokens\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"magic_link_tokens\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"nostr_identity_id\\\" UUID NOT NULL,\\n \\\"token_hash\\\" TEXT DEFAULT '',\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"used_at\\\" TIMESTAMP,\\n \\\"requested_from_ip\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"nostr_identity_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"nostr_identities\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"token_hash\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"requested_from_ip\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"magic_link_tokens_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"magic_link_tokens_token_hash_idx\",\"columns\":[\"token_hash\"]},{\"name\":\"magic_link_tokens_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"magic_link_tokens_nostr_identity_id_idx\",\"columns\":[\"nostr_identity_id\"]}],\"version\":\"d60748fe\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:NostrIdentity\":{\"name\":\"nostridentity\",\"className\":\"NostrIdentity\",\"qualifiedName\":\"@happyvertical/smrt-profiles:NostrIdentity\",\"collection\":\"nostridentities\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/NostrIdentity.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"pubkey\":{\"type\":\"text\",\"required\":false,\"default\":\"\",\"_meta\":{\"indexed\":true}},\"encryptedPrivkey\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"encryptionIv\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"encryptionTag\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"email\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"nip05Username\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"lastUsedAt\":{\"type\":\"datetime\",\"required\":false},\"verifiedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getProfile\":{\"name\":\"getProfile\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"findByPubkey\":{\"name\":\"findByPubkey\",\"async\":true,\"parameters\":[{\"name\":\"pubkey\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":true,\"isPublic\":true},\"findByEmail\":{\"name\":\"findByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":true,\"isPublic\":true},\"findByNip05\":{\"name\":\"findByNip05\",\"async\":true,\"parameters\":[{\"name\":\"username\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<NostrIdentity | null>\",\"isStatic\":true,\"isPublic\":true},\"decryptPrivkey\":{\"name\":\"decryptPrivkey\",\"async\":false,\"parameters\":[{\"name\":\"masterSecret\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true},\"getKeypair\":{\"name\":\"getKeypair\",\"async\":false,\"parameters\":[{\"name\":\"masterSecret\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"object\",\"isStatic\":false,\"isPublic\":true},\"recordUsage\":{\"name\":\"recordUsage\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"markVerified\":{\"name\":\"markVerified\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isVerified\":{\"name\":\"isVerified\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getNip05Identifier\":{\"name\":\"getNip05Identifier\",\"async\":false,\"parameters\":[{\"name\":\"domain\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"nostr_identities\",\"sensitive\":true,\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"include\":[\"list\",\"get\"]}},\"extends\":\"SmrtObject\",\"exportName\":\"NostrIdentity\",\"collectionExportName\":\"NostrIdentityCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"nostr_identities\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"nostr_identities\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"pubkey\\\" TEXT DEFAULT '',\\n \\\"encrypted_privkey\\\" TEXT DEFAULT '',\\n \\\"encryption_iv\\\" TEXT DEFAULT '',\\n \\\"encryption_tag\\\" TEXT DEFAULT '',\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"nip05_username\\\" TEXT DEFAULT '',\\n \\\"last_used_at\\\" TIMESTAMP,\\n \\\"verified_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"pubkey\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"encrypted_privkey\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"encryption_iv\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"encryption_tag\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"nip05_username\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"last_used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"verified_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"nostr_identities_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"nostr_identities_pubkey_idx\",\"columns\":[\"pubkey\"]},{\"name\":\"nostr_identities_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"nostr_identities_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"92eda375\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:OidcIdentity\":{\"name\":\"oidcidentity\",\"className\":\"OidcIdentity\",\"qualifiedName\":\"@happyvertical/smrt-profiles:OidcIdentity\",\"collection\":\"oidcidentities\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/OidcIdentity.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"provider\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"issuer\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"indexed\":true}},\"subject\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"indexed\":true}},\"identityKey\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true,\"unique\":true,\"readonly\":true},\"readonly\":true},\"email\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"lastUsedAt\":{\"type\":\"datetime\",\"required\":false,\"_meta\":{\"nullable\":true}}},\"methods\":{\"getProfile\":{\"name\":\"getProfile\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":false,\"isPublic\":true},\"findBySubject\":{\"name\":\"findBySubject\",\"async\":true,\"parameters\":[{\"name\":\"issuer\",\"type\":\"string\",\"optional\":false},{\"name\":\"subject\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<OidcIdentity | null>\",\"isStatic\":true,\"isPublic\":true},\"buildIdentityKey\":{\"name\":\"buildIdentityKey\",\"async\":false,\"parameters\":[{\"name\":\"issuer\",\"type\":\"string\",\"optional\":false},{\"name\":\"subject\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"findOrCreate\":{\"name\":\"findOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"profile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"oidcData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<OidcIdentity>\",\"isStatic\":true,\"isPublic\":true},\"recordUsage\":{\"name\":\"recordUsage\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"oidc_identities\",\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"include\":[\"list\",\"get\"]}},\"extends\":\"SmrtObject\",\"exportName\":\"OidcIdentity\",\"collectionExportName\":\"OidcIdentityCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"oidc_identities\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oidc_identities\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"provider\\\" TEXT,\\n \\\"issuer\\\" TEXT,\\n \\\"subject\\\" TEXT,\\n \\\"identity_key\\\" TEXT UNIQUE,\\n \\\"email\\\" TEXT,\\n \\\"last_used_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"provider\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"issuer\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"subject\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"identity_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":true},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_used_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"oidc_identities_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"oidc_identities_issuer_idx\",\"columns\":[\"issuer\"]},{\"name\":\"oidc_identities_subject_idx\",\"columns\":[\"subject\"]},{\"name\":\"oidc_identities_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"oidc_identities_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"925387ea\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:OidcProfileEmailReservation\":{\"name\":\"oidcprofileemailreservation\",\"className\":\"OidcProfileEmailReservation\",\"qualifiedName\":\"@happyvertical/smrt-profiles:OidcProfileEmailReservation\",\"collection\":\"oidcprofileemailreservations\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/OidcProfileEmailReservation.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true,\"unique\":true}},\"emailKey\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true,\"unique\":true,\"readonly\":true},\"readonly\":true}},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"oidc_profile_email_reservations\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtObject\",\"exportName\":\"OidcProfileEmailReservation\",\"collectionExportName\":\"OidcProfileEmailReservationCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"emailKey\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"oidc_profile_email_reservations\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oidc_profile_email_reservations\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID NOT NULL UNIQUE,\\n \\\"email_key\\\" TEXT NOT NULL UNIQUE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":true,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email_key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true}},\"indexes\":[{\"name\":\"oidc_profile_email_reservations_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"oidc_profile_email_reservations_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"01586e67\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:Profile\":{\"name\":\"profile\",\"className\":\"Profile\",\"qualifiedName\":\"@happyvertical/smrt-profiles:Profile\",\"collection\":\"profiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/Profile.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"typeId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileType\",\"_meta\":{\"required\":true}},\"email\":{\"type\":\"text\",\"required\":false},\"emailKey\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true,\"indexed\":true,\"readonly\":true},\"readonly\":true},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"description\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileMetadata\"},\"relationshipsFrom\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"fromProfileId\"}},\"relationshipsTo\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"toProfileId\"}}},\"methods\":{\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"getTypeSlug\":{\"name\":\"getTypeSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"setTypeBySlug\":{\"name\":\"setTypeBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addMetadata\":{\"name\":\"addMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string, string>>\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeMetadata\":{\"name\":\"removeMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addRelationship\":{\"name\":\"addRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"contextProfile\",\"type\":\"Profile\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRelationships\":{\"name\":\"getRelationships\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"'from' | 'to' | 'all'\"]}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelatedProfiles\":{\"name\":\"getRelatedProfiles\",\"async\":true,\"parameters\":[{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"removeRelationship\":{\"name\":\"removeRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateBio\":{\"name\":\"generateBio\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"matches\":{\"name\":\"matches\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"findByMetadata\":{\"name\":\"findByMetadata\",\"async\":true,\"parameters\":[{\"name\":\"_metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"_value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findByType\":{\"name\":\"findByType\",\"async\":true,\"parameters\":[{\"name\":\"_typeSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findRelated\":{\"name\":\"findRelated\",\"async\":true,\"parameters\":[{\"name\":\"_profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"_relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"searchByEmail\":{\"name\":\"searchByEmail\",\"async\":true,\"parameters\":[{\"name\":\"_email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":true,\"isPublic\":true},\"getApiKeys\":{\"name\":\"getApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"getActiveApiKeys\":{\"name\":\"getActiveApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"generateApiKey\":{\"name\":\"generateApiKey\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string[]\",\"Date | null\"]}],\"returnType\":\"Promise<GenerateKeyResult>\",\"isStatic\":false,\"isPublic\":true},\"getOidcIdentities\":{\"name\":\"getOidcIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<OidcIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkOidcIdentity\":{\"name\":\"linkOidcIdentity\",\"async\":true,\"parameters\":[{\"name\":\"oidcData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<OidcIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getNostrIdentities\":{\"name\":\"getNostrIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<NostrIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkNostrIdentity\":{\"name\":\"linkNostrIdentity\",\"async\":true,\"parameters\":[{\"name\":\"nostrData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getAuditLogs\":{\"name\":\"getAuditLogs\",\"async\":true,\"parameters\":[{\"name\":\"limit\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"recordAction\":{\"name\":\"recordAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"'web' | 'cli' | 'ci' | 'webhook' | 'mcp'\",\"Record<string, unknown>\",\"Profile | null\"]}],\"returnType\":\"Promise<AuditLog>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"Profile\",\"collectionExportName\":\"ProfileCollection\",\"validationRules\":[{\"field\":\"typeId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"email\\\" TEXT,\\n \\\"email_key\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email\":{\"type\":\"TEXT\",\"notNull\":false},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profiles_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profiles_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profiles_email_key_idx\",\"columns\":[\"email_key\"]},{\"name\":\"profiles_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profiles_type_id_idx\",\"columns\":[\"type_id\"]}],\"version\":\"fd4497fb\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileAsset\":{\"name\":\"profileasset\",\"className\":\"ProfileAsset\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileAsset\",\"collection\":\"profileassets\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileAsset.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"assetId\":{\"type\":\"crossPackageRef\",\"required\":true,\"related\":\"@happyvertical/smrt-assets:Asset\"},\"relationship\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"sortOrder\":{\"type\":\"integer\",\"required\":true,\"default\":0}},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"profile_assets\",\"conflictColumns\":[\"profile_id\",\"asset_id\",\"relationship\"],\"api\":false,\"mcp\":false,\"cli\":false,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileAsset\",\"collectionExportName\":\"ProfileAssetCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"assetId\",\"rule\":\"required\",\"fieldType\":\"crossPackageRef\"},{\"field\":\"relationship\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"sortOrder\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"profile_assets\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_assets\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"profile_id\\\" UUID NOT NULL,\\n \\\"asset_id\\\" UUID NOT NULL,\\n \\\"relationship\\\" TEXT NOT NULL,\\n \\\"sort_order\\\" INTEGER NOT NULL DEFAULT 0\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":true,\"unique\":false},\"relationship\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"sort_order\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0}},\"indexes\":[{\"name\":\"profile_assets_profile_id_asset_id_idx\",\"columns\":[\"profile_id\",\"asset_id\",\"relationship\"],\"unique\":true},{\"name\":\"profile_assets_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"profile_assets_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profile_assets_asset_id_idx\",\"columns\":[\"asset_id\"]}],\"version\":\"d0d7c2a2\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileMetadata\":{\"name\":\"profilemetadata\",\"className\":\"ProfileMetadata\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileMetadata\",\"collection\":\"profilemetadatas\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileMetadata.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"profileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"metafieldId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileMetafield\",\"_meta\":{\"required\":true}},\"value\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}}},\"methods\":{\"validate\":{\"name\":\"validate\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getMetafieldSlug\":{\"name\":\"getMetafieldSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileMetadata\",\"collectionExportName\":\"ProfileMetadataCollection\",\"validationRules\":[{\"field\":\"profileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"metafieldId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"value\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profile_metadata\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_metadata\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"profile_id\\\" UUID,\\n \\\"metafield_id\\\" UUID,\\n \\\"value\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"metafield_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_metafields\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"value\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"profile_metadata_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_metadata_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_metadata_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profile_metadata_profile_id_idx\",\"columns\":[\"profile_id\"]},{\"name\":\"profile_metadata_metafield_id_idx\",\"columns\":[\"metafield_id\"]}],\"version\":\"d3ab1b70\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileMetafield\":{\"name\":\"profilemetafield\",\"className\":\"ProfileMetafield\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileMetafield\",\"collection\":\"profilemetafields\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileMetafield.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"description\":{\"type\":\"text\",\"required\":false},\"validation\":{\"type\":\"json\",\"required\":false}},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileMetafield | null>\",\"isStatic\":true,\"isPublic\":true},\"registerValidator\":{\"name\":\"registerValidator\",\"async\":false,\"parameters\":[{\"name\":\"name\",\"type\":\"string\",\"optional\":false},{\"name\":\"validator\",\"type\":\"ValidatorFunction\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":true,\"isPublic\":true},\"getValidator\":{\"name\":\"getValidator\",\"async\":false,\"parameters\":[{\"name\":\"name\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"ValidatorFunction | undefined\",\"isStatic\":true,\"isPublic\":true},\"validateValue\":{\"name\":\"validateValue\",\"async\":true,\"parameters\":[{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileMetafield\",\"collectionExportName\":\"ProfileMetafieldCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profile_metafields\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_metafields\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT,\\n \\\"validation\\\" JSON\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"validation\":{\"type\":\"JSON\",\"notNull\":false}},\"indexes\":[{\"name\":\"profile_metafields_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_metafields_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_metafields_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"afe420df\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileRelationship\":{\"name\":\"profilerelationship\",\"className\":\"ProfileRelationship\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileRelationship\",\"collection\":\"profilerelationships\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileRelationship.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"fromProfileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"toProfileId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Profile\",\"_meta\":{\"required\":true}},\"typeId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileRelationshipType\",\"_meta\":{\"required\":true}},\"contextProfileId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Profile\"},\"terms\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationshipTerm\"}},\"methods\":{\"getTypeSlug\":{\"name\":\"getTypeSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"addTerm\":{\"name\":\"addTerm\",\"async\":true,\"parameters\":[{\"name\":\"startedAt\",\"type\":\"Date\",\"optional\":false},{\"name\":\"endedAt\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"endCurrentTerm\":{\"name\":\"endCurrentTerm\",\"async\":true,\"parameters\":[{\"name\":\"endedAt\",\"type\":\"Date\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getTerms\":{\"name\":\"getTerms\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ProfileRelationshipTerm[]>\",\"isStatic\":false,\"isPublic\":true},\"getActiveTerm\":{\"name\":\"getActiveTerm\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ProfileRelationshipTerm | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileRelationship\",\"collectionExportName\":\"ProfileRelationshipCollection\",\"validationRules\":[{\"field\":\"fromProfileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"toProfileId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"typeId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"profile_relationships\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_relationships\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"from_profile_id\\\" UUID,\\n \\\"to_profile_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"context_profile_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"from_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"to_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_relationship_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"context_profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profiles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"profile_relationships_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_relationships_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_relationships_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profile_relationships_from_profile_id_idx\",\"columns\":[\"from_profile_id\"]},{\"name\":\"profile_relationships_to_profile_id_idx\",\"columns\":[\"to_profile_id\"]},{\"name\":\"profile_relationships_type_id_idx\",\"columns\":[\"type_id\"]},{\"name\":\"profile_relationships_context_profile_id_idx\",\"columns\":[\"context_profile_id\"]}],\"version\":\"48878dba\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileRelationshipTerm\":{\"name\":\"profilerelationshipterm\",\"className\":\"ProfileRelationshipTerm\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileRelationshipTerm\",\"collection\":\"profilerelationshipterms\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileRelationshipTerm.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"relationshipId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileRelationship\",\"_meta\":{\"required\":true}},\"startedAt\":{\"type\":\"datetime\",\"required\":true,\"_meta\":{\"required\":true}},\"endedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"isActive\":{\"name\":\"isActive\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"end\":{\"name\":\"end\",\"async\":true,\"parameters\":[{\"name\":\"endedAt\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getDurationDays\":{\"name\":\"getDurationDays\",\"async\":false,\"parameters\":[],\"returnType\":\"number\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileRelationshipTerm\",\"collectionExportName\":\"ProfileRelationshipTermCollection\",\"validationRules\":[{\"field\":\"relationshipId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"startedAt\",\"rule\":\"required\",\"fieldType\":\"datetime\"}],\"schema\":{\"tableName\":\"profile_relationship_terms\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_relationship_terms\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"relationship_id\\\" UUID,\\n \\\"started_at\\\" TIMESTAMP,\\n \\\"ended_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"relationship_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_relationships\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"started_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"ended_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"profile_relationship_terms_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"profile_relationship_terms_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_relationship_terms_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"profile_relationship_terms_relationship_id_idx\",\"columns\":[\"relationship_id\"]}],\"version\":\"ef299102\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileRelationshipType\":{\"name\":\"profilerelationshiptype\",\"className\":\"ProfileRelationshipType\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileRelationshipType\",\"collection\":\"profilerelationshiptypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileRelationshipType.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"reciprocal\":{\"type\":\"boolean\",\"required\":false,\"default\":true}},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileRelationshipType | null>\",\"isStatic\":true,\"isPublic\":true},\"registerReciprocalHandler\":{\"name\":\"registerReciprocalHandler\",\"async\":false,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"handler\",\"type\":\"ReciprocalHandler\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":true,\"isPublic\":true},\"getReciprocalHandler\":{\"name\":\"getReciprocalHandler\",\"async\":false,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"ReciprocalHandler | undefined\",\"isStatic\":true,\"isPublic\":true},\"isReciprocal\":{\"name\":\"isReciprocal\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileRelationshipType\",\"collectionExportName\":\"ProfileRelationshipTypeCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profile_relationship_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_relationship_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"reciprocal\\\" BOOLEAN DEFAULT TRUE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"reciprocal\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true}},\"indexes\":[{\"name\":\"profile_relationship_types_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"profile_relationship_types_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_relationship_types_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"719fe0d9\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:ProfileType\":{\"name\":\"profiletype\",\"className\":\"ProfileType\",\"qualifiedName\":\"@happyvertical/smrt-profiles:ProfileType\",\"collection\":\"profiletypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileType.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"description\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"_slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProfileType | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ProfileType\",\"collectionExportName\":\"ProfileTypeCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profile_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profile_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profile_types_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profile_types_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profile_types_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"0fb37aeb\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:Person\":{\"name\":\"person\",\"className\":\"Person\",\"qualifiedName\":\"@happyvertical/smrt-profiles:Person\",\"collection\":\"profiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileTypes.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true}}},\"typeId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileType\",\"_meta\":{\"required\":true}},\"email\":{\"type\":\"text\",\"required\":false},\"emailKey\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true,\"indexed\":true,\"readonly\":true},\"readonly\":true},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"description\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileMetadata\"},\"relationshipsFrom\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"fromProfileId\"}},\"relationshipsTo\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"toProfileId\"}}},\"methods\":{\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"getTypeSlug\":{\"name\":\"getTypeSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"setTypeBySlug\":{\"name\":\"setTypeBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addMetadata\":{\"name\":\"addMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string, string>>\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeMetadata\":{\"name\":\"removeMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addRelationship\":{\"name\":\"addRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"contextProfile\",\"type\":\"Profile\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRelationships\":{\"name\":\"getRelationships\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"'from' | 'to' | 'all'\"]}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelatedProfiles\":{\"name\":\"getRelatedProfiles\",\"async\":true,\"parameters\":[{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"removeRelationship\":{\"name\":\"removeRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateBio\":{\"name\":\"generateBio\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"matches\":{\"name\":\"matches\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"findByMetadata\":{\"name\":\"findByMetadata\",\"async\":true,\"parameters\":[{\"name\":\"_metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"_value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findByType\":{\"name\":\"findByType\",\"async\":true,\"parameters\":[{\"name\":\"_typeSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findRelated\":{\"name\":\"findRelated\",\"async\":true,\"parameters\":[{\"name\":\"_profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"_relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"searchByEmail\":{\"name\":\"searchByEmail\",\"async\":true,\"parameters\":[{\"name\":\"_email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":true,\"isPublic\":true},\"getApiKeys\":{\"name\":\"getApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"getActiveApiKeys\":{\"name\":\"getActiveApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"generateApiKey\":{\"name\":\"generateApiKey\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string[]\",\"Date | null\"]}],\"returnType\":\"Promise<GenerateKeyResult>\",\"isStatic\":false,\"isPublic\":true},\"getOidcIdentities\":{\"name\":\"getOidcIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<OidcIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkOidcIdentity\":{\"name\":\"linkOidcIdentity\",\"async\":true,\"parameters\":[{\"name\":\"oidcData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<OidcIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getNostrIdentities\":{\"name\":\"getNostrIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<NostrIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkNostrIdentity\":{\"name\":\"linkNostrIdentity\",\"async\":true,\"parameters\":[{\"name\":\"nostrData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getAuditLogs\":{\"name\":\"getAuditLogs\",\"async\":true,\"parameters\":[{\"name\":\"limit\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"recordAction\":{\"name\":\"recordAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"'web' | 'cli' | 'ci' | 'webhook' | 'mcp'\",\"Record<string, unknown>\",\"Profile | null\"]}],\"returnType\":\"Promise<AuditLog>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"tableName\":\"profiles\"},\"extends\":\"Profile\",\"exportName\":\"Person\",\"collectionExportName\":\"PersonCollection\",\"validationRules\":[{\"field\":\"typeId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"email\\\" TEXT,\\n \\\"email_key\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email\":{\"type\":\"TEXT\",\"notNull\":false},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profiles_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profiles_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profiles_email_key_idx\",\"columns\":[\"email_key\"]},{\"name\":\"profiles_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profiles_type_id_idx\",\"columns\":[\"type_id\"]}],\"version\":\"50218e42\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:Organization\":{\"name\":\"organization\",\"className\":\"Organization\",\"qualifiedName\":\"@happyvertical/smrt-profiles:Organization\",\"collection\":\"profiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileTypes.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true}}},\"typeId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileType\",\"_meta\":{\"required\":true}},\"email\":{\"type\":\"text\",\"required\":false},\"emailKey\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true,\"indexed\":true,\"readonly\":true},\"readonly\":true},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"description\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileMetadata\"},\"relationshipsFrom\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"fromProfileId\"}},\"relationshipsTo\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"toProfileId\"}}},\"methods\":{\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"getTypeSlug\":{\"name\":\"getTypeSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"setTypeBySlug\":{\"name\":\"setTypeBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addMetadata\":{\"name\":\"addMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string, string>>\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeMetadata\":{\"name\":\"removeMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addRelationship\":{\"name\":\"addRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"contextProfile\",\"type\":\"Profile\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRelationships\":{\"name\":\"getRelationships\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"'from' | 'to' | 'all'\"]}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelatedProfiles\":{\"name\":\"getRelatedProfiles\",\"async\":true,\"parameters\":[{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"removeRelationship\":{\"name\":\"removeRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateBio\":{\"name\":\"generateBio\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"matches\":{\"name\":\"matches\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"findByMetadata\":{\"name\":\"findByMetadata\",\"async\":true,\"parameters\":[{\"name\":\"_metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"_value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findByType\":{\"name\":\"findByType\",\"async\":true,\"parameters\":[{\"name\":\"_typeSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findRelated\":{\"name\":\"findRelated\",\"async\":true,\"parameters\":[{\"name\":\"_profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"_relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"searchByEmail\":{\"name\":\"searchByEmail\",\"async\":true,\"parameters\":[{\"name\":\"_email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":true,\"isPublic\":true},\"getApiKeys\":{\"name\":\"getApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"getActiveApiKeys\":{\"name\":\"getActiveApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"generateApiKey\":{\"name\":\"generateApiKey\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string[]\",\"Date | null\"]}],\"returnType\":\"Promise<GenerateKeyResult>\",\"isStatic\":false,\"isPublic\":true},\"getOidcIdentities\":{\"name\":\"getOidcIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<OidcIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkOidcIdentity\":{\"name\":\"linkOidcIdentity\",\"async\":true,\"parameters\":[{\"name\":\"oidcData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<OidcIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getNostrIdentities\":{\"name\":\"getNostrIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<NostrIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkNostrIdentity\":{\"name\":\"linkNostrIdentity\",\"async\":true,\"parameters\":[{\"name\":\"nostrData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getAuditLogs\":{\"name\":\"getAuditLogs\",\"async\":true,\"parameters\":[{\"name\":\"limit\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"recordAction\":{\"name\":\"recordAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"'web' | 'cli' | 'ci' | 'webhook' | 'mcp'\",\"Record<string, unknown>\",\"Profile | null\"]}],\"returnType\":\"Promise<AuditLog>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"tableName\":\"profiles\"},\"extends\":\"Profile\",\"exportName\":\"Organization\",\"collectionExportName\":\"OrganizationCollection\",\"validationRules\":[{\"field\":\"typeId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"email\\\" TEXT,\\n \\\"email_key\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email\":{\"type\":\"TEXT\",\"notNull\":false},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profiles_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profiles_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profiles_email_key_idx\",\"columns\":[\"email_key\"]},{\"name\":\"profiles_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profiles_type_id_idx\",\"columns\":[\"type_id\"]}],\"version\":\"b6b91ae1\"},\"importPath\":\"@happyvertical/smrt-profiles\"},\"@happyvertical/smrt-profiles:Bot\":{\"name\":\"bot\",\"className\":\"Bot\",\"qualifiedName\":\"@happyvertical/smrt-profiles:Bot\",\"collection\":\"profiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/profiles/src/models/ProfileTypes.ts\",\"packageName\":\"@happyvertical/smrt-profiles\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true}}},\"typeId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ProfileType\",\"_meta\":{\"required\":true}},\"email\":{\"type\":\"text\",\"required\":false},\"emailKey\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true,\"indexed\":true,\"readonly\":true},\"readonly\":true},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"description\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileMetadata\"},\"relationshipsFrom\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"fromProfileId\"}},\"relationshipsTo\":{\"type\":\"oneToMany\",\"required\":false,\"related\":\"ProfileRelationship\",\"_meta\":{\"foreignKey\":\"toProfileId\"}}},\"methods\":{\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"getTypeSlug\":{\"name\":\"getTypeSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"setTypeBySlug\":{\"name\":\"setTypeBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addMetadata\":{\"name\":\"addMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string, string>>\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeMetadata\":{\"name\":\"removeMetadata\",\"async\":true,\"parameters\":[{\"name\":\"metafieldSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addRelationship\":{\"name\":\"addRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"contextProfile\",\"type\":\"Profile\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRelationships\":{\"name\":\"getRelationships\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"'from' | 'to' | 'all'\"]}],\"returnType\":\"Promise<ProfileRelationship[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelatedProfiles\":{\"name\":\"getRelatedProfiles\",\"async\":true,\"parameters\":[{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":false,\"isPublic\":true},\"removeRelationship\":{\"name\":\"removeRelationship\",\"async\":true,\"parameters\":[{\"name\":\"toProfile\",\"type\":\"Profile\",\"optional\":false},{\"name\":\"relationshipSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateBio\":{\"name\":\"generateBio\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"matches\":{\"name\":\"matches\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"findByMetadata\":{\"name\":\"findByMetadata\",\"async\":true,\"parameters\":[{\"name\":\"_metafieldSlug\",\"type\":\"string\",\"optional\":false},{\"name\":\"_value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findByType\":{\"name\":\"findByType\",\"async\":true,\"parameters\":[{\"name\":\"_typeSlug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"findRelated\":{\"name\":\"findRelated\",\"async\":true,\"parameters\":[{\"name\":\"_profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"_relationshipSlug\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Profile[]>\",\"isStatic\":true,\"isPublic\":true},\"searchByEmail\":{\"name\":\"searchByEmail\",\"async\":true,\"parameters\":[{\"name\":\"_email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Profile | null>\",\"isStatic\":true,\"isPublic\":true},\"getApiKeys\":{\"name\":\"getApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"getActiveApiKeys\":{\"name\":\"getActiveApiKeys\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ApiKey[]>\",\"isStatic\":false,\"isPublic\":true},\"generateApiKey\":{\"name\":\"generateApiKey\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string[]\",\"Date | null\"]}],\"returnType\":\"Promise<GenerateKeyResult>\",\"isStatic\":false,\"isPublic\":true},\"getOidcIdentities\":{\"name\":\"getOidcIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<OidcIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkOidcIdentity\":{\"name\":\"linkOidcIdentity\",\"async\":true,\"parameters\":[{\"name\":\"oidcData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<OidcIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getNostrIdentities\":{\"name\":\"getNostrIdentities\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<NostrIdentity[]>\",\"isStatic\":false,\"isPublic\":true},\"linkNostrIdentity\":{\"name\":\"linkNostrIdentity\",\"async\":true,\"parameters\":[{\"name\":\"nostrData\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<NostrIdentity>\",\"isStatic\":false,\"isPublic\":true},\"getAuditLogs\":{\"name\":\"getAuditLogs\",\"async\":true,\"parameters\":[{\"name\":\"limit\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<AuditLog[]>\",\"isStatic\":false,\"isPublic\":true},\"recordAction\":{\"name\":\"recordAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"'web' | 'cli' | 'ci' | 'webhook' | 'mcp'\",\"Record<string, unknown>\",\"Profile | null\"]}],\"returnType\":\"Promise<AuditLog>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"tableName\":\"profiles\"},\"extends\":\"Profile\",\"exportName\":\"Bot\",\"collectionExportName\":\"BotCollection\",\"validationRules\":[{\"field\":\"typeId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type_id\\\" UUID,\\n \\\"email\\\" TEXT,\\n \\\"email_key\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"profile_types\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"email\":{\"type\":\"TEXT\",\"notNull\":false},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"profiles_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"profiles_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"profiles_email_key_idx\",\"columns\":[\"email_key\"]},{\"name\":\"profiles_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"profiles_type_id_idx\",\"columns\":[\"type_id\"]}],\"version\":\"39683be5\"},\"importPath\":\"@happyvertical/smrt-profiles\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-assets\",\"@happyvertical/smrt-core\",\"@happyvertical/smrt-prompts\",\"@happyvertical/smrt-tenancy\"]}"));
1340
+ var __defProp$16 = Object.defineProperty;
1341
+ var __getOwnPropDesc$15 = Object.getOwnPropertyDescriptor;
1342
+ var __decorateClass$15 = (decorators, target, key, kind) => {
1343
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$15(target, key) : target;
1344
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1345
+ if (kind && result) __defProp$16(target, key, result);
1346
+ return result;
1347
+ };
1348
+ var DEFAULT_EXPIRATION_MINUTES = 15;
1349
+ var MagicLinkToken = class extends SmrtObject {
1350
+ nostrIdentityId;
1351
+ tokenHash = "";
1352
+ /**
1353
+ * Email this token was sent to
1354
+ */
1355
+ email = "";
1356
+ /**
1357
+ * When this token expires
1358
+ */
1359
+ expiresAt = new Date(Date.now() + DEFAULT_EXPIRATION_MINUTES * 60 * 1e3);
1360
+ /**
1361
+ * When this token was used (null = unused)
1362
+ */
1363
+ usedAt = null;
1364
+ /**
1365
+ * IP address that requested the token (for rate limiting)
1366
+ */
1367
+ requestedFromIp = "";
1368
+ /**
1369
+ * When this token was created (for rate limiting)
1370
+ */
1371
+ createdAt = /* @__PURE__ */ new Date();
1372
+ constructor(options = {}) {
1373
+ super(options);
1374
+ if (options.nostrIdentityId) this.nostrIdentityId = options.nostrIdentityId;
1375
+ if (options.tokenHash) this.tokenHash = options.tokenHash;
1376
+ if (options.email) this.email = options.email;
1377
+ if (options.expiresAt) this.expiresAt = options.expiresAt;
1378
+ if (options.usedAt !== void 0) this.usedAt = options.usedAt;
1379
+ if (options.requestedFromIp) this.requestedFromIp = options.requestedFromIp;
1380
+ if (options.createdAt) this.createdAt = options.createdAt;
1381
+ }
1382
+ /**
1383
+ * Hash a token using SHA-256
1384
+ */
1385
+ static hashToken(token) {
1386
+ return createHash("sha256").update(token).digest("hex");
1387
+ }
1388
+ /**
1389
+ * Generate a new magic link token
1390
+ * @param nostrIdentity - The identity this token is for
1391
+ * @param email - The email address to send to
1392
+ * @param options - Additional options
1393
+ */
1394
+ static async generate(nostrIdentity, email, options = {}) {
1395
+ const token = randomBytes(32).toString("base64url");
1396
+ const tokenHash = MagicLinkToken.hashToken(token);
1397
+ const expiresInMinutes = options.expiresInMinutes ?? DEFAULT_EXPIRATION_MINUTES;
1398
+ const expiresAt = new Date(Date.now() + expiresInMinutes * 60 * 1e3);
1399
+ const magicLinkToken = new MagicLinkToken({
1400
+ db: options.db ?? nostrIdentity.options?.db,
1401
+ nostrIdentityId: nostrIdentity.id,
1402
+ tokenHash,
1403
+ email: email.toLowerCase(),
1404
+ expiresAt,
1405
+ requestedFromIp: options.requestedFromIp || ""
1406
+ });
1407
+ await magicLinkToken.initialize();
1408
+ await magicLinkToken.save();
1409
+ return {
1410
+ token,
1411
+ magicLinkToken
1412
+ };
1413
+ }
1414
+ /**
1415
+ * Verify a token and return the MagicLinkToken if valid
1416
+ * @param token - The plaintext token to verify
1417
+ * @param options - Database options
1418
+ * @returns The MagicLinkToken if valid, null otherwise
1419
+ */
1420
+ static async verify(token, options = {}) {
1421
+ const tokenHash = MagicLinkToken.hashToken(token);
1422
+ const { MagicLinkTokenCollection } = await Promise.resolve().then(() => MagicLinkTokenCollection_exports);
1423
+ const magicLinkToken = await (await MagicLinkTokenCollection.create(options)).findOne({ where: { tokenHash } });
1424
+ if (!magicLinkToken) return null;
1425
+ if (!magicLinkToken.isValid()) return null;
1426
+ return magicLinkToken;
1427
+ }
1428
+ /**
1429
+ * Check if this token is valid (not expired and not used)
1430
+ */
1431
+ isValid() {
1432
+ if (this.usedAt !== null) return false;
1433
+ if (/* @__PURE__ */ new Date() > this.expiresAt) return false;
1434
+ return true;
1435
+ }
1436
+ /**
1437
+ * Check if this token has expired
1438
+ */
1439
+ isExpired() {
1440
+ return /* @__PURE__ */ new Date() > this.expiresAt;
1441
+ }
1442
+ /**
1443
+ * Check if this token has been used
1444
+ */
1445
+ isUsed() {
1446
+ return this.usedAt !== null;
1447
+ }
1448
+ /**
1449
+ * Mark this token as used
1450
+ */
1451
+ async markUsed() {
1452
+ this.usedAt = /* @__PURE__ */ new Date();
1453
+ await this.save();
1454
+ }
1455
+ /**
1456
+ * Get the NostrIdentity this token is for
1457
+ */
1458
+ async getNostrIdentity() {
1459
+ return await this.getRelated("nostrIdentityId");
1460
+ }
1461
+ /**
1462
+ * Get time remaining until expiration in seconds
1463
+ */
1464
+ getTimeRemainingSeconds() {
1465
+ const now = /* @__PURE__ */ new Date();
1466
+ const diff = this.expiresAt.getTime() - now.getTime();
1467
+ return Math.max(0, Math.floor(diff / 1e3));
1468
+ }
1469
+ };
1470
+ __decorateClass$15([foreignKey("NostrIdentity", { required: true })], MagicLinkToken.prototype, "nostrIdentityId", 2);
1471
+ __decorateClass$15([field({ indexed: true })], MagicLinkToken.prototype, "tokenHash", 2);
1472
+ MagicLinkToken = __decorateClass$15([smrt({
1473
+ tableName: "magic_link_tokens",
1474
+ sensitive: true,
1475
+ api: { exclude: ["*"] },
1476
+ mcp: { exclude: ["*"] },
1477
+ cli: { include: ["list"] }
1478
+ })], MagicLinkToken);
1479
+ var MagicLinkTokenCollection_exports = /* @__PURE__ */ __exportAll$1({ MagicLinkTokenCollection: () => MagicLinkTokenCollection });
1480
+ var MagicLinkTokenCollection = class extends SmrtCollection {
1481
+ static _itemClass = MagicLinkToken;
1482
+ /**
1483
+ * Find token by hash
1484
+ */
1485
+ async findByTokenHash(tokenHash) {
1486
+ return await this.findOne({ where: { tokenHash } });
1487
+ }
1488
+ /**
1489
+ * Find active (non-expired, non-used) tokens for an email
1490
+ */
1491
+ async findActiveForEmail(email) {
1492
+ return (await this.list({ where: { email: email.toLowerCase() } })).filter((token) => token.isValid());
1493
+ }
1494
+ /**
1495
+ * Find tokens for a NostrIdentity
1496
+ */
1497
+ async findByIdentity(nostrIdentityId) {
1498
+ return await this.list({ where: { nostrIdentityId } });
1499
+ }
1500
+ /**
1501
+ * Count tokens created for an email within a time window (for rate limiting)
1502
+ * @param email - Email address
1503
+ * @param withinMinutes - Time window in minutes
1504
+ */
1505
+ async countRecentByEmail(email, withinMinutes) {
1506
+ const cutoff = /* @__PURE__ */ new Date(Date.now() - withinMinutes * 60 * 1e3);
1507
+ return (await this.list({ where: { email: email.toLowerCase() } })).filter((token) => {
1508
+ const createdAt = token.createdAt;
1509
+ return createdAt && new Date(createdAt) > cutoff;
1510
+ }).length;
1511
+ }
1512
+ /**
1513
+ * Count tokens created from an IP within a time window (for rate limiting)
1514
+ * @param ip - IP address
1515
+ * @param withinMinutes - Time window in minutes
1516
+ */
1517
+ async countRecentByIp(ip, withinMinutes) {
1518
+ const cutoff = /* @__PURE__ */ new Date(Date.now() - withinMinutes * 60 * 1e3);
1519
+ return (await this.list({ where: { requestedFromIp: ip } })).filter((token) => {
1520
+ const createdAt = token.createdAt;
1521
+ return createdAt && new Date(createdAt) > cutoff;
1522
+ }).length;
1523
+ }
1524
+ /**
1525
+ * Verify a token and return it if valid
1526
+ */
1527
+ async verify(token) {
1528
+ const tokenHash = MagicLinkToken.hashToken(token);
1529
+ const magicLinkToken = await this.findByTokenHash(tokenHash);
1530
+ if (!magicLinkToken) return null;
1531
+ if (!magicLinkToken.isValid()) return null;
1532
+ return magicLinkToken;
1533
+ }
1534
+ /**
1535
+ * Clean up expired tokens by deleting them
1536
+ * @returns Number of tokens deleted
1537
+ */
1538
+ async cleanupExpired() {
1539
+ const allTokens = await this.list({});
1540
+ let deleted = 0;
1541
+ for (const token of allTokens) if (token.isExpired() || token.isUsed()) {
1542
+ await token.delete();
1543
+ deleted++;
1544
+ }
1545
+ return deleted;
1546
+ }
1547
+ /**
1548
+ * Revoke all tokens for a NostrIdentity (e.g., when identity is deleted)
1549
+ */
1550
+ async revokeForIdentity(nostrIdentityId) {
1551
+ const tokens = await this.findByIdentity(nostrIdentityId);
1552
+ let revoked = 0;
1553
+ for (const token of tokens) if (!token.isUsed()) {
1554
+ await token.markUsed();
1555
+ revoked++;
1556
+ }
1557
+ return revoked;
1558
+ }
1559
+ /**
1560
+ * Check if rate limit is exceeded for email
1561
+ * @param email - Email address
1562
+ * @param maxPerHour - Maximum tokens allowed per hour (default: 5)
1563
+ */
1564
+ async isRateLimitedByEmail(email, maxPerHour = 5) {
1565
+ return await this.countRecentByEmail(email, 60) >= maxPerHour;
1566
+ }
1567
+ /**
1568
+ * Check if rate limit is exceeded for IP
1569
+ * @param ip - IP address
1570
+ * @param maxPerHour - Maximum tokens allowed per hour (default: 10)
1571
+ */
1572
+ async isRateLimitedByIp(ip, maxPerHour = 10) {
1573
+ return await this.countRecentByIp(ip, 60) >= maxPerHour;
1574
+ }
1575
+ };
1576
+ //#endregion
1577
+ //#region ../users/dist/chunks/types-DFqeph0R.js
1578
+ var DEFAULT_ROLE_SLUGS = {
1579
+ OWNER: "owner",
1580
+ ADMIN: "admin",
1581
+ MEMBER: "member",
1582
+ VIEWER: "viewer"
1583
+ };
1584
+ DEFAULT_ROLE_SLUGS.OWNER, DEFAULT_ROLE_SLUGS.ADMIN, DEFAULT_ROLE_SLUGS.MEMBER, DEFAULT_ROLE_SLUGS.VIEWER;
1585
+ //#endregion
1586
+ //#region ../users/dist/chunks/TerminalAuthService-DK_1yyr8.js
1587
+ var __defProp$14 = Object.defineProperty;
1588
+ var __exportAll = (all, no_symbols) => {
1589
+ let target = {};
1590
+ for (var name in all) __defProp$14(target, name, {
1591
+ get: all[name],
1592
+ enumerable: true
1593
+ });
1594
+ if (!no_symbols) __defProp$14(target, Symbol.toStringTag, { value: "Module" });
1595
+ return target;
1596
+ };
1597
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-users\",\"packageVersion\":\"0.51.17\",\"objects\":{\"@happyvertical/smrt-users:AccessRequestCollection\":{\"name\":\"accessrequestcollection\",\"className\":\"AccessRequestCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:AccessRequestCollection\",\"collection\":\"accessrequests\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/AccessRequestCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByEmail\":{\"name\":\"findByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AccessRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findOpenByEmail\":{\"name\":\"findOpenByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<AccessRequest | null>\",\"isStatic\":false,\"isPublic\":true},\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"AccessRequestStatus\",\"optional\":false}],\"returnType\":\"Promise<AccessRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findOpen\":{\"name\":\"findOpen\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<AccessRequest[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"access_requests\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"AccessRequest\",\"exportName\":\"AccessRequestCollection\",\"collectionExportName\":\"AccessRequestCollectionCollection\",\"schema\":{\"tableName\":\"access_requests\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"access_requests\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"email\\\" TEXT NOT NULL DEFAULT '',\\n \\\"name\\\" TEXT,\\n \\\"status\\\" TEXT,\\n \\\"source\\\" TEXT DEFAULT '',\\n \\\"request_context\\\" TEXT DEFAULT '{}',\\n \\\"note\\\" TEXT,\\n \\\"requested_at\\\" TIMESTAMP,\\n \\\"decided_at\\\" TIMESTAMP,\\n \\\"decided_by\\\" TEXT,\\n \\\"resulting_user_id\\\" TEXT,\\n \\\"tenant_hint\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"email\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false,\"default\":\"\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"source\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"request_context\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"{}\"},\"note\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"requested_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"decided_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"decided_by\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"resulting_user_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_hint\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"access_requests_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"access_requests_email_idx\",\"columns\":[\"email\"]},{\"name\":\"access_requests_status_idx\",\"columns\":[\"status\"]},{\"name\":\"access_requests_source_idx\",\"columns\":[\"source\"]},{\"name\":\"access_requests_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"f396996f\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UsersCliAuthApproveLimitCollection\":{\"name\":\"userscliauthapprovelimitcollection\",\"className\":\"UsersCliAuthApproveLimitCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:UsersCliAuthApproveLimitCollection\",\"collection\":\"userscliauthapprovelimits\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/CliAuthApproveLimitCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"reserveAttempt\":{\"name\":\"reserveAttempt\",\"async\":true,\"parameters\":[{\"name\":\"input\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"Promise<CliAuthApproveReservation>\",\"isStatic\":false,\"isPublic\":true},\"releaseAttempt\":{\"name\":\"releaseAttempt\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false},{\"name\":\"windowStartedAt\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"users_cli_auth_approve_limits\",\"api\":false,\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"UsersCliAuthApproveLimit\",\"exportName\":\"UsersCliAuthApproveLimitCollection\",\"collectionExportName\":\"UsersCliAuthApproveLimitCollectionCollection\",\"schema\":{\"tableName\":\"users_cli_auth_approve_limits\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users_cli_auth_approve_limits\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_id\\\" UUID NOT NULL UNIQUE,\\n \\\"attempt_count\\\" INTEGER NOT NULL DEFAULT 0,\\n \\\"window_started_at\\\" TIMESTAMP NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":true,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"attempt_count\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0},\"window_started_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"unique\":false}},\"indexes\":[{\"name\":\"users_cli_auth_approve_limits_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_cli_auth_approve_limits_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"c45c02de\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UsersCliAuthRequestCollection\":{\"name\":\"userscliauthrequestcollection\",\"className\":\"UsersCliAuthRequestCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:UsersCliAuthRequestCollection\",\"collection\":\"userscliauthrequests\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/CliAuthRequestCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"approvePendingRequest\":{\"name\":\"approvePendingRequest\",\"async\":true,\"parameters\":[{\"name\":\"input\",\"type\":\"ApprovePendingCliAuthRequestInput\",\"optional\":false}],\"returnType\":\"Promise<ApprovedCliAuthRequestSnapshot | null>\",\"isStatic\":false,\"isPublic\":true},\"consumeApprovedSession\":{\"name\":\"consumeApprovedSession\",\"async\":true,\"parameters\":[{\"name\":\"deviceCodeHash\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string | null>\",\"isStatic\":false,\"isPublic\":true},\"findByUserCode\":{\"name\":\"findByUserCode\",\"async\":true,\"parameters\":[{\"name\":\"userCode\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<UsersCliAuthRequest | null>\",\"isStatic\":false,\"isPublic\":true},\"findByDeviceCodeHash\":{\"name\":\"findByDeviceCodeHash\",\"async\":true,\"parameters\":[{\"name\":\"deviceCodeHash\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<UsersCliAuthRequest | null>\",\"isStatic\":false,\"isPublic\":true},\"deleteExpired\":{\"name\":\"deleteExpired\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"boolean\"]}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"users_cli_auth_requests\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"UsersCliAuthRequest\",\"exportName\":\"UsersCliAuthRequestCollection\",\"collectionExportName\":\"UsersCliAuthRequestCollectionCollection\",\"schema\":{\"tableName\":\"users_cli_auth_requests\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users_cli_auth_requests\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_code\\\" TEXT NOT NULL UNIQUE,\\n \\\"device_code_hash\\\" TEXT NOT NULL UNIQUE,\\n \\\"status\\\" TEXT,\\n \\\"user_id\\\" UUID,\\n \\\"tenant_id\\\" UUID,\\n \\\"session_id\\\" UUID,\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"approved_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_code\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true},\"device_code_hash\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"session_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"sessions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"approved_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"users_cli_auth_requests_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_cli_auth_requests_expires_at_idx\",\"columns\":[\"expires_at\"]},{\"name\":\"users_cli_auth_requests_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"users_cli_auth_requests_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"users_cli_auth_requests_tenant_id_idx\",\"columns\":[\"tenant_id\"]},{\"name\":\"users_cli_auth_requests_session_id_idx\",\"columns\":[\"session_id\"]}],\"version\":\"713ae04c\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:GroupCollection\":{\"name\":\"groupcollection\",\"className\":\"GroupCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:GroupCollection\",\"collection\":\"groups\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/GroupCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Group[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySlug\":{\"name\":\"findBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Group | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Group\",\"exportName\":\"GroupCollection\",\"collectionExportName\":\"GroupCollectionCollection\",\"schema\":{\"tableName\":\"groups\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"groups\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"groups_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"groups_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"groups_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"1824c19b\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:GroupMemberCollection\":{\"name\":\"groupmembercollection\",\"className\":\"GroupMemberCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:GroupMemberCollection\",\"collection\":\"groupmembers\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/GroupMemberCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByGroup\":{\"name\":\"findByGroup\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<GroupMember[]>\",\"isStatic\":false,\"isPublic\":true},\"findByUser\":{\"name\":\"findByUser\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<GroupMember[]>\",\"isStatic\":false,\"isPublic\":true},\"isMember\":{\"name\":\"isMember\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false},{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"addMember\":{\"name\":\"addMember\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false},{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<GroupMember>\",\"isStatic\":false,\"isPublic\":true},\"removeMember\":{\"name\":\"removeMember\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false},{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getGroupIds\":{\"name\":\"getGroupIds\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getGroupIdsForTenant\":{\"name\":\"getGroupIdsForTenant\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getUserIds\":{\"name\":\"getUserIds\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"GroupMember\",\"exportName\":\"GroupMemberCollection\",\"collectionExportName\":\"GroupMemberCollectionCollection\",\"schema\":{\"tableName\":\"group_members\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"group_members\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"group_id\\\" UUID NOT NULL,\\n \\\"user_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"group_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"groups\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"group_members_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"group_members_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"group_members_group_id_idx\",\"columns\":[\"group_id\"]},{\"name\":\"group_members_user_id_idx\",\"columns\":[\"user_id\"]}],\"version\":\"ed4d1187\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:GroupRoleCollection\":{\"name\":\"grouprolecollection\",\"className\":\"GroupRoleCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:GroupRoleCollection\",\"collection\":\"grouproles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/GroupRoleCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByGroup\":{\"name\":\"findByGroup\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<GroupRole[]>\",\"isStatic\":false,\"isPublic\":true},\"findByRole\":{\"name\":\"findByRole\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<GroupRole[]>\",\"isStatic\":false,\"isPublic\":true},\"hasRole\":{\"name\":\"hasRole\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false},{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"addRole\":{\"name\":\"addRole\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false},{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<GroupRole>\",\"isStatic\":false,\"isPublic\":true},\"removeRole\":{\"name\":\"removeRole\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false},{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getRoleIds\":{\"name\":\"getRoleIds\",\"async\":true,\"parameters\":[{\"name\":\"groupId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"GroupRole\",\"exportName\":\"GroupRoleCollection\",\"collectionExportName\":\"GroupRoleCollectionCollection\",\"schema\":{\"tableName\":\"group_roles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"group_roles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"group_id\\\" UUID NOT NULL,\\n \\\"role_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"group_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"groups\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"role_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"roles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"group_roles_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"group_roles_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"group_roles_group_id_idx\",\"columns\":[\"group_id\"]},{\"name\":\"group_roles_role_id_idx\",\"columns\":[\"role_id\"]}],\"version\":\"b1e35f93\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UsersMagicLinkTokenCollection\":{\"name\":\"usersmagiclinktokencollection\",\"className\":\"UsersMagicLinkTokenCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:UsersMagicLinkTokenCollection\",\"collection\":\"usersmagiclinktokens\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/MagicLinkTokenCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByNonce\":{\"name\":\"findByNonce\",\"async\":true,\"parameters\":[{\"name\":\"nonce\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<UsersMagicLinkToken | null>\",\"isStatic\":false,\"isPublic\":true},\"markUsed\":{\"name\":\"markUsed\",\"async\":true,\"parameters\":[{\"name\":\"nonce\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"deleteExpired\":{\"name\":\"deleteExpired\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"boolean\"]}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"users_magic_link_tokens\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"UsersMagicLinkToken\",\"exportName\":\"UsersMagicLinkTokenCollection\",\"collectionExportName\":\"UsersMagicLinkTokenCollectionCollection\",\"schema\":{\"tableName\":\"users_magic_link_tokens\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users_magic_link_tokens\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"nonce\\\" TEXT NOT NULL UNIQUE DEFAULT '',\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"used\\\" BOOLEAN DEFAULT FALSE,\\n \\\"expires_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"nonce\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true,\"default\":\"\"},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"used\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"users_magic_link_tokens_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_magic_link_tokens_expires_at_idx\",\"columns\":[\"expires_at\"]},{\"name\":\"users_magic_link_tokens_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"537853d3\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:MembershipCollection\":{\"name\":\"membershipcollection\",\"className\":\"MembershipCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:MembershipCollection\",\"collection\":\"memberships\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/MembershipCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByUser\":{\"name\":\"findByUser\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Membership[]>\",\"isStatic\":false,\"isPublic\":true},\"findActiveByUser\":{\"name\":\"findActiveByUser\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Membership[]>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Membership[]>\",\"isStatic\":false,\"isPublic\":true},\"findActiveByTenant\":{\"name\":\"findActiveByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Membership[]>\",\"isStatic\":false,\"isPublic\":true},\"findByUserAndTenant\":{\"name\":\"findByUserAndTenant\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Membership | null>\",\"isStatic\":false,\"isPublic\":true},\"findByRole\":{\"name\":\"findByRole\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Membership[]>\",\"isStatic\":false,\"isPublic\":true},\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"MembershipStatus\",\"optional\":false}],\"returnType\":\"Promise<Membership[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Membership\",\"exportName\":\"MembershipCollection\",\"collectionExportName\":\"MembershipCollectionCollection\",\"schema\":{\"tableName\":\"memberships\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"memberships\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_id\\\" UUID NOT NULL,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"role_id\\\" UUID NOT NULL,\\n \\\"status\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"role_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"roles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"memberships_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"memberships_tenant_id_user_id_idx\",\"columns\":[\"tenant_id\",\"user_id\"]},{\"name\":\"memberships_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"memberships_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"memberships_role_id_idx\",\"columns\":[\"role_id\"]}],\"version\":\"ebfd11e0\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:MembershipOverrideCollection\":{\"name\":\"membershipoverridecollection\",\"className\":\"MembershipOverrideCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:MembershipOverrideCollection\",\"collection\":\"membershipoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/MembershipOverrideCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByMembership\":{\"name\":\"findByMembership\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MembershipOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findGrants\":{\"name\":\"findGrants\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MembershipOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findDenies\":{\"name\":\"findDenies\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MembershipOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"getGrantedPermissionIds\":{\"name\":\"getGrantedPermissionIds\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getDeniedPermissionIds\":{\"name\":\"getDeniedPermissionIds\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"setOverride\":{\"name\":\"setOverride\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"OverrideEffect\",\"optional\":false}],\"returnType\":\"Promise<MembershipOverride>\",\"isStatic\":false,\"isPublic\":true},\"removeOverride\":{\"name\":\"removeOverride\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"grantPermission\":{\"name\":\"grantPermission\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MembershipOverride>\",\"isStatic\":false,\"isPublic\":true},\"denyPermission\":{\"name\":\"denyPermission\",\"async\":true,\"parameters\":[{\"name\":\"membershipId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<MembershipOverride>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"MembershipOverride\",\"exportName\":\"MembershipOverrideCollection\",\"collectionExportName\":\"MembershipOverrideCollectionCollection\",\"schema\":{\"tableName\":\"membership_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"membership_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"membership_id\\\" UUID NOT NULL,\\n \\\"permission_id\\\" UUID NOT NULL,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"membership_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"memberships\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"permission_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"permissions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"membership_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"membership_overrides_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"membership_overrides_membership_id_idx\",\"columns\":[\"membership_id\"]},{\"name\":\"membership_overrides_permission_id_idx\",\"columns\":[\"permission_id\"]}],\"version\":\"25fe9da8\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:PermissionCollection\":{\"name\":\"permissioncollection\",\"className\":\"PermissionCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:PermissionCollection\",\"collection\":\"permissions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/PermissionCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByCategory\":{\"name\":\"findByCategory\",\"async\":true,\"parameters\":[{\"name\":\"category\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Permission[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySlug\":{\"name\":\"findBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Permission | null>\",\"isStatic\":false,\"isPublic\":true},\"findByIds\":{\"name\":\"findByIds\",\"async\":true,\"parameters\":[{\"name\":\"ids\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<Map<string, Permission>>\",\"isStatic\":false,\"isPublic\":true},\"getCategories\":{\"name\":\"getCategories\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"findOrCreate\":{\"name\":\"findOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"defaults\",\"type\":\"Partial<object>\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<Permission>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Permission\",\"exportName\":\"PermissionCollection\",\"collectionExportName\":\"PermissionCollectionCollection\",\"schema\":{\"tableName\":\"permissions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"permissions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"category\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"category\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"permissions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"permissions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"4c81b2af\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:ResourceGrantCollection\":{\"name\":\"resourcegrantcollection\",\"className\":\"ResourceGrantCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:ResourceGrantCollection\",\"collection\":\"resourcegrants\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/ResourceGrantCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findExact\":{\"name\":\"findExact\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"userId\",\"type\":\"string\",\"optional\":false},{\"name\":\"resourceType\",\"type\":\"string\",\"optional\":false},{\"name\":\"resourceId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permission\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ResourceGrant[]>\",\"isStatic\":false,\"isPublic\":true},\"findChildren\":{\"name\":\"findChildren\",\"async\":true,\"parameters\":[{\"name\":\"parentGrantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ResourceGrant[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ResourceGrant\",\"exportName\":\"ResourceGrantCollection\",\"collectionExportName\":\"ResourceGrantCollectionCollection\",\"schema\":{\"tableName\":\"resource_grants\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"resource_grants\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"user_id\\\" UUID NOT NULL,\\n \\\"resource_type\\\" TEXT,\\n \\\"resource_id\\\" TEXT,\\n \\\"permission\\\" TEXT,\\n \\\"effect\\\" TEXT,\\n \\\"can_delegate\\\" BOOLEAN DEFAULT FALSE,\\n \\\"parent_grant_id\\\" UUID,\\n \\\"revoked_at\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":true,\"unique\":false},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"resource_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"resource_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"permission\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"can_delegate\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"parent_grant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"resource_grants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"revoked_at\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"resource_grants_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true},{\"name\":\"resource_grants_lookup_idx\",\"columns\":[\"tenant_id\",\"user_id\"]},{\"name\":\"resource_grants_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"resource_grants_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"resource_grants_parent_grant_id_idx\",\"columns\":[\"parent_grant_id\"]}],\"version\":\"52e03776\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:RoleCollection\":{\"name\":\"rolecollection\",\"className\":\"RoleCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:RoleCollection\",\"collection\":\"roles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/RoleCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findSystemRoles\":{\"name\":\"findSystemRoles\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Role[]>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Role[]>\",\"isStatic\":false,\"isPublic\":true},\"findTenantRoles\":{\"name\":\"findTenantRoles\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Role[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySlug\":{\"name\":\"findBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Role | null>\",\"isStatic\":false,\"isPublic\":true},\"findSystemRoleBySlug\":{\"name\":\"findSystemRoleBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Role | null>\",\"isStatic\":false,\"isPublic\":true},\"seedSystemRoles\":{\"name\":\"seedSystemRoles\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SeedSystemRolesOptions\",\"optional\":true}],\"returnType\":\"Promise<Role[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Role\",\"exportName\":\"RoleCollection\",\"collectionExportName\":\"RoleCollectionCollection\",\"schema\":{\"tableName\":\"roles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"roles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"is_system\\\" BOOLEAN DEFAULT FALSE,\\n \\\"inherits_to_descendants\\\" BOOLEAN DEFAULT FALSE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"is_system\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"inherits_to_descendants\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false}},\"indexes\":[{\"name\":\"roles_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"roles_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"roles_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"47369d9d\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:RolePermissionCollection\":{\"name\":\"rolepermissioncollection\",\"className\":\"RolePermissionCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:RolePermissionCollection\",\"collection\":\"rolepermissions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/RolePermissionCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByRole\":{\"name\":\"findByRole\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<RolePermission[]>\",\"isStatic\":false,\"isPublic\":true},\"findByPermission\":{\"name\":\"findByPermission\",\"async\":true,\"parameters\":[{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<RolePermission[]>\",\"isStatic\":false,\"isPublic\":true},\"hasPermission\":{\"name\":\"hasPermission\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"addPermission\":{\"name\":\"addPermission\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<RolePermission>\",\"isStatic\":false,\"isPublic\":true},\"removePermission\":{\"name\":\"removePermission\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getPermissionIds\":{\"name\":\"getPermissionIds\",\"async\":true,\"parameters\":[{\"name\":\"roleId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"seedRolePermissions\":{\"name\":\"seedRolePermissions\",\"async\":true,\"parameters\":[{\"name\":\"matrix\",\"type\":\"RolePermissionPatternMatrix\",\"optional\":true},{\"name\":\"options\",\"type\":\"SeedRolePermissionsOptions\",\"optional\":true}],\"returnType\":\"Promise<SeedRolePermissionsResult>\",\"isStatic\":false,\"isPublic\":true},\"seedDefaultRolePersonalizationPermissions\":{\"name\":\"seedDefaultRolePersonalizationPermissions\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<SeedRolePermissionsOptions, 'prune'>\",\"optional\":true}],\"returnType\":\"Promise<SeedRolePermissionsResult>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"RolePermission\",\"exportName\":\"RolePermissionCollection\",\"collectionExportName\":\"RolePermissionCollectionCollection\",\"schema\":{\"tableName\":\"role_permissions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"role_permissions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"role_id\\\" UUID NOT NULL,\\n \\\"permission_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"role_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"roles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"permission_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"permissions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"role_permissions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"role_permissions_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"role_permissions_role_id_idx\",\"columns\":[\"role_id\"]},{\"name\":\"role_permissions_permission_id_idx\",\"columns\":[\"permission_id\"]}],\"version\":\"4dfed3ac\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:SessionCollection\":{\"name\":\"sessioncollection\",\"className\":\"SessionCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:SessionCollection\",\"collection\":\"sessions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/SessionCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"createSession\":{\"name\":\"createSession\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateSessionOptions\",\"optional\":false}],\"returnType\":\"Promise<Session>\",\"isStatic\":false,\"isPublic\":true},\"findValidSession\":{\"name\":\"findValidSession\",\"async\":true,\"parameters\":[{\"name\":\"sessionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Session | null>\",\"isStatic\":false,\"isPublic\":true},\"touch\":{\"name\":\"touch\",\"async\":true,\"parameters\":[{\"name\":\"sessionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"extendTtl\",\"type\":\"boolean\",\"optional\":true},{\"name\":\"ttl\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"findByUser\":{\"name\":\"findByUser\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Session[]>\",\"isStatic\":false,\"isPublic\":true},\"deleteUserSessions\":{\"name\":\"deleteUserSessions\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"revokeUserSessions\":{\"name\":\"revokeUserSessions\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"revokeSession\":{\"name\":\"revokeSession\",\"async\":true,\"parameters\":[{\"name\":\"sessionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"deleteExpired\":{\"name\":\"deleteExpired\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"boolean\"]}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"countUserSessions\":{\"name\":\"countUserSessions\",\"async\":true,\"parameters\":[{\"name\":\"userId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"setSessionTenant\":{\"name\":\"setSessionTenant\",\"async\":true,\"parameters\":[{\"name\":\"sessionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"setSessionData\":{\"name\":\"setSessionData\",\"async\":true,\"parameters\":[{\"name\":\"sessionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getSessionData\":{\"name\":\"getSessionData\",\"async\":true,\"parameters\":[{\"name\":\"sessionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<T | undefined>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Session\",\"exportName\":\"SessionCollection\",\"collectionExportName\":\"SessionCollectionCollection\",\"schema\":{\"tableName\":\"sessions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"sessions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_id\\\" UUID,\\n \\\"tenant_id\\\" UUID,\\n \\\"status\\\" TEXT,\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"user_agent\\\" TEXT DEFAULT '',\\n \\\"ip_address\\\" TEXT DEFAULT '',\\n \\\"last_accessed_at\\\" TIMESTAMP,\\n \\\"data\\\" JSON DEFAULT '{}'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"user_agent\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"ip_address\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"last_accessed_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"data\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":{}}},\"indexes\":[{\"name\":\"sessions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"sessions_expires_at_idx\",\"columns\":[\"expires_at\"]},{\"name\":\"sessions_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"sessions_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"sessions_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"dc55d351\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:TenantCollection\":{\"name\":\"tenantcollection\",\"className\":\"TenantCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:TenantCollection\",\"collection\":\"tenants\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/TenantCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"TenantStatus\",\"optional\":false}],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"findActive\":{\"name\":\"findActive\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySlug\":{\"name\":\"findBySlug\",\"async\":true,\"parameters\":[{\"name\":\"slug\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant | null>\",\"isStatic\":false,\"isPublic\":true},\"findRoots\":{\"name\":\"findRoots\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"findChildren\":{\"name\":\"findChildren\",\"async\":true,\"parameters\":[{\"name\":\"parentTenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"findParent\":{\"name\":\"findParent\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant | null>\",\"isStatic\":false,\"isPublic\":true},\"getAncestors\":{\"name\":\"getAncestors\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"getAncestorsFromRoot\":{\"name\":\"getAncestorsFromRoot\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"getDescendants\":{\"name\":\"getDescendants\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"getSiblings\":{\"name\":\"getSiblings\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant[]>\",\"isStatic\":false,\"isPublic\":true},\"isAncestorOf\":{\"name\":\"isAncestorOf\",\"async\":true,\"parameters\":[{\"name\":\"potentialAncestorId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isDescendantOf\":{\"name\":\"isDescendantOf\",\"async\":true,\"parameters\":[{\"name\":\"potentialDescendantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"createChild\":{\"name\":\"createChild\",\"async\":true,\"parameters\":[{\"name\":\"parentTenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"CreateChildTenantOptions\",\"optional\":false}],\"returnType\":\"Promise<Tenant>\",\"isStatic\":false,\"isPublic\":true},\"moveToParent\":{\"name\":\"moveToParent\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"newParentId\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<Tenant>\",\"isStatic\":false,\"isPublic\":true},\"makeRoot\":{\"name\":\"makeRoot\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Tenant>\",\"isStatic\":false,\"isPublic\":true},\"validateHierarchy\":{\"name\":\"validateHierarchy\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getTree\":{\"name\":\"getTree\",\"async\":true,\"parameters\":[{\"name\":\"rootTenantId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Tenant\",\"exportName\":\"TenantCollection\",\"collectionExportName\":\"TenantCollectionCollection\",\"schema\":{\"tableName\":\"tenants\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tenants\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"status\\\" TEXT,\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"parent_tenant_id\\\" UUID,\\n \\\"hierarchy_level\\\" INTEGER DEFAULT 0,\\n \\\"hierarchy_path\\\" TEXT DEFAULT '',\\n \\\"cascade_permissions\\\" BOOLEAN DEFAULT TRUE,\\n \\\"inherit_permissions\\\" BOOLEAN DEFAULT TRUE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"status\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"parent_tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"hierarchy_level\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"hierarchy_path\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"cascade_permissions\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true},\"inherit_permissions\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true}},\"indexes\":[{\"name\":\"tenants_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"tenants_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"tenants_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"tenants_parent_tenant_id_idx\",\"columns\":[\"parent_tenant_id\"]}],\"version\":\"934f7025\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:TenantIntegrationCollection\":{\"name\":\"tenantintegrationcollection\",\"className\":\"TenantIntegrationCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:TenantIntegrationCollection\",\"collection\":\"tenantintegrations\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/TenantIntegrationCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"listForTenant\":{\"name\":\"listForTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantIntegration[]>\",\"isStatic\":false,\"isPublic\":true},\"findFor\":{\"name\":\"findFor\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"provider\",\"type\":\"TenantIntegrationProvider\",\"optional\":false}],\"returnType\":\"Promise<TenantIntegration | null>\",\"isStatic\":false,\"isPublic\":true},\"findOrInit\":{\"name\":\"findOrInit\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"provider\",\"type\":\"TenantIntegrationProvider\",\"optional\":false}],\"returnType\":\"Promise<TenantIntegration>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"tenant_integrations\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"TenantIntegration\",\"exportName\":\"TenantIntegrationCollection\",\"collectionExportName\":\"TenantIntegrationCollectionCollection\",\"schema\":{\"tableName\":\"tenant_integrations\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tenant_integrations\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"provider\\\" TEXT DEFAULT 'aws',\\n \\\"external_ids\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'unprovisioned',\\n \\\"last_checked_at\\\" TIMESTAMP,\\n \\\"last_check_summary\\\" TEXT,\\n \\\"last_error\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":true,\"unique\":false},\"provider\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"aws\"},\"external_ids\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"unprovisioned\"},\"last_checked_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"last_check_summary\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_error\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"tenant_integrations_tenant_id_provider_idx\",\"columns\":[\"tenant_id\",\"provider\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"tenant_integrations_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"tenant_integrations_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"3ed31966\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:TenantPermissionOverrideCollection\":{\"name\":\"tenantpermissionoverridecollection\",\"className\":\"TenantPermissionOverrideCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:TenantPermissionOverrideCollection\",\"collection\":\"tenantpermissionoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/TenantPermissionOverrideCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findGrants\":{\"name\":\"findGrants\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findDenies\":{\"name\":\"findDenies\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"findInherits\":{\"name\":\"findInherits\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"getGrantedPermissionIds\":{\"name\":\"getGrantedPermissionIds\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getDeniedPermissionIds\":{\"name\":\"getDeniedPermissionIds\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getOverridesByEffect\":{\"name\":\"getOverridesByEffect\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverrideResult>\",\"isStatic\":false,\"isPublic\":true},\"getOverridesByEffectBatch\":{\"name\":\"getOverridesByEffectBatch\",\"async\":true,\"parameters\":[{\"name\":\"tenantIds\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<Map<string, TenantPermissionOverrideResult>>\",\"isStatic\":false,\"isPublic\":true},\"setOverride\":{\"name\":\"setOverride\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false},{\"name\":\"effect\",\"type\":\"TenantPermissionEffect\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride>\",\"isStatic\":false,\"isPublic\":true},\"removeOverride\":{\"name\":\"removeOverride\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"removeAllOverrides\":{\"name\":\"removeAllOverrides\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"grantPermission\":{\"name\":\"grantPermission\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride>\",\"isStatic\":false,\"isPublic\":true},\"denyPermission\":{\"name\":\"denyPermission\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride>\",\"isStatic\":false,\"isPublic\":true},\"inheritPermission\":{\"name\":\"inheritPermission\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"permissionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride>\",\"isStatic\":false,\"isPublic\":true},\"bulkSetOverrides\":{\"name\":\"bulkSetOverrides\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"overrides\",\"type\":\"Array<object>\",\"optional\":false,\"memberTypes\":[\"string\",\"TenantPermissionEffect\"]}],\"returnType\":\"Promise<TenantPermissionOverride[]>\",\"isStatic\":false,\"isPublic\":true},\"copyOverrides\":{\"name\":\"copyOverrides\",\"async\":true,\"parameters\":[{\"name\":\"fromTenantId\",\"type\":\"string\",\"optional\":false},{\"name\":\"toTenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<TenantPermissionOverride[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"TenantPermissionOverride\",\"exportName\":\"TenantPermissionOverrideCollection\",\"collectionExportName\":\"TenantPermissionOverrideCollectionCollection\",\"schema\":{\"tableName\":\"tenant_permission_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tenant_permission_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"permission_id\\\" UUID NOT NULL,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"permission_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"permissions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"tenant_permission_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"tenant_permission_overrides_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"tenant_permission_overrides_tenant_id_idx\",\"columns\":[\"tenant_id\"]},{\"name\":\"tenant_permission_overrides_permission_id_idx\",\"columns\":[\"permission_id\"]}],\"version\":\"95b78bdd\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UserCollection\":{\"name\":\"usercollection\",\"className\":\"UserCollection\",\"qualifiedName\":\"@happyvertical/smrt-users:UserCollection\",\"collection\":\"users\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/collections/UserCollection.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{},\"methods\":{\"findByEmail\":{\"name\":\"findByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<User | null>\",\"isStatic\":false,\"isPublic\":true},\"findByProfile\":{\"name\":\"findByProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<User | null>\",\"isStatic\":false,\"isPublic\":true},\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"UserStatus\",\"optional\":false}],\"returnType\":\"Promise<User[]>\",\"isStatic\":false,\"isPublic\":true},\"findActive\":{\"name\":\"findActive\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<User[]>\",\"isStatic\":false,\"isPublic\":true},\"findPending\":{\"name\":\"findPending\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<User[]>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreateForProfile\":{\"name\":\"getOrCreateForProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false},{\"name\":\"email\",\"type\":\"string\",\"optional\":false},{\"name\":\"defaults\",\"type\":\"Partial<object>\",\"optional\":true,\"memberTypes\":[\"UserStatus\"]}],\"returnType\":\"Promise<User>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreateFromOidc\":{\"name\":\"getOrCreateFromOidc\",\"async\":true,\"parameters\":[{\"name\":\"claims\",\"type\":\"OidcClaims\",\"optional\":false},{\"name\":\"provider\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"GetOrCreateFromOidcOptions\",\"optional\":true}],\"returnType\":\"Promise<OidcIdentityResult>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"User\",\"exportName\":\"UserCollection\",\"collectionExportName\":\"UserCollectionCollection\",\"schema\":{\"tableName\":\"users\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID UNIQUE,\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"email_key\\\" TEXT UNIQUE,\\n \\\"status\\\" TEXT,\\n \\\"last_login_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":true},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":true},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_login_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"users_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_email_idx\",\"columns\":[\"email\"]},{\"name\":\"users_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"38fd1677\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:AccessRequest\":{\"name\":\"accessrequest\",\"className\":\"AccessRequest\",\"qualifiedName\":\"@happyvertical/smrt-users:AccessRequest\",\"collection\":\"accessrequests\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/AccessRequest.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"email\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true,\"indexed\":true}},\"name\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"status\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"indexed\":true}},\"source\":{\"type\":\"text\",\"required\":false,\"default\":\"\",\"_meta\":{\"indexed\":true}},\"requestContext\":{\"type\":\"text\",\"required\":false,\"default\":\"{}\"},\"note\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"requestedAt\":{\"type\":\"datetime\",\"required\":false},\"decidedAt\":{\"type\":\"datetime\",\"required\":false,\"_meta\":{\"nullable\":true}},\"decidedBy\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"resultingUserId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}},\"tenantHint\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true}}},\"methods\":{\"getRequestContext\":{\"name\":\"getRequestContext\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setRequestContext\":{\"name\":\"setRequestContext\",\"async\":false,\"parameters\":[{\"name\":\"value\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getTenantHint\":{\"name\":\"getTenantHint\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown> | null\",\"isStatic\":false,\"isPublic\":true},\"setTenantHint\":{\"name\":\"setTenantHint\",\"async\":false,\"parameters\":[{\"name\":\"value\",\"type\":\"Record<string, unknown> | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"Record<string, unknown>\"},{\"type\":\"null\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"isOpen\":{\"name\":\"isOpen\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isApproved\":{\"name\":\"isApproved\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isTerminal\":{\"name\":\"isTerminal\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"access_requests\",\"conflictColumns\":[\"id\"],\"api\":{\"include\":[]},\"mcp\":{\"include\":[]},\"cli\":{\"include\":[]}},\"extends\":\"SmrtObject\",\"exportName\":\"AccessRequest\",\"collectionExportName\":\"AccessRequestCollection\",\"validationRules\":[{\"field\":\"email\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"access_requests\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"access_requests\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"email\\\" TEXT NOT NULL DEFAULT '',\\n \\\"name\\\" TEXT,\\n \\\"status\\\" TEXT,\\n \\\"source\\\" TEXT DEFAULT '',\\n \\\"request_context\\\" TEXT DEFAULT '{}',\\n \\\"note\\\" TEXT,\\n \\\"requested_at\\\" TIMESTAMP,\\n \\\"decided_at\\\" TIMESTAMP,\\n \\\"decided_by\\\" TEXT,\\n \\\"resulting_user_id\\\" TEXT,\\n \\\"tenant_hint\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"email\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false,\"default\":\"\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"source\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"request_context\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"{}\"},\"note\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"requested_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"decided_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"decided_by\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"resulting_user_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_hint\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"access_requests_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"access_requests_email_idx\",\"columns\":[\"email\"]},{\"name\":\"access_requests_status_idx\",\"columns\":[\"status\"]},{\"name\":\"access_requests_source_idx\",\"columns\":[\"source\"]},{\"name\":\"access_requests_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"f396996f\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UsersCliAuthApproveLimit\":{\"name\":\"userscliauthapprovelimit\",\"className\":\"UsersCliAuthApproveLimit\",\"qualifiedName\":\"@happyvertical/smrt-users:UsersCliAuthApproveLimit\",\"collection\":\"userscliauthapprovelimits\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/CliAuthApproveLimit.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"userId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"User\",\"_meta\":{\"required\":true,\"unique\":true}},\"attemptCount\":{\"type\":\"integer\",\"required\":true,\"default\":0,\"_meta\":{\"required\":true,\"default\":0}},\"windowStartedAt\":{\"type\":\"datetime\",\"required\":true,\"_meta\":{\"required\":true}}},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"users_cli_auth_approve_limits\",\"api\":false,\"cli\":false,\"mcp\":false},\"extends\":\"SmrtObject\",\"exportName\":\"UsersCliAuthApproveLimit\",\"collectionExportName\":\"UsersCliAuthApproveLimitCollection\",\"validationRules\":[{\"field\":\"userId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"attemptCount\",\"rule\":\"required\",\"fieldType\":\"integer\"},{\"field\":\"windowStartedAt\",\"rule\":\"required\",\"fieldType\":\"datetime\"}],\"schema\":{\"tableName\":\"users_cli_auth_approve_limits\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users_cli_auth_approve_limits\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_id\\\" UUID NOT NULL UNIQUE,\\n \\\"attempt_count\\\" INTEGER NOT NULL DEFAULT 0,\\n \\\"window_started_at\\\" TIMESTAMP NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":true,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"attempt_count\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0},\"window_started_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"unique\":false}},\"indexes\":[{\"name\":\"users_cli_auth_approve_limits_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_cli_auth_approve_limits_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"c45c02de\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UsersCliAuthRequest\":{\"name\":\"userscliauthrequest\",\"className\":\"UsersCliAuthRequest\",\"qualifiedName\":\"@happyvertical/smrt-users:UsersCliAuthRequest\",\"collection\":\"userscliauthrequests\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/CliAuthRequest.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"userCode\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true,\"unique\":true}},\"deviceCodeHash\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true,\"unique\":true}},\"status\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"userId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"User\",\"_meta\":{\"nullable\":true}},\"tenantId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Tenant\",\"_meta\":{\"nullable\":true}},\"sessionId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Session\",\"_meta\":{\"nullable\":true}},\"expiresAt\":{\"type\":\"datetime\",\"required\":false,\"_meta\":{\"indexed\":true}},\"approvedAt\":{\"type\":\"datetime\",\"required\":false,\"_meta\":{\"nullable\":true}}},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"users_cli_auth_requests\",\"sensitive\":true,\"api\":{\"include\":[]},\"cli\":{\"include\":[]},\"mcp\":{\"include\":[]}},\"extends\":\"SmrtObject\",\"exportName\":\"UsersCliAuthRequest\",\"collectionExportName\":\"UsersCliAuthRequestCollection\",\"validationRules\":[{\"field\":\"userCode\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"deviceCodeHash\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"users_cli_auth_requests\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users_cli_auth_requests\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_code\\\" TEXT NOT NULL UNIQUE,\\n \\\"device_code_hash\\\" TEXT NOT NULL UNIQUE,\\n \\\"status\\\" TEXT,\\n \\\"user_id\\\" UUID,\\n \\\"tenant_id\\\" UUID,\\n \\\"session_id\\\" UUID,\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"approved_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_code\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true},\"device_code_hash\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"session_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"sessions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"approved_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"users_cli_auth_requests_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_cli_auth_requests_expires_at_idx\",\"columns\":[\"expires_at\"]},{\"name\":\"users_cli_auth_requests_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"users_cli_auth_requests_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"users_cli_auth_requests_tenant_id_idx\",\"columns\":[\"tenant_id\"]},{\"name\":\"users_cli_auth_requests_session_id_idx\",\"columns\":[\"session_id\"]}],\"version\":\"713ae04c\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:Group\":{\"name\":\"group\",\"className\":\"Group\",\"qualifiedName\":\"@happyvertical/smrt-users:Group\",\"collection\":\"groups\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/Group.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"tenantId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Tenant\",\"_meta\":{\"required\":true}},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"}},\"methods\":{},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true},\"extends\":\"SmrtObject\",\"exportName\":\"Group\",\"collectionExportName\":\"GroupCollection\",\"validationRules\":[{\"field\":\"tenantId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"groups\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"groups\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"groups_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"groups_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"groups_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"1824c19b\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:GroupMember\":{\"name\":\"groupmember\",\"className\":\"GroupMember\",\"qualifiedName\":\"@happyvertical/smrt-users:GroupMember\",\"collection\":\"groupmembers\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/GroupMember.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"groupId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Group\",\"_meta\":{\"required\":true}},\"userId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"User\",\"_meta\":{\"required\":true}}},\"methods\":{},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true},\"extends\":\"SmrtObject\",\"exportName\":\"GroupMember\",\"collectionExportName\":\"GroupMemberCollection\",\"validationRules\":[{\"field\":\"groupId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"userId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"group_members\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"group_members\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"group_id\\\" UUID NOT NULL,\\n \\\"user_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"group_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"groups\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"group_members_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"group_members_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"group_members_group_id_idx\",\"columns\":[\"group_id\"]},{\"name\":\"group_members_user_id_idx\",\"columns\":[\"user_id\"]}],\"version\":\"ed4d1187\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:GroupRole\":{\"name\":\"grouprole\",\"className\":\"GroupRole\",\"qualifiedName\":\"@happyvertical/smrt-users:GroupRole\",\"collection\":\"grouproles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/GroupRole.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"groupId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Group\",\"_meta\":{\"required\":true}},\"roleId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Role\",\"_meta\":{\"required\":true}}},\"methods\":{},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true},\"extends\":\"SmrtObject\",\"exportName\":\"GroupRole\",\"collectionExportName\":\"GroupRoleCollection\",\"validationRules\":[{\"field\":\"groupId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"roleId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"group_roles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"group_roles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"group_id\\\" UUID NOT NULL,\\n \\\"role_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"group_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"groups\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"role_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"roles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"group_roles_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"group_roles_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"group_roles_group_id_idx\",\"columns\":[\"group_id\"]},{\"name\":\"group_roles_role_id_idx\",\"columns\":[\"role_id\"]}],\"version\":\"b1e35f93\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:UsersMagicLinkToken\":{\"name\":\"usersmagiclinktoken\",\"className\":\"UsersMagicLinkToken\",\"qualifiedName\":\"@happyvertical/smrt-users:UsersMagicLinkToken\",\"collection\":\"usersmagiclinktokens\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/MagicLinkToken.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"nonce\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true,\"unique\":true}},\"email\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"used\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"expiresAt\":{\"type\":\"datetime\",\"required\":false,\"_meta\":{\"indexed\":true}}},\"methods\":{\"isExpired\":{\"name\":\"isExpired\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isValid\":{\"name\":\"isValid\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"users_magic_link_tokens\",\"sensitive\":true,\"api\":{\"include\":[]},\"mcp\":{\"include\":[]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"UsersMagicLinkToken\",\"collectionExportName\":\"UsersMagicLinkTokenCollection\",\"validationRules\":[{\"field\":\"nonce\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"users_magic_link_tokens\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users_magic_link_tokens\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"nonce\\\" TEXT NOT NULL UNIQUE DEFAULT '',\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"used\\\" BOOLEAN DEFAULT FALSE,\\n \\\"expires_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"nonce\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":true,\"default\":\"\"},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"used\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"users_magic_link_tokens_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_magic_link_tokens_expires_at_idx\",\"columns\":[\"expires_at\"]},{\"name\":\"users_magic_link_tokens_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"537853d3\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:Membership\":{\"name\":\"membership\",\"className\":\"Membership\",\"qualifiedName\":\"@happyvertical/smrt-users:Membership\",\"collection\":\"memberships\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/Membership.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"userId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"User\",\"_meta\":{\"required\":true}},\"tenantId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Tenant\",\"_meta\":{\"required\":true}},\"roleId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Role\",\"_meta\":{\"required\":true}},\"status\":{\"type\":\"text\",\"required\":false,\"_meta\":{}}},\"methods\":{\"isActive\":{\"name\":\"isActive\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isPending\":{\"name\":\"isPending\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"indexes\":[{\"name\":\"memberships_tenant_id_user_id_idx\",\"columns\":[\"tenantId\",\"userId\"]}]},\"extends\":\"SmrtObject\",\"exportName\":\"Membership\",\"collectionExportName\":\"MembershipCollection\",\"validationRules\":[{\"field\":\"userId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"tenantId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"roleId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"memberships\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"memberships\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_id\\\" UUID NOT NULL,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"role_id\\\" UUID NOT NULL,\\n \\\"status\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"role_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"roles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"memberships_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"memberships_tenant_id_user_id_idx\",\"columns\":[\"tenant_id\",\"user_id\"]},{\"name\":\"memberships_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"memberships_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"memberships_role_id_idx\",\"columns\":[\"role_id\"]}],\"version\":\"ebfd11e0\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:MembershipOverride\":{\"name\":\"membershipoverride\",\"className\":\"MembershipOverride\",\"qualifiedName\":\"@happyvertical/smrt-users:MembershipOverride\",\"collection\":\"membershipoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/MembershipOverride.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"membershipId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Membership\",\"_meta\":{\"required\":true}},\"permissionId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Permission\",\"_meta\":{\"required\":true}},\"effect\":{\"type\":\"text\",\"required\":false,\"_meta\":{}}},\"methods\":{\"isGrant\":{\"name\":\"isGrant\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isDeny\":{\"name\":\"isDeny\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"MembershipOverride\",\"collectionExportName\":\"MembershipOverrideCollection\",\"validationRules\":[{\"field\":\"membershipId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"permissionId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"membership_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"membership_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"membership_id\\\" UUID NOT NULL,\\n \\\"permission_id\\\" UUID NOT NULL,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"membership_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"memberships\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"permission_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"permissions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"membership_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"membership_overrides_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"membership_overrides_membership_id_idx\",\"columns\":[\"membership_id\"]},{\"name\":\"membership_overrides_permission_id_idx\",\"columns\":[\"permission_id\"]}],\"version\":\"25fe9da8\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:Permission\":{\"name\":\"permission\",\"className\":\"Permission\",\"qualifiedName\":\"@happyvertical/smrt-users:Permission\",\"collection\":\"permissions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/Permission.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"category\":{\"type\":\"text\",\"required\":false,\"default\":\"\"}},\"methods\":{\"parseSlug\":{\"name\":\"parseSlug\",\"async\":false,\"parameters\":[],\"returnType\":\"ParsedPermissionSlug\",\"isStatic\":false,\"isPublic\":true},\"getResource\":{\"name\":\"getResource\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true},\"getAction\":{\"name\":\"getAction\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true},\"isValidSlug\":{\"name\":\"isValidSlug\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"Permission\",\"collectionExportName\":\"PermissionCollection\",\"schema\":{\"tableName\":\"permissions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"permissions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"category\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"category\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"permissions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"permissions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"4c81b2af\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:ResourceGrant\":{\"name\":\"resourcegrant\",\"className\":\"ResourceGrant\",\"qualifiedName\":\"@happyvertical/smrt-users:ResourceGrant\",\"collection\":\"resourcegrants\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/ResourceGrant.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"tenantId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Tenant\",\"_meta\":{\"required\":true,\"sqlType\":\"UUID\",\"__tenancy\":{\"isTenantIdField\":true,\"mode\":\"required\",\"field\":\"tenantId\",\"autoFilter\":true,\"autoPopulate\":true,\"allowSuperAdminBypass\":false}}},\"userId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"User\",\"_meta\":{\"required\":true}},\"resourceType\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"resourceId\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"permission\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"effect\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"canDelegate\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"parentGrantId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"ResourceGrant\"},\"revokedAt\":{\"type\":\"text\",\"required\":false,\"_meta\":{}}},\"methods\":{\"isActive\":{\"name\":\"isActive\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tenantScoped\":true,\"api\":{\"include\":[]},\"mcp\":{\"include\":[]},\"cli\":{\"skipApiCheck\":true},\"indexes\":[{\"name\":\"resource_grants_lookup_idx\",\"columns\":[\"tenantId\",\"userId\"]}],\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ResourceGrant\",\"collectionExportName\":\"ResourceGrantCollection\",\"validationRules\":[{\"field\":\"userId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"resource_grants\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"resource_grants\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"user_id\\\" UUID NOT NULL,\\n \\\"resource_type\\\" TEXT,\\n \\\"resource_id\\\" TEXT,\\n \\\"permission\\\" TEXT,\\n \\\"effect\\\" TEXT,\\n \\\"can_delegate\\\" BOOLEAN DEFAULT FALSE,\\n \\\"parent_grant_id\\\" UUID,\\n \\\"revoked_at\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":true,\"unique\":false},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"resource_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"resource_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"permission\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"can_delegate\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"parent_grant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"resource_grants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"revoked_at\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"resource_grants_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true},{\"name\":\"resource_grants_lookup_idx\",\"columns\":[\"tenant_id\",\"user_id\"]},{\"name\":\"resource_grants_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"resource_grants_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"resource_grants_parent_grant_id_idx\",\"columns\":[\"parent_grant_id\"]}],\"version\":\"52e03776\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:Role\":{\"name\":\"role\",\"className\":\"Role\",\"qualifiedName\":\"@happyvertical/smrt-users:Role\",\"collection\":\"roles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/Role.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"tenantId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Tenant\",\"_meta\":{\"nullable\":true}},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"isSystem\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"inheritsToDescendants\":{\"type\":\"boolean\",\"required\":false,\"default\":false}},\"methods\":{\"isSystemRole\":{\"name\":\"isSystemRole\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isTenantRole\":{\"name\":\"isTenantRole\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"canDelete\":{\"name\":\"canDelete\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"Role\",\"collectionExportName\":\"RoleCollection\",\"schema\":{\"tableName\":\"roles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"roles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"is_system\\\" BOOLEAN DEFAULT FALSE,\\n \\\"inherits_to_descendants\\\" BOOLEAN DEFAULT FALSE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"is_system\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"inherits_to_descendants\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false}},\"indexes\":[{\"name\":\"roles_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"roles_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"roles_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"47369d9d\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:RolePermission\":{\"name\":\"rolepermission\",\"className\":\"RolePermission\",\"qualifiedName\":\"@happyvertical/smrt-users:RolePermission\",\"collection\":\"rolepermissions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/RolePermission.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"roleId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Role\",\"_meta\":{\"required\":true}},\"permissionId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Permission\",\"_meta\":{\"required\":true}}},\"methods\":{},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true},\"extends\":\"SmrtObject\",\"exportName\":\"RolePermission\",\"collectionExportName\":\"RolePermissionCollection\",\"validationRules\":[{\"field\":\"roleId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"permissionId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"role_permissions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"role_permissions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"role_id\\\" UUID NOT NULL,\\n \\\"permission_id\\\" UUID NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"role_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"roles\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"permission_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"permissions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}}},\"indexes\":[{\"name\":\"role_permissions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"role_permissions_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"role_permissions_role_id_idx\",\"columns\":[\"role_id\"]},{\"name\":\"role_permissions_permission_id_idx\",\"columns\":[\"permission_id\"]}],\"version\":\"4dfed3ac\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:Session\":{\"name\":\"session\",\"className\":\"Session\",\"qualifiedName\":\"@happyvertical/smrt-users:Session\",\"collection\":\"sessions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/Session.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"userId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"User\"},\"tenantId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Tenant\",\"_meta\":{\"nullable\":true}},\"status\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"expiresAt\":{\"type\":\"datetime\",\"required\":false,\"_meta\":{\"indexed\":true}},\"userAgent\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"ipAddress\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"lastAccessedAt\":{\"type\":\"datetime\",\"required\":false},\"data\":{\"type\":\"json\",\"required\":false,\"default\":{}}},\"methods\":{\"isValid\":{\"name\":\"isValid\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isExpired\":{\"name\":\"isExpired\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isRevoked\":{\"name\":\"isRevoked\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"touch\":{\"name\":\"touch\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"extend\":{\"name\":\"extend\",\"async\":false,\"parameters\":[{\"name\":\"ttlSeconds\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"recordActivity\":{\"name\":\"recordActivity\",\"async\":true,\"parameters\":[{\"name\":\"extendTtl\",\"type\":\"any\",\"optional\":true},{\"name\":\"ttlSeconds\",\"type\":\"number\",\"optional\":true}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"revoke\":{\"name\":\"revoke\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"setTenant\":{\"name\":\"setTenant\",\"async\":false,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getData\":{\"name\":\"getData\",\"async\":false,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"T | undefined\",\"isStatic\":false,\"isPublic\":true},\"setData\":{\"name\":\"setData\",\"async\":false,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"removeData\":{\"name\":\"removeData\",\"async\":false,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"sensitive\":true,\"api\":{\"include\":[\"get\",\"delete\"]},\"mcp\":{\"include\":[]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"Session\",\"collectionExportName\":\"SessionCollection\",\"schema\":{\"tableName\":\"sessions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"sessions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"user_id\\\" UUID,\\n \\\"tenant_id\\\" UUID,\\n \\\"status\\\" TEXT,\\n \\\"expires_at\\\" TIMESTAMP,\\n \\\"user_agent\\\" TEXT DEFAULT '',\\n \\\"ip_address\\\" TEXT DEFAULT '',\\n \\\"last_accessed_at\\\" TIMESTAMP,\\n \\\"data\\\" JSON DEFAULT '{}'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"user_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"users\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"user_agent\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"ip_address\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"last_accessed_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"data\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":{}}},\"indexes\":[{\"name\":\"sessions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"sessions_expires_at_idx\",\"columns\":[\"expires_at\"]},{\"name\":\"sessions_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"sessions_user_id_idx\",\"columns\":[\"user_id\"]},{\"name\":\"sessions_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"dc55d351\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:Tenant\":{\"name\":\"tenant\",\"className\":\"Tenant\",\"qualifiedName\":\"@happyvertical/smrt-users:Tenant\",\"collection\":\"tenants\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/Tenant.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"status\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"parentTenantId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Tenant\",\"_meta\":{\"nullable\":true}},\"hierarchyLevel\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"hierarchyPath\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"cascadePermissions\":{\"type\":\"boolean\",\"required\":false,\"default\":true},\"inheritPermissions\":{\"type\":\"boolean\",\"required\":false,\"default\":true}},\"methods\":{\"isActive\":{\"name\":\"isActive\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isSuspended\":{\"name\":\"isSuspended\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isRoot\":{\"name\":\"isRoot\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"canCascadeToChildren\":{\"name\":\"canCascadeToChildren\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"acceptsInheritance\":{\"name\":\"acceptsInheritance\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SmrtSaveOptions\",\"optional\":true}],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"getAncestorIds\":{\"name\":\"getAncestorIds\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"Tenant\",\"collectionExportName\":\"TenantCollection\",\"schema\":{\"tableName\":\"tenants\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tenants\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"status\\\" TEXT,\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"parent_tenant_id\\\" UUID,\\n \\\"hierarchy_level\\\" INTEGER DEFAULT 0,\\n \\\"hierarchy_path\\\" TEXT DEFAULT '',\\n \\\"cascade_permissions\\\" BOOLEAN DEFAULT TRUE,\\n \\\"inherit_permissions\\\" BOOLEAN DEFAULT TRUE\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"status\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"parent_tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"hierarchy_level\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"hierarchy_path\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"cascade_permissions\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true},\"inherit_permissions\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true}},\"indexes\":[{\"name\":\"tenants_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"tenants_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"tenants_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"tenants_parent_tenant_id_idx\",\"columns\":[\"parent_tenant_id\"]}],\"version\":\"934f7025\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:TenantIntegration\":{\"name\":\"tenantintegration\",\"className\":\"TenantIntegration\",\"qualifiedName\":\"@happyvertical/smrt-users:TenantIntegration\",\"collection\":\"tenantintegrations\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/TenantIntegration.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"sqlType\":\"UUID\",\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":true,\"autoPopulate\":true,\"nullable\":false,\"mode\":\"required\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"provider\":{\"type\":\"text\",\"required\":false,\"default\":\"aws\"},\"externalIds\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"unprovisioned\"},\"lastCheckedAt\":{\"type\":\"datetime\",\"required\":false},\"lastCheckSummary\":{\"type\":\"text\",\"required\":false},\"lastError\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"getExternalIds\":{\"name\":\"getExternalIds\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, string>\",\"isStatic\":false,\"isPublic\":true},\"setExternalIds\":{\"name\":\"setExternalIds\",\"async\":false,\"parameters\":[{\"name\":\"externalIds\",\"type\":\"Record<string, string> | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Record<string, string>\"},{\"type\":\"string\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getExternalId\":{\"name\":\"getExternalId\",\"async\":false,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"string | undefined\",\"isStatic\":false,\"isPublic\":true},\"setExternalId\":{\"name\":\"setExternalId\",\"async\":false,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"string | undefined\",\"optional\":false,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"undefined\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getLastCheckSummary\":{\"name\":\"getLastCheckSummary\",\"async\":false,\"parameters\":[],\"returnType\":\"TenantIntegrationCheckSummary[]\",\"isStatic\":false,\"isPublic\":true},\"setLastCheckSummary\":{\"name\":\"setLastCheckSummary\",\"async\":false,\"parameters\":[{\"name\":\"summary\",\"type\":\"TenantIntegrationCheckSummary[] | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"TenantIntegrationCheckSummary[]\"},{\"type\":\"string\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"recordDoctorRun\":{\"name\":\"recordDoctorRun\",\"async\":false,\"parameters\":[{\"name\":\"outcome\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"TenantIntegrationStatus\",\"TenantIntegrationCheckSummary[]\",\"string | null\"]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"tenant_integrations\",\"conflictColumns\":[\"tenant_id\",\"provider\"],\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"required\"}},\"extends\":\"SmrtObject\",\"exportName\":\"TenantIntegration\",\"collectionExportName\":\"TenantIntegrationCollection\",\"validationRules\":[],\"schema\":{\"tableName\":\"tenant_integrations\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tenant_integrations\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"provider\\\" TEXT DEFAULT 'aws',\\n \\\"external_ids\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'unprovisioned',\\n \\\"last_checked_at\\\" TIMESTAMP,\\n \\\"last_check_summary\\\" TEXT,\\n \\\"last_error\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":true,\"unique\":false},\"provider\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"aws\"},\"external_ids\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"unprovisioned\"},\"last_checked_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"last_check_summary\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_error\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"tenant_integrations_tenant_id_provider_idx\",\"columns\":[\"tenant_id\",\"provider\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"tenant_integrations_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"tenant_integrations_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"3ed31966\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:TenantPermissionOverride\":{\"name\":\"tenantpermissionoverride\",\"className\":\"TenantPermissionOverride\",\"qualifiedName\":\"@happyvertical/smrt-users:TenantPermissionOverride\",\"collection\":\"tenantpermissionoverrides\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/TenantPermissionOverride.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"tenantId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Tenant\",\"_meta\":{\"required\":true}},\"permissionId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Permission\",\"_meta\":{\"required\":true}},\"effect\":{\"type\":\"text\",\"required\":false,\"_meta\":{}}},\"methods\":{\"isInherit\":{\"name\":\"isInherit\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isGrant\":{\"name\":\"isGrant\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isDeny\":{\"name\":\"isDeny\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"hasExplicitEffect\":{\"name\":\"hasExplicitEffect\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"TenantPermissionOverride\",\"collectionExportName\":\"TenantPermissionOverrideCollection\",\"validationRules\":[{\"field\":\"tenantId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"permissionId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"tenant_permission_overrides\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"tenant_permission_overrides\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID NOT NULL,\\n \\\"permission_id\\\" UUID NOT NULL,\\n \\\"effect\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"tenants\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"permission_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"permissions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"effect\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"tenant_permission_overrides_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"tenant_permission_overrides_created_at_idx\",\"columns\":[\"created_at\"]},{\"name\":\"tenant_permission_overrides_tenant_id_idx\",\"columns\":[\"tenant_id\"]},{\"name\":\"tenant_permission_overrides_permission_id_idx\",\"columns\":[\"permission_id\"]}],\"version\":\"95b78bdd\"},\"importPath\":\"@happyvertical/smrt-users\"},\"@happyvertical/smrt-users:User\":{\"name\":\"user\",\"className\":\"User\",\"qualifiedName\":\"@happyvertical/smrt-users:User\",\"collection\":\"users\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/users/src/models/User.ts\",\"packageName\":\"@happyvertical/smrt-users\",\"fields\":{\"profileId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-profiles:Profile\",\"_meta\":{\"unique\":true}},\"email\":{\"type\":\"text\",\"required\":false,\"default\":\"\",\"_meta\":{\"indexed\":true}},\"emailKey\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"nullable\":true,\"unique\":true,\"readonly\":true},\"readonly\":true},\"status\":{\"type\":\"text\",\"required\":false,\"_meta\":{}},\"lastLoginAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"hasValidEmail\":{\"name\":\"hasValidEmail\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isActive\":{\"name\":\"isActive\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isSuspended\":{\"name\":\"isSuspended\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isPending\":{\"name\":\"isPending\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"recordLogin\":{\"name\":\"recordLogin\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true}},\"extends\":\"SmrtObject\",\"exportName\":\"User\",\"collectionExportName\":\"UserCollection\",\"schema\":{\"tableName\":\"users\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"users\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID UNIQUE,\\n \\\"email\\\" TEXT DEFAULT '',\\n \\\"email_key\\\" TEXT UNIQUE,\\n \\\"status\\\" TEXT,\\n \\\"last_login_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":true},\"email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"email_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":true},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_login_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"users_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"users_email_idx\",\"columns\":[\"email\"]},{\"name\":\"users_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"38fd1677\"},\"importPath\":\"@happyvertical/smrt-users\"}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-mobile-contract\",\"@happyvertical/smrt-profiles\",\"@happyvertical/smrt-tenancy\"]}"));
1598
+ var __defProp$13 = Object.defineProperty;
1599
+ var __getOwnPropDesc$13 = Object.getOwnPropertyDescriptor;
1600
+ var __decorateClass$13 = (decorators, target, key, kind) => {
1601
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$13(target, key) : target;
1602
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1603
+ if (kind && result) __defProp$13(target, key, result);
1604
+ return result;
1605
+ };
1606
+ var UsersCliAuthRequest = class extends SmrtObject {
1607
+ userCode = "";
1608
+ deviceCodeHash = "";
1609
+ status = "pending";
1610
+ userId = null;
1611
+ tenantId = null;
1612
+ sessionId = null;
1613
+ expiresAt = /* @__PURE__ */ new Date();
1614
+ approvedAt = null;
1615
+ };
1616
+ __decorateClass$13([field({
1617
+ type: "text",
1618
+ required: true,
1619
+ unique: true
1620
+ })], UsersCliAuthRequest.prototype, "userCode", 2);
1621
+ __decorateClass$13([field({
1622
+ type: "text",
1623
+ required: true,
1624
+ unique: true
1625
+ })], UsersCliAuthRequest.prototype, "deviceCodeHash", 2);
1626
+ __decorateClass$13([field({ type: "text" })], UsersCliAuthRequest.prototype, "status", 2);
1627
+ __decorateClass$13([foreignKey("User", { nullable: true })], UsersCliAuthRequest.prototype, "userId", 2);
1628
+ __decorateClass$13([foreignKey("Tenant", { nullable: true })], UsersCliAuthRequest.prototype, "tenantId", 2);
1629
+ __decorateClass$13([foreignKey("Session", { nullable: true })], UsersCliAuthRequest.prototype, "sessionId", 2);
1630
+ __decorateClass$13([field({
1631
+ type: "datetime",
1632
+ indexed: true
1633
+ })], UsersCliAuthRequest.prototype, "expiresAt", 2);
1634
+ __decorateClass$13([field({
1635
+ type: "datetime",
1636
+ nullable: true
1637
+ })], UsersCliAuthRequest.prototype, "approvedAt", 2);
1638
+ UsersCliAuthRequest = __decorateClass$13([smrt({
1639
+ tableName: "users_cli_auth_requests",
1640
+ sensitive: true,
1641
+ api: { include: [] },
1642
+ cli: { include: [] },
1643
+ mcp: { include: [] }
1644
+ })], UsersCliAuthRequest);
1645
+ var __defProp$12 = Object.defineProperty;
1646
+ var __getOwnPropDesc$12 = Object.getOwnPropertyDescriptor;
1647
+ var __decorateClass$12 = (decorators, target, key, kind) => {
1648
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$12(target, key) : target;
1649
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1650
+ if (kind && result) __defProp$12(target, key, result);
1651
+ return result;
1652
+ };
1653
+ var DEFAULT_SESSION_TTL = 10080 * 60;
1654
+ function generateSessionId() {
1655
+ return crypto.randomUUID();
1656
+ }
1657
+ var Session = class extends SmrtObject {
1658
+ userId = "";
1659
+ tenantId = null;
1660
+ status = SessionStatus.ACTIVE;
1661
+ expiresAt = /* @__PURE__ */ new Date();
1662
+ /**
1663
+ * User agent string from the browser
1664
+ */
1665
+ userAgent = "";
1666
+ /**
1667
+ * IP address of the client
1668
+ */
1669
+ ipAddress = "";
1670
+ /**
1671
+ * Last activity timestamp (updated on each request)
1672
+ */
1673
+ lastAccessedAt = /* @__PURE__ */ new Date();
1674
+ /**
1675
+ * Custom session data (JSON serializable)
1676
+ */
1677
+ data = {};
1678
+ constructor(options = {}) {
1679
+ super(options);
1680
+ if (options.userId !== void 0) this.userId = options.userId;
1681
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
1682
+ if (options.status !== void 0) this.status = options.status;
1683
+ if (options.expiresAt !== void 0) this.expiresAt = options.expiresAt instanceof Date ? options.expiresAt : new Date(options.expiresAt);
1684
+ if (options.userAgent !== void 0) this.userAgent = options.userAgent;
1685
+ if (options.ipAddress !== void 0) this.ipAddress = options.ipAddress;
1686
+ if (options.lastAccessedAt !== void 0) this.lastAccessedAt = options.lastAccessedAt instanceof Date ? options.lastAccessedAt : new Date(options.lastAccessedAt);
1687
+ if (options.data !== void 0) this.data = options.data;
1688
+ }
1689
+ /**
1690
+ * Check if the session is currently valid (active and not expired)
1691
+ */
1692
+ isValid() {
1693
+ return this.status === SessionStatus.ACTIVE && /* @__PURE__ */ new Date() < this.expiresAt;
1694
+ }
1695
+ /**
1696
+ * Check if the session has expired
1697
+ */
1698
+ isExpired() {
1699
+ return /* @__PURE__ */ new Date() >= this.expiresAt;
1700
+ }
1701
+ /**
1702
+ * Check if the session was revoked
1703
+ */
1704
+ isRevoked() {
1705
+ return this.status === SessionStatus.REVOKED;
1706
+ }
1707
+ /**
1708
+ * Update the last accessed timestamp
1709
+ */
1710
+ touch() {
1711
+ this.lastAccessedAt = /* @__PURE__ */ new Date();
1712
+ }
1713
+ /**
1714
+ * Extend the session expiration by the given TTL (in seconds)
1715
+ */
1716
+ extend(ttlSeconds = DEFAULT_SESSION_TTL) {
1717
+ this.expiresAt = new Date(Date.now() + ttlSeconds * 1e3);
1718
+ this.touch();
1719
+ }
1720
+ /** Persist routine session activity without failing concurrent requests. */
1721
+ async recordActivity(extendTtl = false, ttlSeconds = DEFAULT_SESSION_TTL) {
1722
+ for (let attempt = 0; attempt < 4; attempt += 1) {
1723
+ if (attempt > 0 && !await this.reloadValidActivityState()) return false;
1724
+ if (extendTtl) this.extend(ttlSeconds);
1725
+ else this.touch();
1726
+ try {
1727
+ await this.save();
1728
+ return true;
1729
+ } catch (error) {
1730
+ if (!(error instanceof Error && "code" in error && error.code === "RUNTIME_REVISION_CONFLICT")) throw error;
1731
+ if (attempt === 3) return this.reloadValidActivityState();
1732
+ }
1733
+ }
1734
+ return false;
1735
+ }
1736
+ async reloadValidActivityState() {
1737
+ if (!this.id) return false;
1738
+ const current = await this.getCanonicalPersistedRow({ id: this.id });
1739
+ if (!current) return false;
1740
+ await this.loadDataFromDb(current);
1741
+ return this.isValid();
1742
+ }
1743
+ /**
1744
+ * Revoke the session
1745
+ */
1746
+ revoke() {
1747
+ this.status = SessionStatus.REVOKED;
1748
+ }
1749
+ /**
1750
+ * Set the tenant context for this session
1751
+ */
1752
+ setTenant(tenantId) {
1753
+ this.tenantId = tenantId;
1754
+ }
1755
+ /**
1756
+ * Get or set custom session data
1757
+ */
1758
+ getData(key) {
1759
+ return this.data[key];
1760
+ }
1761
+ /**
1762
+ * Set custom session data
1763
+ */
1764
+ setData(key, value) {
1765
+ this.data[key] = value;
1766
+ }
1767
+ /**
1768
+ * Remove custom session data
1769
+ */
1770
+ removeData(key) {
1771
+ delete this.data[key];
1772
+ }
1773
+ };
1774
+ __decorateClass$12([foreignKey("User")], Session.prototype, "userId", 2);
1775
+ __decorateClass$12([foreignKey("Tenant", { nullable: true })], Session.prototype, "tenantId", 2);
1776
+ __decorateClass$12([field({ type: "text" })], Session.prototype, "status", 2);
1777
+ __decorateClass$12([field({
1778
+ type: "datetime",
1779
+ indexed: true
1780
+ })], Session.prototype, "expiresAt", 2);
1781
+ Session = __decorateClass$12([smrt({
1782
+ sensitive: true,
1783
+ api: { include: ["get", "delete"] },
1784
+ mcp: { include: [] },
1785
+ cli: { skipApiCheck: true }
1786
+ })], Session);
1787
+ var SessionCollection = class extends SmrtCollection {
1788
+ static _itemClass = Session;
1789
+ async revokeWithRetry(sessionId) {
1790
+ for (let attempt = 0; attempt < 4; attempt += 1) {
1791
+ const session = await this.get(sessionId);
1792
+ if (!session) return false;
1793
+ if (session.status !== SessionStatus.ACTIVE) return true;
1794
+ session.revoke();
1795
+ try {
1796
+ await session.save();
1797
+ return true;
1798
+ } catch (error) {
1799
+ if (attempt === 3 || !(error instanceof Error && "code" in error && error.code === "RUNTIME_REVISION_CONFLICT")) throw error;
1800
+ }
1801
+ }
1802
+ return false;
1803
+ }
1804
+ /**
1805
+ * Create a new session with a secure ID
1806
+ */
1807
+ async createSession(options) {
1808
+ const ttl = options.ttl ?? 604800;
1809
+ const expiresAt = new Date(Date.now() + ttl * 1e3);
1810
+ const session = await this.create({
1811
+ id: generateSessionId(),
1812
+ userId: options.userId,
1813
+ tenantId: options.tenantId ?? null,
1814
+ status: SessionStatus.ACTIVE,
1815
+ expiresAt,
1816
+ userAgent: options.userAgent ?? "",
1817
+ ipAddress: options.ipAddress ?? "",
1818
+ lastAccessedAt: /* @__PURE__ */ new Date(),
1819
+ data: options.data ?? {}
1820
+ });
1821
+ await session.save();
1822
+ return session;
1823
+ }
1824
+ /**
1825
+ * Find a valid session by ID
1826
+ * Returns null if session doesn't exist, is expired, or is revoked
1827
+ */
1828
+ async findValidSession(sessionId) {
1829
+ const session = await this.get(sessionId);
1830
+ if (!session) return null;
1831
+ if (!session.isValid()) {
1832
+ if (session.isExpired() && session.status === SessionStatus.ACTIVE) {
1833
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1834
+ await this.db.query(`UPDATE ${this.tableName}
1835
+ SET status = ?, updated_at = ?
1836
+ WHERE id = ? AND status = ? AND expires_at < ?`, SessionStatus.EXPIRED, now, sessionId, SessionStatus.ACTIVE, now);
1837
+ }
1838
+ return null;
1839
+ }
1840
+ return session;
1841
+ }
1842
+ /**
1843
+ * Update last accessed time and optionally extend session
1844
+ */
1845
+ async touch(sessionId, extendTtl = false, ttl = DEFAULT_SESSION_TTL) {
1846
+ const session = await this.findValidSession(sessionId);
1847
+ if (!session) return false;
1848
+ return session.recordActivity(extendTtl, ttl);
1849
+ }
1850
+ /**
1851
+ * Find all active sessions for a user
1852
+ */
1853
+ async findByUser(userId) {
1854
+ return (await this.list({
1855
+ where: {
1856
+ userId,
1857
+ status: SessionStatus.ACTIVE
1858
+ },
1859
+ orderBy: "last_accessed_at DESC"
1860
+ })).filter((session) => session.isValid());
1861
+ }
1862
+ /**
1863
+ * Delete all sessions for a user (logout from all devices)
1864
+ */
1865
+ async deleteUserSessions(userId) {
1866
+ const sessions = await this.list({ where: { userId } });
1867
+ let count = 0;
1868
+ for (const session of sessions) {
1869
+ await session.delete();
1870
+ count++;
1871
+ }
1872
+ return count;
1873
+ }
1874
+ /**
1875
+ * Revoke all sessions for a user (soft delete)
1876
+ */
1877
+ async revokeUserSessions(userId) {
1878
+ const sessions = await this.list({ where: {
1879
+ userId,
1880
+ status: SessionStatus.ACTIVE
1881
+ } });
1882
+ let count = 0;
1883
+ for (const session of sessions) if (session.id && await this.revokeWithRetry(session.id)) count++;
1884
+ return count;
1885
+ }
1886
+ /**
1887
+ * Revoke a specific session
1888
+ */
1889
+ async revokeSession(sessionId) {
1890
+ return this.revokeWithRetry(sessionId);
1891
+ }
1892
+ /**
1893
+ * Delete expired sessions (cleanup job)
1894
+ *
1895
+ * Scheduled by the framework retention sweep (#2375); `expires_at` carries
1896
+ * an index for this predicate.
1897
+ *
1898
+ * @param options.dryRun - Count the sessions the predicate selects without
1899
+ * deleting them.
1900
+ * @returns Number of sessions deleted (or, under `dryRun`, matched)
1901
+ */
1902
+ async deleteExpired(options = {}) {
1903
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1904
+ const predicate = "expires_at < ? OR status = ?";
1905
+ const counted = await this.db.query(`SELECT COUNT(*) AS total FROM ${this.tableName} WHERE ${predicate}`, now, SessionStatus.REVOKED);
1906
+ const total = Number(counted.rows?.[0]?.total ?? 0);
1907
+ if (!Number.isFinite(total) || total <= 0) return 0;
1908
+ if (!options.dryRun) await this.db.query(`DELETE FROM ${this.tableName} WHERE ${predicate}`, now, SessionStatus.REVOKED);
1909
+ return total;
1910
+ }
1911
+ /**
1912
+ * Count active sessions for a user
1913
+ */
1914
+ async countUserSessions(userId) {
1915
+ return (await this.findByUser(userId)).length;
1916
+ }
1917
+ /**
1918
+ * Update tenant context for a session (low-level primitive).
1919
+ *
1920
+ * SECURITY (#1400): this does NOT verify that the session's user is a member
1921
+ * of `tenantId` — it is the unguarded storage primitive. Application/route
1922
+ * code must go through {@link SessionService.switchTenant}, which fail-closes
1923
+ * on a missing/inactive membership before calling this. Calling it directly
1924
+ * with an untrusted `tenantId` reintroduces the cross-tenant access bug.
1925
+ */
1926
+ async setSessionTenant(sessionId, tenantId) {
1927
+ const session = await this.findValidSession(sessionId);
1928
+ if (!session) return false;
1929
+ session.setTenant(tenantId);
1930
+ await session.save();
1931
+ return true;
1932
+ }
1933
+ /**
1934
+ * Set custom session data
1935
+ */
1936
+ async setSessionData(sessionId, key, value) {
1937
+ const session = await this.findValidSession(sessionId);
1938
+ if (!session) return false;
1939
+ session.setData(key, value);
1940
+ await session.save();
1941
+ return true;
1942
+ }
1943
+ /**
1944
+ * Get custom session data
1945
+ */
1946
+ async getSessionData(sessionId, key) {
1947
+ const session = await this.findValidSession(sessionId);
1948
+ if (!session) return void 0;
1949
+ return session.getData(key);
1950
+ }
1951
+ };
1952
+ var CliAuthApprovalLostError = class extends Error {};
1953
+ var UsersCliAuthRequestCollection = class extends SmrtCollection {
1954
+ static _itemClass = UsersCliAuthRequest;
1955
+ /**
1956
+ * Atomically approve one pending request and mint its bearer session.
1957
+ *
1958
+ * The session is created inside the same transaction as the conditional
1959
+ * pending-to-approved transition. If another approver wins, or persisting
1960
+ * the approval fails, throwing rolls the losing session back with the
1961
+ * request write so no usable orphan credential can remain.
1962
+ */
1963
+ async approvePendingRequest(input) {
1964
+ const transaction = this.db.transaction?.bind(this.db);
1965
+ if (!transaction) throw new Error("Terminal approval requires database transaction support.");
1966
+ try {
1967
+ return await transaction(async (tx) => {
1968
+ const createdSessionId = (await (await SessionCollection.create({ db: tx })).createSession({
1969
+ data: {
1970
+ approvedBy: input.approvedBy,
1971
+ kind: "terminal"
1972
+ },
1973
+ ipAddress: input.ipAddress,
1974
+ tenantId: input.tenantId,
1975
+ ttl: input.sessionTtlSeconds,
1976
+ userAgent: input.userAgent,
1977
+ userId: input.userId
1978
+ })).id;
1979
+ if (!createdSessionId) throw new Error("Terminal approval failed to mint a session.");
1980
+ const approvedAt = /* @__PURE__ */ new Date();
1981
+ const now = approvedAt.toISOString();
1982
+ const approved = await tx.query(`UPDATE ${this.tableName}
1983
+ SET approved_at = ?, session_id = ?, status = 'approved',
1984
+ tenant_id = ?, user_id = ?, updated_at = ?
1985
+ WHERE user_code = ? AND status = 'pending' AND expires_at > ?
1986
+ RETURNING id`, now, createdSessionId, input.tenantId, input.userId, now, input.userCode.trim().toUpperCase(), now);
1987
+ if (approved.rows?.length !== 1) throw new CliAuthApprovalLostError();
1988
+ const id = approved.rows[0]?.id;
1989
+ if (typeof id !== "string") throw new Error("Terminal approval did not return its request id.");
1990
+ return {
1991
+ approvedAt,
1992
+ id,
1993
+ sessionId: createdSessionId,
1994
+ tenantId: input.tenantId,
1995
+ userId: input.userId
1996
+ };
1997
+ });
1998
+ } catch (error) {
1999
+ if (error instanceof CliAuthApprovalLostError) return null;
2000
+ throw error;
2001
+ }
2002
+ }
2003
+ /**
2004
+ * Atomically consume the bearer session attached to an approved request.
2005
+ *
2006
+ * The conditional update is the arbiter: concurrent exchangers may observe
2007
+ * the same candidate, but only one can change `approved` to `consumed` while
2008
+ * matching the same session id. The winning transaction returns the token
2009
+ * from its locked candidate and clears it from durable storage.
2010
+ */
2011
+ async consumeApprovedSession(deviceCodeHash) {
2012
+ const transaction = this.db.transaction?.bind(this.db);
2013
+ if (!transaction) throw new Error("Terminal device exchange requires database transaction support.");
2014
+ return transaction(async (tx) => {
2015
+ const candidate = (await tx.query(`SELECT id, session_id FROM ${this.tableName}
2016
+ WHERE device_code_hash = ? AND status = 'approved' AND session_id IS NOT NULL
2017
+ LIMIT 1`, deviceCodeHash)).rows?.[0];
2018
+ const id = typeof candidate?.id === "string" ? candidate.id : null;
2019
+ const sessionId = typeof candidate?.session_id === "string" ? candidate.session_id : null;
2020
+ if (!id || !sessionId) return null;
2021
+ return (await tx.query(`UPDATE ${this.tableName}
2022
+ SET status = 'consumed', session_id = NULL, updated_at = ?
2023
+ WHERE id = ? AND status = 'approved' AND session_id = ?
2024
+ RETURNING id`, (/* @__PURE__ */ new Date()).toISOString(), id, sessionId)).rows?.length === 1 ? sessionId : null;
2025
+ });
2026
+ }
2027
+ /**
2028
+ * Look up a pending or completed request by the short user code shown in the CLI.
2029
+ */
2030
+ async findByUserCode(userCode) {
2031
+ const [request] = await this.list({
2032
+ limit: 1,
2033
+ where: { userCode: userCode.trim().toUpperCase() }
2034
+ });
2035
+ return request ?? null;
2036
+ }
2037
+ /**
2038
+ * Look up a request by the hash of its device code (the CLI's polling key).
2039
+ */
2040
+ async findByDeviceCodeHash(deviceCodeHash) {
2041
+ const [request] = await this.list({
2042
+ limit: 1,
2043
+ where: { deviceCodeHash }
2044
+ });
2045
+ return request ?? null;
2046
+ }
2047
+ /**
2048
+ * Delete expired pending, lazily-expired, or already-consumed requests.
2049
+ *
2050
+ * Scheduled by the framework retention sweep (#2375); `expiresAt` carries an
2051
+ * index for this predicate.
2052
+ *
2053
+ * @param options.dryRun - Count the requests the predicate selects without
2054
+ * deleting them.
2055
+ * @returns Number of requests deleted (or, under `dryRun`, matched)
2056
+ */
2057
+ async deleteExpired(options = {}) {
2058
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2059
+ const predicate = "status IN ('pending', 'expired', 'consumed') AND expires_at < ?";
2060
+ const counted = await this.db.query(`SELECT COUNT(*) AS total FROM ${this.tableName} WHERE ${predicate}`, now);
2061
+ const total = Number(counted.rows?.[0]?.total ?? 0);
2062
+ if (!Number.isFinite(total) || total <= 0) return 0;
2063
+ if (!options.dryRun) await this.db.query(`DELETE FROM ${this.tableName} WHERE ${predicate}`, now);
2064
+ return total;
2065
+ }
2066
+ };
2067
+ var __defProp$11 = Object.defineProperty;
2068
+ var __getOwnPropDesc$11 = Object.getOwnPropertyDescriptor;
2069
+ var __decorateClass$11 = (decorators, target, key, kind) => {
2070
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$11(target, key) : target;
2071
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2072
+ if (kind && result) __defProp$11(target, key, result);
2073
+ return result;
2074
+ };
2075
+ var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2076
+ function isValidEmail(email) {
2077
+ if (!email || typeof email !== "string") return false;
2078
+ return EMAIL_REGEX.test(email.trim());
2079
+ }
2080
+ function normalizeEmail(email) {
2081
+ if (!email || typeof email !== "string") return "";
2082
+ return email.trim() ? normalizeIdentityEmail(email) : "";
2083
+ }
2084
+ var User = class extends SmrtObject {
2085
+ profileId = "";
2086
+ email = "";
2087
+ emailKey = null;
2088
+ status = UserStatus.ACTIVE;
2089
+ /**
2090
+ * Last login timestamp
2091
+ */
2092
+ lastLoginAt = null;
2093
+ constructor(options = {}) {
2094
+ super(options);
2095
+ if (options.profileId !== void 0) this.profileId = options.profileId;
2096
+ if (options.email !== void 0) this.email = normalizeEmail(options.email);
2097
+ if (options.status !== void 0) this.status = options.status;
2098
+ if (options.lastLoginAt !== void 0) this.lastLoginAt = options.lastLoginAt;
2099
+ }
2100
+ /**
2101
+ * Validate the user's email format.
2102
+ * @returns true if email is valid
2103
+ */
2104
+ hasValidEmail() {
2105
+ return isValidEmail(this.email);
2106
+ }
2107
+ /**
2108
+ * Check if user is active
2109
+ */
2110
+ isActive() {
2111
+ return this.status === UserStatus.ACTIVE;
2112
+ }
2113
+ /**
2114
+ * Check if user is suspended
2115
+ */
2116
+ isSuspended() {
2117
+ return this.status === UserStatus.SUSPENDED;
2118
+ }
2119
+ /**
2120
+ * Check if user is pending verification
2121
+ */
2122
+ isPending() {
2123
+ return this.status === UserStatus.PENDING;
2124
+ }
2125
+ /**
2126
+ * Record a login event
2127
+ */
2128
+ recordLogin() {
2129
+ this.lastLoginAt = /* @__PURE__ */ new Date();
2130
+ }
2131
+ /** Keep the durable email key derived from the public email field. */
2132
+ async save() {
2133
+ this.email = normalizeEmail(this.email);
2134
+ this.emailKey = this.email || null;
2135
+ return super.save();
2136
+ }
2137
+ };
2138
+ __decorateClass$11([crossPackageRef("@happyvertical/smrt-profiles:Profile", { unique: true })], User.prototype, "profileId", 2);
2139
+ __decorateClass$11([field({ indexed: true })], User.prototype, "email", 2);
2140
+ __decorateClass$11([field({
2141
+ type: "text",
2142
+ nullable: true,
2143
+ unique: true,
2144
+ readonly: true
2145
+ })], User.prototype, "emailKey", 2);
2146
+ __decorateClass$11([field({ type: "text" })], User.prototype, "status", 2);
2147
+ User = __decorateClass$11([smrt({
2148
+ api: { include: ["list", "get"] },
2149
+ mcp: { include: ["list", "get"] },
2150
+ cli: { skipApiCheck: true }
2151
+ })], User);
2152
+ var __defProp$10 = Object.defineProperty;
2153
+ var __getOwnPropDesc$10 = Object.getOwnPropertyDescriptor;
2154
+ var __decorateClass$10 = (decorators, target, key, kind) => {
2155
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$10(target, key) : target;
2156
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2157
+ if (kind && result) __defProp$10(target, key, result);
2158
+ return result;
2159
+ };
2160
+ var UsersCliAuthApproveLimit = class extends SmrtObject {
2161
+ userId = "";
2162
+ attemptCount = 0;
2163
+ windowStartedAt = /* @__PURE__ */ new Date();
2164
+ };
2165
+ __decorateClass$10([foreignKey("User", {
2166
+ required: true,
2167
+ unique: true
2168
+ })], UsersCliAuthApproveLimit.prototype, "userId", 2);
2169
+ __decorateClass$10([field({
2170
+ type: "integer",
2171
+ required: true,
2172
+ default: 0
2173
+ })], UsersCliAuthApproveLimit.prototype, "attemptCount", 2);
2174
+ __decorateClass$10([field({
2175
+ type: "datetime",
2176
+ required: true
2177
+ })], UsersCliAuthApproveLimit.prototype, "windowStartedAt", 2);
2178
+ UsersCliAuthApproveLimit = __decorateClass$10([smrt({
2179
+ tableName: "users_cli_auth_approve_limits",
2180
+ api: false,
2181
+ cli: false,
2182
+ mcp: false
2183
+ })], UsersCliAuthApproveLimit);
2184
+ var __defProp$9 = Object.defineProperty;
2185
+ var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
2186
+ var __decorateClass$9 = (decorators, target, key, kind) => {
2187
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$9(target, key) : target;
2188
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2189
+ if (kind && result) __defProp$9(target, key, result);
2190
+ return result;
2191
+ };
2192
+ var Group = class extends SmrtObject {
2193
+ tenantId;
2194
+ /**
2195
+ * Display name for the group
2196
+ */
2197
+ name = "";
2198
+ /**
2199
+ * Description of the group
2200
+ */
2201
+ description = "";
2202
+ constructor(options = {}) {
2203
+ super(options);
2204
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
2205
+ if (options.name !== void 0) this.name = options.name;
2206
+ if (options.description !== void 0) this.description = options.description;
2207
+ }
2208
+ };
2209
+ __decorateClass$9([foreignKey("Tenant", { required: true })], Group.prototype, "tenantId", 2);
2210
+ Group = __decorateClass$9([smrt({
2211
+ api: { include: ["list", "get"] },
2212
+ mcp: { include: ["list", "get"] },
2213
+ cli: true
2214
+ })], Group);
2215
+ var __defProp$8 = Object.defineProperty;
2216
+ var __getOwnPropDesc$8 = Object.getOwnPropertyDescriptor;
2217
+ var __decorateClass$8 = (decorators, target, key, kind) => {
2218
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$8(target, key) : target;
2219
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2220
+ if (kind && result) __defProp$8(target, key, result);
2221
+ return result;
2222
+ };
2223
+ var GroupMember = class extends SmrtObject {
2224
+ groupId;
2225
+ userId;
2226
+ constructor(options = {}) {
2227
+ super(options);
2228
+ if (options.groupId !== void 0) this.groupId = options.groupId;
2229
+ if (options.userId !== void 0) this.userId = options.userId;
2230
+ }
2231
+ };
2232
+ __decorateClass$8([foreignKey("Group", { required: true })], GroupMember.prototype, "groupId", 2);
2233
+ __decorateClass$8([foreignKey("User", { required: true })], GroupMember.prototype, "userId", 2);
2234
+ GroupMember = __decorateClass$8([smrt({
2235
+ api: { include: ["list", "get"] },
2236
+ mcp: { include: ["list", "get"] },
2237
+ cli: true
2238
+ })], GroupMember);
2239
+ var __defProp$7 = Object.defineProperty;
2240
+ var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
2241
+ var __decorateClass$7 = (decorators, target, key, kind) => {
2242
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
2243
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2244
+ if (kind && result) __defProp$7(target, key, result);
2245
+ return result;
2246
+ };
2247
+ var GroupRole = class extends SmrtObject {
2248
+ groupId;
2249
+ roleId;
2250
+ constructor(options = {}) {
2251
+ super(options);
2252
+ if (options.groupId !== void 0) this.groupId = options.groupId;
2253
+ if (options.roleId !== void 0) this.roleId = options.roleId;
2254
+ }
2255
+ };
2256
+ __decorateClass$7([foreignKey("Group", { required: true })], GroupRole.prototype, "groupId", 2);
2257
+ __decorateClass$7([foreignKey("Role", { required: true })], GroupRole.prototype, "roleId", 2);
2258
+ GroupRole = __decorateClass$7([smrt({
2259
+ api: { include: ["list", "get"] },
2260
+ mcp: { include: ["list", "get"] },
2261
+ cli: true
2262
+ })], GroupRole);
2263
+ var __defProp$6 = Object.defineProperty;
2264
+ var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
2265
+ var __decorateClass$6 = (decorators, target, key, kind) => {
2266
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
2267
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2268
+ if (kind && result) __defProp$6(target, key, result);
2269
+ return result;
2270
+ };
2271
+ var Membership = class extends SmrtObject {
2272
+ userId;
2273
+ tenantId;
2274
+ roleId;
2275
+ status = MembershipStatus.ACTIVE;
2276
+ constructor(options = {}) {
2277
+ super(options);
2278
+ if (options.userId !== void 0) this.userId = options.userId;
2279
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
2280
+ if (options.roleId !== void 0) this.roleId = options.roleId;
2281
+ if (options.status !== void 0) this.status = options.status;
2282
+ }
2283
+ /**
2284
+ * Check if membership is active
2285
+ */
2286
+ isActive() {
2287
+ return this.status === MembershipStatus.ACTIVE;
2288
+ }
2289
+ /**
2290
+ * Check if membership is pending (invitation not yet accepted)
2291
+ */
2292
+ isPending() {
2293
+ return this.status === MembershipStatus.PENDING;
2294
+ }
2295
+ };
2296
+ __decorateClass$6([foreignKey("User", { required: true })], Membership.prototype, "userId", 2);
2297
+ __decorateClass$6([foreignKey("Tenant", { required: true })], Membership.prototype, "tenantId", 2);
2298
+ __decorateClass$6([foreignKey("Role", { required: true })], Membership.prototype, "roleId", 2);
2299
+ __decorateClass$6([field({ type: "text" })], Membership.prototype, "status", 2);
2300
+ Membership = __decorateClass$6([smrt({
2301
+ api: { include: ["list", "get"] },
2302
+ mcp: { include: ["list", "get"] },
2303
+ cli: { skipApiCheck: true },
2304
+ indexes: [{
2305
+ name: "memberships_tenant_id_user_id_idx",
2306
+ columns: ["tenantId", "userId"]
2307
+ }]
2308
+ })], Membership);
2309
+ var __defProp$5 = Object.defineProperty;
2310
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
2311
+ var __decorateClass$5 = (decorators, target, key, kind) => {
2312
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
2313
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2314
+ if (kind && result) __defProp$5(target, key, result);
2315
+ return result;
2316
+ };
2317
+ var MembershipOverride = class extends SmrtObject {
2318
+ membershipId;
2319
+ permissionId;
2320
+ effect = OverrideEffect.GRANT;
2321
+ constructor(options = {}) {
2322
+ super(options);
2323
+ if (options.membershipId !== void 0) this.membershipId = options.membershipId;
2324
+ if (options.permissionId !== void 0) this.permissionId = options.permissionId;
2325
+ if (options.effect !== void 0) this.effect = options.effect;
2326
+ }
2327
+ /**
2328
+ * Check if this override grants the permission
2329
+ */
2330
+ isGrant() {
2331
+ return this.effect === OverrideEffect.GRANT;
2332
+ }
2333
+ /**
2334
+ * Check if this override denies the permission
2335
+ */
2336
+ isDeny() {
2337
+ return this.effect === OverrideEffect.DENY;
2338
+ }
2339
+ };
2340
+ __decorateClass$5([foreignKey("Membership", { required: true })], MembershipOverride.prototype, "membershipId", 2);
2341
+ __decorateClass$5([foreignKey("Permission", { required: true })], MembershipOverride.prototype, "permissionId", 2);
2342
+ __decorateClass$5([field({ type: "text" })], MembershipOverride.prototype, "effect", 2);
2343
+ MembershipOverride = __decorateClass$5([smrt({
2344
+ api: { include: ["list", "get"] },
2345
+ mcp: { include: ["list", "get"] },
2346
+ cli: { skipApiCheck: true }
2347
+ })], MembershipOverride);
2348
+ var __defProp$4 = Object.defineProperty;
2349
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
2350
+ var __decorateClass$4 = (decorators, target, key, kind) => {
2351
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
2352
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2353
+ if (kind && result) __defProp$4(target, key, result);
2354
+ return result;
2355
+ };
2356
+ function parsePermissionSlug(slug) {
2357
+ const parts = slug.split(".");
2358
+ if (parts.length >= 2 && parts.every(Boolean)) return {
2359
+ resource: parts[0],
2360
+ action: parts.slice(1).join("."),
2361
+ isValid: true
2362
+ };
2363
+ return {
2364
+ resource: slug,
2365
+ action: "",
2366
+ isValid: false
2367
+ };
2368
+ }
2369
+ var Permission = class extends SmrtObject {
2370
+ /**
2371
+ * Display name for the permission
2372
+ */
2373
+ name = "";
2374
+ /**
2375
+ * Description of what this permission allows
2376
+ */
2377
+ description = "";
2378
+ /**
2379
+ * Category for grouping in UI (e.g., 'articles', 'users', 'settings')
2380
+ */
2381
+ category = "";
2382
+ constructor(options = {}) {
2383
+ super(options);
2384
+ if (options.name !== void 0) this.name = options.name;
2385
+ if (options.description !== void 0) this.description = options.description;
2386
+ if (options.category !== void 0) this.category = options.category;
2387
+ }
2388
+ /**
2389
+ * Parse the permission slug into resource and action components.
2390
+ * @returns Parsed slug with resource, action, and validation status
2391
+ */
2392
+ parseSlug() {
2393
+ return parsePermissionSlug(this.slug ?? "");
2394
+ }
2395
+ /**
2396
+ * Get the resource part of the permission slug
2397
+ * e.g., 'articles.create' -> 'articles'
2398
+ */
2399
+ getResource() {
2400
+ return this.parseSlug().resource;
2401
+ }
2402
+ /**
2403
+ * Get the action part of the permission slug
2404
+ * e.g., 'articles.create' -> 'create'
2405
+ */
2406
+ getAction() {
2407
+ return this.parseSlug().action;
2408
+ }
2409
+ /**
2410
+ * Check if the permission slug is valid (follows 'resource.action' pattern)
2411
+ */
2412
+ isValidSlug() {
2413
+ return this.parseSlug().isValid;
2414
+ }
2415
+ };
2416
+ Permission = __decorateClass$4([smrt({
2417
+ api: { include: ["list", "get"] },
2418
+ mcp: { include: ["list", "get"] },
2419
+ cli: { skipApiCheck: true }
2420
+ })], Permission);
2421
+ var __defProp$3$1 = Object.defineProperty;
2422
+ var __getOwnPropDesc$3$1 = Object.getOwnPropertyDescriptor;
2423
+ var __decorateClass$3$1 = (decorators, target, key, kind) => {
2424
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3$1(target, key) : target;
2425
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2426
+ if (kind && result) __defProp$3$1(target, key, result);
2427
+ return result;
2428
+ };
2429
+ var Role = class extends SmrtObject {
2430
+ tenantId;
2431
+ /**
2432
+ * Display name for the role
2433
+ */
2434
+ name = "";
2435
+ /**
2436
+ * Description of the role
2437
+ */
2438
+ description = "";
2439
+ /**
2440
+ * Whether this is a system role (cannot be deleted)
2441
+ */
2442
+ isSystem = false;
2443
+ /**
2444
+ * Opt-in hierarchical inheritance: when true, an ACTIVE membership holding
2445
+ * this role also resolves permissions in descendant tenants where the user
2446
+ * has no direct membership (nearest flagged ancestor membership wins).
2447
+ *
2448
+ * Default false: the role's authority is exact-tenant only, which is the
2449
+ * pre-existing resolver behavior. Flag structural roles like a network-level
2450
+ * owner/admin; leave per-tenant roles like member/viewer unflagged.
2451
+ */
2452
+ inheritsToDescendants = false;
2453
+ constructor(options = {}) {
2454
+ super(options);
2455
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
2456
+ if (options.name !== void 0) this.name = options.name;
2457
+ if (options.description !== void 0) this.description = options.description;
2458
+ if (options.isSystem !== void 0) this.isSystem = options.isSystem;
2459
+ if (options.inheritsToDescendants !== void 0) this.inheritsToDescendants = options.inheritsToDescendants;
2460
+ }
2461
+ /**
2462
+ * Check if this is a system-wide role
2463
+ */
2464
+ isSystemRole() {
2465
+ return this.tenantId === null || this.tenantId === void 0;
2466
+ }
2467
+ /**
2468
+ * Check if this is a tenant-specific role
2469
+ */
2470
+ isTenantRole() {
2471
+ return this.tenantId !== null && this.tenantId !== void 0;
2472
+ }
2473
+ /**
2474
+ * Check if this role can be deleted.
2475
+ * System roles (isSystem = true) cannot be deleted.
2476
+ * @returns true if the role can be deleted
2477
+ */
2478
+ canDelete() {
2479
+ return !this.isSystem;
2480
+ }
2481
+ /**
2482
+ * Delete guard - prevents deletion of system roles.
2483
+ * Override the delete method to check isSystem flag first.
2484
+ */
2485
+ async delete() {
2486
+ if (this.isSystem) throw new Error(`Cannot delete system role '${this.slug}'. System roles are protected.`);
2487
+ return super.delete();
2488
+ }
2489
+ };
2490
+ __decorateClass$3$1([foreignKey("Tenant", { nullable: true })], Role.prototype, "tenantId", 2);
2491
+ Role = __decorateClass$3$1([smrt({
2492
+ api: { include: ["list", "get"] },
2493
+ mcp: { include: ["list", "get"] },
2494
+ cli: { skipApiCheck: true }
2495
+ })], Role);
2496
+ var __defProp$2$1 = Object.defineProperty;
2497
+ var __getOwnPropDesc$2$1 = Object.getOwnPropertyDescriptor;
2498
+ var __decorateClass$2$1 = (decorators, target, key, kind) => {
2499
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2$1(target, key) : target;
2500
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2501
+ if (kind && result) __defProp$2$1(target, key, result);
2502
+ return result;
2503
+ };
2504
+ var RolePermission = class extends SmrtObject {
2505
+ roleId;
2506
+ permissionId;
2507
+ constructor(options = {}) {
2508
+ super(options);
2509
+ if (options.roleId !== void 0) this.roleId = options.roleId;
2510
+ if (options.permissionId !== void 0) this.permissionId = options.permissionId;
2511
+ }
2512
+ };
2513
+ __decorateClass$2$1([foreignKey("Role", { required: true })], RolePermission.prototype, "roleId", 2);
2514
+ __decorateClass$2$1([foreignKey("Permission", { required: true })], RolePermission.prototype, "permissionId", 2);
2515
+ RolePermission = __decorateClass$2$1([smrt({
2516
+ api: { include: ["list", "get"] },
2517
+ mcp: { include: ["list", "get"] },
2518
+ cli: true
2519
+ })], RolePermission);
2520
+ DEFAULT_ROLE_SLUGS.OWNER, DEFAULT_ROLE_SLUGS.ADMIN, DEFAULT_ROLE_SLUGS.MEMBER, DEFAULT_ROLE_SLUGS.VIEWER;
2521
+ var logger$1 = createLogger({ level: "info" });
2522
+ var TenantHierarchyError = class extends Error {
2523
+ constructor(message, code) {
2524
+ super(message);
2525
+ this.code = code;
2526
+ this.name = "TenantHierarchyError";
2527
+ }
2528
+ code;
2529
+ };
2530
+ var IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
2531
+ function assertTenantTableName(tableName) {
2532
+ if (!IDENTIFIER.test(tableName)) throw new TenantHierarchyError(`Invalid tenant table name: ${JSON.stringify(tableName)}`, "INVALID_OPERATION");
2533
+ return tableName;
2534
+ }
2535
+ function toId(value) {
2536
+ if (value === null || value === void 0) return null;
2537
+ const id = String(value);
2538
+ return id.length > 0 ? id : null;
2539
+ }
2540
+ function childHierarchyFields(parentId, parent) {
2541
+ return {
2542
+ hierarchyPath: parent.hierarchyPath ? `${parent.hierarchyPath}/${parentId}` : parentId,
2543
+ hierarchyLevel: parent.hierarchyLevel + 1
2544
+ };
2545
+ }
2546
+ async function computeTenantHierarchyFields(db, tableName, tenantId, parentTenantId) {
2547
+ const table = assertTenantTableName(tableName);
2548
+ const ancestors = [];
2549
+ const seen = /* @__PURE__ */ new Set();
2550
+ if (tenantId) seen.add(tenantId);
2551
+ let cursor = toId(parentTenantId);
2552
+ while (cursor) {
2553
+ if (seen.has(cursor)) throw new TenantHierarchyError(`Tenant hierarchy for ${tenantId ?? "a new tenant"} is circular at ${cursor}`, "CIRCULAR_REFERENCE");
2554
+ if (ancestors.length + 1 >= 10) throw new TenantHierarchyError(`Maximum hierarchy depth (10) exceeded`, "MAX_DEPTH_EXCEEDED");
2555
+ seen.add(cursor);
2556
+ const { rows } = await db.query(`SELECT id, parent_tenant_id FROM ${table} WHERE id = ?`, cursor);
2557
+ const row = rows[0];
2558
+ if (!row) throw new TenantHierarchyError(`Parent tenant not found: ${cursor}`, "PARENT_NOT_FOUND");
2559
+ ancestors.unshift(cursor);
2560
+ cursor = toId(row.parent_tenant_id);
2561
+ }
2562
+ return {
2563
+ hierarchyPath: ancestors.join("/"),
2564
+ hierarchyLevel: ancestors.length
2565
+ };
2566
+ }
2567
+ async function planDescendantHierarchy(db, tableName, rootId, root) {
2568
+ const table = assertTenantTableName(tableName);
2569
+ const updates = [];
2570
+ const seen = /* @__PURE__ */ new Set([rootId]);
2571
+ let frontier = [{
2572
+ id: rootId,
2573
+ fields: root
2574
+ }];
2575
+ while (frontier.length > 0) {
2576
+ const next = [];
2577
+ for (const parent of frontier) {
2578
+ const { rows } = await db.query(`SELECT id, hierarchy_path, hierarchy_level FROM ${table} WHERE parent_tenant_id = ?`, parent.id);
2579
+ for (const row of rows) {
2580
+ const id = toId(row.id);
2581
+ if (!id) continue;
2582
+ if (seen.has(id)) throw new TenantHierarchyError(`Tenant hierarchy below ${rootId} is circular at ${id}`, "CIRCULAR_REFERENCE");
2583
+ seen.add(id);
2584
+ const fields = childHierarchyFields(parent.id, parent.fields);
2585
+ if (fields.hierarchyLevel >= 10) throw new TenantHierarchyError(`Moving would exceed maximum hierarchy depth (10)`, "MAX_DEPTH_EXCEEDED");
2586
+ if ((row.hierarchy_path ?? "") !== fields.hierarchyPath || Number(row.hierarchy_level) !== fields.hierarchyLevel) updates.push({
2587
+ id,
2588
+ ...fields
2589
+ });
2590
+ next.push({
2591
+ id,
2592
+ fields
2593
+ });
2594
+ }
2595
+ }
2596
+ frontier = next;
2597
+ }
2598
+ return updates;
2599
+ }
2600
+ async function applyTenantHierarchyUpdates(db, tableName, updates) {
2601
+ const table = assertTenantTableName(tableName);
2602
+ for (const update of updates) await db.query(`UPDATE ${table} SET hierarchy_path = ?, hierarchy_level = ? WHERE id = ?`, update.hierarchyPath, update.hierarchyLevel, update.id);
2603
+ }
2604
+ function planTenantHierarchy(rows) {
2605
+ const byId = new Map(rows.map((row) => [row.id, row]));
2606
+ const resolved = /* @__PURE__ */ new Map();
2607
+ const resolve = (id) => {
2608
+ const cached = resolved.get(id);
2609
+ if (cached) return cached;
2610
+ const chain = [];
2611
+ const onChain = /* @__PURE__ */ new Set();
2612
+ let cursor = id;
2613
+ let base;
2614
+ while (cursor) {
2615
+ const known = resolved.get(cursor);
2616
+ if (known) {
2617
+ base = known;
2618
+ break;
2619
+ }
2620
+ if (onChain.has(cursor)) {
2621
+ base = {
2622
+ id,
2623
+ code: "CIRCULAR_REFERENCE",
2624
+ message: `Tenant ${id} has a circular parent chain at ${cursor}.`
2625
+ };
2626
+ break;
2627
+ }
2628
+ const row = byId.get(cursor);
2629
+ if (!row) {
2630
+ base = {
2631
+ id,
2632
+ code: "PARENT_NOT_FOUND",
2633
+ message: `Tenant ${chain[chain.length - 1] ?? id} names missing parent ${cursor}.`
2634
+ };
2635
+ break;
2636
+ }
2637
+ onChain.add(cursor);
2638
+ chain.push(cursor);
2639
+ cursor = row.parentTenantId;
2640
+ }
2641
+ if (!base) {
2642
+ const rootId = chain.pop();
2643
+ base = {
2644
+ hierarchyPath: "",
2645
+ hierarchyLevel: 0
2646
+ };
2647
+ resolved.set(rootId, base);
2648
+ if (rootId === id) return base;
2649
+ }
2650
+ let parentFields = base;
2651
+ for (let i = chain.length - 1; i >= 0; i--) {
2652
+ const current = chain[i];
2653
+ let fields;
2654
+ if ("code" in parentFields) fields = {
2655
+ ...parentFields,
2656
+ id: current
2657
+ };
2658
+ else {
2659
+ const parentId = byId.get(current)?.parentTenantId;
2660
+ const child = childHierarchyFields(parentId, parentFields);
2661
+ fields = child.hierarchyLevel >= 10 ? {
2662
+ id: current,
2663
+ code: "MAX_DEPTH_EXCEEDED",
2664
+ message: `Tenant ${current} would sit at level ${child.hierarchyLevel}; the maximum depth is 10.`
2665
+ } : child;
2666
+ }
2667
+ resolved.set(current, fields);
2668
+ parentFields = fields;
2669
+ }
2670
+ return resolved.get(id);
2671
+ };
2672
+ const changes = [];
2673
+ const problems = [];
2674
+ for (const row of rows) {
2675
+ const fields = resolve(row.id);
2676
+ if ("code" in fields) {
2677
+ problems.push({
2678
+ ...fields,
2679
+ id: row.id
2680
+ });
2681
+ continue;
2682
+ }
2683
+ if ((row.hierarchyPath ?? "") !== fields.hierarchyPath || row.hierarchyLevel !== fields.hierarchyLevel) changes.push({
2684
+ id: row.id,
2685
+ ...fields,
2686
+ previousPath: row.hierarchyPath,
2687
+ previousLevel: row.hierarchyLevel
2688
+ });
2689
+ }
2690
+ const byIdOrder = (a, b) => a.id.localeCompare(b.id);
2691
+ return {
2692
+ total: rows.length,
2693
+ changes: changes.sort(byIdOrder),
2694
+ problems: problems.sort(byIdOrder)
2695
+ };
2696
+ }
2697
+ async function recordTenantHierarchyChanges(db, tableName, rowIds) {
2698
+ const inputs = rowIds === void 0 ? [{
2699
+ table: tableName,
2700
+ rowId: null
2701
+ }] : rowIds.map((rowId) => ({
2702
+ table: tableName,
2703
+ rowId
2704
+ }));
2705
+ for (const input of inputs) try {
2706
+ await bumpChangeFeed(db, {
2707
+ ...input,
2708
+ operation: "update"
2709
+ });
2710
+ } catch (error) {
2711
+ logger$1.warn("Failed to record tenant hierarchy change in change feed", {
2712
+ table: tableName,
2713
+ rowId: input.rowId,
2714
+ error: error instanceof Error ? error.message : String(error)
2715
+ });
2716
+ }
2717
+ }
2718
+ var __defProp$1$1 = Object.defineProperty;
2719
+ var __getOwnPropDesc$1$1 = Object.getOwnPropertyDescriptor;
2720
+ var __decorateClass$1$1 = (decorators, target, key, kind) => {
2721
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1$1(target, key) : target;
2722
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
2723
+ if (kind && result) __defProp$1$1(target, key, result);
2724
+ return result;
2725
+ };
2726
+ var Tenant = class extends SmrtObject {
2727
+ /**
2728
+ * Display name for the tenant
2729
+ */
2730
+ name = "";
2731
+ status = TenantStatus.ACTIVE;
2732
+ /**
2733
+ * Optional description
2734
+ */
2735
+ description = "";
2736
+ parentTenantId;
2737
+ /**
2738
+ * Depth in the hierarchy tree (0 = root, 1 = first level child, etc.)
2739
+ * Derived from `parentTenantId` and maintained by {@link Tenant.save};
2740
+ * any value assigned directly is recomputed on save.
2741
+ */
2742
+ hierarchyLevel = 0;
2743
+ /**
2744
+ * Materialized path for efficient tree traversal.
2745
+ * Format: "ancestor-id/parent-id" (path to parent; does not include this tenant's id)
2746
+ * Empty string for root tenants.
2747
+ * Derived from `parentTenantId` and maintained by {@link Tenant.save};
2748
+ * any value assigned directly is recomputed on save. Rows written before
2749
+ * the framework maintained it are backfilled with
2750
+ * `smrt db:materialize-tenant-hierarchy` (smrt#3036).
2751
+ */
2752
+ hierarchyPath = "";
2753
+ /**
2754
+ * If true, this tenant's permissions cascade DOWN to child tenants.
2755
+ * Children can still opt-out by setting inheritPermissions: false.
2756
+ * Default: true
2757
+ */
2758
+ cascadePermissions = true;
2759
+ /**
2760
+ * If true, this tenant ACCEPTS permissions from its parent tenant.
2761
+ * Parent must also have cascadePermissions: true for inheritance to work.
2762
+ * Default: true
2763
+ */
2764
+ inheritPermissions = true;
2765
+ constructor(options = {}) {
2766
+ super(options);
2767
+ if (options.name !== void 0) this.name = options.name;
2768
+ if (options.status !== void 0) this.status = options.status;
2769
+ if (options.description !== void 0) this.description = options.description;
2770
+ if (options.parentTenantId !== void 0) this.parentTenantId = options.parentTenantId;
2771
+ if (options.hierarchyLevel !== void 0) this.hierarchyLevel = options.hierarchyLevel;
2772
+ if (options.hierarchyPath !== void 0) this.hierarchyPath = options.hierarchyPath;
2773
+ if (options.cascadePermissions !== void 0) this.cascadePermissions = options.cascadePermissions;
2774
+ if (options.inheritPermissions !== void 0) this.inheritPermissions = options.inheritPermissions;
2775
+ }
2776
+ /**
2777
+ * Check if tenant is active
2778
+ */
2779
+ isActive() {
2780
+ return this.status === TenantStatus.ACTIVE;
2781
+ }
2782
+ /**
2783
+ * Check if tenant is suspended
2784
+ */
2785
+ isSuspended() {
2786
+ return this.status === TenantStatus.SUSPENDED;
2787
+ }
2788
+ /**
2789
+ * Check if this is a root-level tenant (no parent)
2790
+ */
2791
+ isRoot() {
2792
+ return !this.parentTenantId;
2793
+ }
2794
+ /**
2795
+ * Check if this tenant is configured to cascade permissions to children.
2796
+ *
2797
+ * Note: This does NOT indicate whether any child tenants actually exist.
2798
+ * Use TenantCollection.findChildren() for accurate child lookup.
2799
+ */
2800
+ canCascadeToChildren() {
2801
+ return this.cascadePermissions;
2802
+ }
2803
+ /**
2804
+ * Check if permission inheritance is active for this tenant.
2805
+ * Inheritance is active if:
2806
+ * - This tenant has a parent AND
2807
+ * - This tenant has inheritPermissions: true
2808
+ *
2809
+ * Note: The parent must also have cascadePermissions: true
2810
+ * for actual inheritance to occur. Use PermissionResolver
2811
+ * for accurate permission calculation.
2812
+ */
2813
+ acceptsInheritance() {
2814
+ return !!this.parentTenantId && this.inheritPermissions;
2815
+ }
2816
+ /**
2817
+ * Persist the tenant, keeping the derived hierarchy fields true (smrt#3036).
2818
+ *
2819
+ * `hierarchyPath` / `hierarchyLevel` are recomputed from the real
2820
+ * `parentTenantId` chain on EVERY save — whichever collection, subclass, or
2821
+ * code path produced the object — so a consumer never hand-maintains them.
2822
+ * When they change (a reparent, or healing a stale row), every descendant is
2823
+ * re-materialized too. Both columns are an authorization source for
2824
+ * `inheritsToDescendants` and the declared ancestor-read policy.
2825
+ *
2826
+ * @throws {TenantHierarchyError} before anything is written, when the new
2827
+ * parent is missing, would create a cycle, or would put this tenant or one
2828
+ * of its descendants at or below `MAX_TENANT_HIERARCHY_DEPTH`.
2829
+ */
2830
+ async save(options = {}) {
2831
+ const db = this.db;
2832
+ const table = this.tableName;
2833
+ await this.assertNewParentVisible(db, table);
2834
+ const fields = await computeTenantHierarchyFields(db, table, this.id, this.parentTenantId);
2835
+ const descendantUpdates = (fields.hierarchyPath !== this.hierarchyPath || fields.hierarchyLevel !== this.hierarchyLevel) && this.id && this.isPersisted ? await planDescendantHierarchy(db, table, this.id, fields) : [];
2836
+ this.hierarchyPath = fields.hierarchyPath;
2837
+ this.hierarchyLevel = fields.hierarchyLevel;
2838
+ await super.save(options);
2839
+ if (descendantUpdates.length > 0) {
2840
+ await applyTenantHierarchyUpdates(db, table, descendantUpdates);
2841
+ await recordTenantHierarchyChanges(this.db, table, descendantUpdates.map((update) => update.id));
2842
+ }
2843
+ return this;
2844
+ }
2845
+ /**
2846
+ * Refuse to link this tenant under a parent the caller cannot see.
2847
+ *
2848
+ * A parent link is authority-bearing: ancestor tenant overrides cascade down
2849
+ * it and `inheritsToDescendants` roles flow along it. The chain itself is
2850
+ * resolved with raw reads (so paths can be derived for any row), so this is
2851
+ * the check that keeps a NEW or CHANGED link subject to the caller's own
2852
+ * tenancy scope, whichever path made it — `createChild`, `moveToParent`,
2853
+ * `create({ parentTenantId })`, or a plain `parentTenantId` assignment and
2854
+ * `save()`. The parent is loaded through `TenantCollection`, i.e. through
2855
+ * the tenancy interceptor: a refused or filtered read fails the save before
2856
+ * anything is written. System context (migrations, backfills, platform
2857
+ * administration) bypasses the interceptor as everywhere else. An unchanged
2858
+ * link is not re-checked, so a tenant can still save itself under its own
2859
+ * scope when its parent is not visible there.
2860
+ */
2861
+ async assertNewParentVisible(db, table) {
2862
+ const parentId = this.parentTenantId ?? null;
2863
+ if (!parentId) return;
2864
+ if (this.id) {
2865
+ const { rows } = await db.query(`SELECT parent_tenant_id FROM ${table} WHERE id = ?`, this.id);
2866
+ const stored = rows[0]?.parent_tenant_id;
2867
+ if (rows[0] && stored !== null && stored !== void 0 && String(stored) === parentId) return;
2868
+ }
2869
+ const { TenantCollection } = await Promise.resolve().then(() => TenantCollection_exports);
2870
+ if (!(await (await TenantCollection.create({ db: this.db })).get({ id: parentId }))?.id) throw new TenantHierarchyError(`Parent tenant not found: ${parentId}`, "PARENT_NOT_FOUND");
2871
+ }
2872
+ /**
2873
+ * Get ancestor IDs from the hierarchy path.
2874
+ * Returns an array of tenant IDs from root to immediate parent.
2875
+ * Empty array for root tenants.
2876
+ */
2877
+ getAncestorIds() {
2878
+ if (!this.hierarchyPath) return [];
2879
+ return this.hierarchyPath.split("/").filter((id) => id.length > 0);
2880
+ }
2881
+ };
2882
+ __decorateClass$1$1([field({ type: "text" })], Tenant.prototype, "status", 2);
2883
+ __decorateClass$1$1([foreignKey("Tenant", { nullable: true })], Tenant.prototype, "parentTenantId", 2);
2884
+ Tenant = __decorateClass$1$1([smrt({
2885
+ tableStrategy: "sti",
2886
+ api: { include: ["list", "get"] },
2887
+ mcp: { include: ["list", "get"] },
2888
+ cli: { skipApiCheck: true }
2889
+ })], Tenant);
2890
+ var TenantCollection_exports = /* @__PURE__ */ __exportAll({
2891
+ TenantCollection: () => TenantCollection,
2892
+ TenantHierarchyError: () => TenantHierarchyError
2893
+ });
2894
+ var TenantCollection = class extends SmrtCollection {
2895
+ static _itemClass = Tenant;
2896
+ /**
2897
+ * Find tenants by status
2898
+ */
2899
+ async findByStatus(status) {
2900
+ return await this.list({
2901
+ where: { status },
2902
+ orderBy: "name ASC"
2903
+ });
2904
+ }
2905
+ /**
2906
+ * Find all active tenants
2907
+ */
2908
+ async findActive() {
2909
+ return await this.findByStatus(TenantStatus.ACTIVE);
2910
+ }
2911
+ /**
2912
+ * Find tenant by slug
2913
+ */
2914
+ async findBySlug(slug) {
2915
+ const results = await this.list({
2916
+ where: { slug },
2917
+ limit: 1
2918
+ });
2919
+ return results.length > 0 ? results[0] : null;
2920
+ }
2921
+ /**
2922
+ * Find all root tenants (tenants with no parent)
2923
+ */
2924
+ async findRoots() {
2925
+ return await this.list({
2926
+ where: { parentTenantId: null },
2927
+ orderBy: "name ASC"
2928
+ });
2929
+ }
2930
+ /**
2931
+ * Find direct children of a tenant
2932
+ */
2933
+ async findChildren(parentTenantId) {
2934
+ return await this.list({
2935
+ where: { parentTenantId },
2936
+ orderBy: "name ASC"
2937
+ });
2938
+ }
2939
+ /**
2940
+ * Find the parent tenant of a given tenant
2941
+ */
2942
+ async findParent(tenantId) {
2943
+ const tenant = await this.get({ id: tenantId });
2944
+ if (!tenant?.parentTenantId) return null;
2945
+ return await this.get({ id: tenant.parentTenantId });
2946
+ }
2947
+ /**
2948
+ * Get all ancestors of a tenant, from immediate parent to root.
2949
+ * Uses the hierarchyPath for efficient lookup.
2950
+ */
2951
+ async getAncestors(tenantId) {
2952
+ const tenant = await this.get({ id: tenantId });
2953
+ if (!tenant) return [];
2954
+ const ancestorIds = tenant.getAncestorIds();
2955
+ if (ancestorIds.length === 0) return [];
2956
+ const ancestorsList = await this.listByIds(ancestorIds);
2957
+ const ancestorsMap = new Map(ancestorsList.map((a) => [a.id, a]));
2958
+ const ancestors = [];
2959
+ for (let i = ancestorIds.length - 1; i >= 0; i--) {
2960
+ const ancestor = ancestorsMap.get(ancestorIds[i]);
2961
+ if (ancestor) ancestors.push(ancestor);
2962
+ }
2963
+ return ancestors;
2964
+ }
2965
+ /**
2966
+ * Get all ancestors in order from root to immediate parent.
2967
+ * Reverse of getAncestors.
2968
+ */
2969
+ async getAncestorsFromRoot(tenantId) {
2970
+ return (await this.getAncestors(tenantId)).reverse();
2971
+ }
2972
+ /**
2973
+ * Get all descendants of a tenant (all children, grandchildren, etc.)
2974
+ * Uses hierarchyPath prefix matching for efficient lookup.
2975
+ */
2976
+ async getDescendants(tenantId) {
2977
+ const tenant = await this.get({ id: tenantId });
2978
+ if (!tenant?.id) return [];
2979
+ const pathPrefix = tenant.hierarchyPath ? `${tenant.hierarchyPath}/${tenant.id}` : tenant.id;
2980
+ return (await this.list({ where: { "hierarchyPath like": `${pathPrefix}%` } })).filter((t) => t.hierarchyPath === pathPrefix || t.hierarchyPath?.startsWith(`${pathPrefix}/`));
2981
+ }
2982
+ /**
2983
+ * Get siblings of a tenant (other tenants with the same parent)
2984
+ */
2985
+ async getSiblings(tenantId) {
2986
+ const tenant = await this.get({ id: tenantId });
2987
+ if (!tenant) return [];
2988
+ return (await this.list({
2989
+ where: { parentTenantId: tenant.parentTenantId ?? null },
2990
+ orderBy: "name ASC"
2991
+ })).filter((s) => s.id !== tenantId);
2992
+ }
2993
+ /**
2994
+ * Check if a tenant is an ancestor of another tenant
2995
+ */
2996
+ async isAncestorOf(potentialAncestorId, tenantId) {
2997
+ const tenant = await this.get({ id: tenantId });
2998
+ if (!tenant) return false;
2999
+ return tenant.getAncestorIds().includes(potentialAncestorId);
3000
+ }
3001
+ /**
3002
+ * Check if a tenant is a descendant of another tenant
3003
+ */
3004
+ async isDescendantOf(potentialDescendantId, tenantId) {
3005
+ return await this.isAncestorOf(tenantId, potentialDescendantId);
3006
+ }
3007
+ /**
3008
+ * Create a child tenant under a parent.
3009
+ * `hierarchyLevel` and `hierarchyPath` are derived by {@link Tenant.save}.
3010
+ *
3011
+ * @throws {TenantHierarchyError} `PARENT_NOT_FOUND` or `MAX_DEPTH_EXCEEDED`.
3012
+ */
3013
+ async createChild(parentTenantId, options) {
3014
+ return await this.create({
3015
+ name: options.name,
3016
+ slug: options.slug,
3017
+ description: options.description ?? "",
3018
+ status: options.status ?? TenantStatus.ACTIVE,
3019
+ parentTenantId,
3020
+ cascadePermissions: options.cascadePermissions ?? true,
3021
+ inheritPermissions: options.inheritPermissions ?? true
3022
+ });
3023
+ }
3024
+ /**
3025
+ * Move a tenant to a new parent (or to the root with `null`).
3026
+ *
3027
+ * {@link Tenant.save} checks the new parent is visible under the caller's
3028
+ * tenancy scope, recomputes the tenant's hierarchy fields from the real
3029
+ * parent chain and re-materializes every descendant, refusing the move
3030
+ * before writing anything when it would create a cycle or push any
3031
+ * descendant past `MAX_TENANT_HIERARCHY_DEPTH`.
3032
+ */
3033
+ async moveToParent(tenantId, newParentId) {
3034
+ const tenant = await this.get({ id: tenantId });
3035
+ if (!tenant?.id) throw new TenantHierarchyError(`Tenant not found: ${tenantId}`, "INVALID_OPERATION");
3036
+ if (newParentId === tenantId) throw new TenantHierarchyError("Cannot move tenant to itself", "CIRCULAR_REFERENCE");
3037
+ tenant.parentTenantId = newParentId;
3038
+ await tenant.save();
3039
+ return tenant;
3040
+ }
3041
+ /**
3042
+ * Make a tenant a root tenant (remove from hierarchy)
3043
+ */
3044
+ async makeRoot(tenantId) {
3045
+ return await this.moveToParent(tenantId, null);
3046
+ }
3047
+ /**
3048
+ * Validate that a tenant hierarchy is consistent.
3049
+ * Returns validation errors if any.
3050
+ */
3051
+ async validateHierarchy(tenantId) {
3052
+ const errors = [];
3053
+ const tenant = await this.get({ id: tenantId });
3054
+ if (!tenant) return [`Tenant not found: ${tenantId}`];
3055
+ if (tenant.parentTenantId) {
3056
+ const parent = await this.get({ id: tenant.parentTenantId });
3057
+ if (!parent) errors.push(`Parent tenant not found: ${tenant.parentTenantId}`);
3058
+ else {
3059
+ if (tenant.hierarchyLevel !== parent.hierarchyLevel + 1) errors.push(`Hierarchy level mismatch: expected ${parent.hierarchyLevel + 1}, got ${tenant.hierarchyLevel}`);
3060
+ const expectedPath = parent.hierarchyPath ? `${parent.hierarchyPath}/${parent.id}` : parent.id;
3061
+ if (tenant.hierarchyPath !== expectedPath) errors.push(`Hierarchy path mismatch: expected "${expectedPath}", got "${tenant.hierarchyPath}"`);
3062
+ }
3063
+ } else {
3064
+ if (tenant.hierarchyLevel !== 0) errors.push(`Root tenant should have hierarchyLevel 0, got ${tenant.hierarchyLevel}`);
3065
+ if (tenant.hierarchyPath !== "") errors.push(`Root tenant should have empty hierarchyPath, got "${tenant.hierarchyPath}"`);
3066
+ }
3067
+ if (tenant.parentTenantId && tenant.id) {
3068
+ if (tenant.getAncestorIds().includes(tenant.id)) errors.push("Circular reference detected in hierarchy");
3069
+ }
3070
+ return errors;
3071
+ }
3072
+ /**
3073
+ * Get the full hierarchy tree starting from a tenant.
3074
+ * Returns a nested structure useful for UI rendering.
3075
+ */
3076
+ async getTree(rootTenantId) {
3077
+ const roots = rootTenantId ? [await this.get({ id: rootTenantId })] : await this.findRoots();
3078
+ const buildTree = async (tenant) => {
3079
+ if (!tenant) return null;
3080
+ const children = await this.findChildren(tenant.id);
3081
+ const childTrees = await Promise.all(children.map(buildTree));
3082
+ return Object.assign(tenant, { children: childTrees.filter(Boolean) });
3083
+ };
3084
+ return (await Promise.all(roots.map(buildTree))).filter(Boolean);
3085
+ }
3086
+ };
3087
+ var __defProp$15 = Object.defineProperty;
3088
+ var __getOwnPropDesc$14 = Object.getOwnPropertyDescriptor;
3089
+ var __decorateClass$14 = (decorators, target, key, kind) => {
3090
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$14(target, key) : target;
3091
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
3092
+ if (kind && result) __defProp$15(target, key, result);
3093
+ return result;
3094
+ };
3095
+ var TenantPermissionOverride = class extends SmrtObject {
3096
+ tenantId;
3097
+ permissionId;
3098
+ effect = TenantPermissionEffect.INHERIT;
3099
+ constructor(options = {}) {
3100
+ super(options);
3101
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
3102
+ if (options.permissionId !== void 0) this.permissionId = options.permissionId;
3103
+ if (options.effect !== void 0) this.effect = options.effect;
3104
+ }
3105
+ /**
3106
+ * Check if this override inherits from parent
3107
+ */
3108
+ isInherit() {
3109
+ return this.effect === TenantPermissionEffect.INHERIT;
3110
+ }
3111
+ /**
3112
+ * Check if this override grants the permission
3113
+ */
3114
+ isGrant() {
3115
+ return this.effect === TenantPermissionEffect.GRANT;
3116
+ }
3117
+ /**
3118
+ * Check if this override denies the permission
3119
+ */
3120
+ isDeny() {
3121
+ return this.effect === TenantPermissionEffect.DENY;
3122
+ }
3123
+ /**
3124
+ * Check if this override has an explicit effect (not inherit)
3125
+ */
3126
+ hasExplicitEffect() {
3127
+ return this.effect !== TenantPermissionEffect.INHERIT;
3128
+ }
3129
+ };
3130
+ __decorateClass$14([foreignKey("Tenant", { required: true })], TenantPermissionOverride.prototype, "tenantId", 2);
3131
+ __decorateClass$14([foreignKey("Permission", { required: true })], TenantPermissionOverride.prototype, "permissionId", 2);
3132
+ __decorateClass$14([field({ type: "text" })], TenantPermissionOverride.prototype, "effect", 2);
3133
+ TenantPermissionOverride = __decorateClass$14([smrt({
3134
+ api: { include: ["list", "get"] },
3135
+ mcp: { include: ["list", "get"] },
3136
+ cli: { skipApiCheck: true }
3137
+ })], TenantPermissionOverride);
3138
+ new TextEncoder();
3139
+ new TextDecoder();
3140
+ new TextDecoder("utf-8", { fatal: !0 });
3141
+ function table(entries) {
3142
+ const out = { __proto__: null };
3143
+ for (const alg in entries) out[alg] = {
3144
+ ...entries[alg],
3145
+ alg
3146
+ };
3147
+ return out;
3148
+ }
3149
+ var sig = [["verify"], ["sign"]];
3150
+ function hmac(bits) {
3151
+ const subtle = {
3152
+ name: "HMAC",
3153
+ hash: `SHA-${bits}`
3154
+ };
3155
+ return {
3156
+ kty: ["oct"],
3157
+ secret: !0,
3158
+ subtle,
3159
+ signing: subtle,
3160
+ usages: sig
3161
+ };
3162
+ }
3163
+ function rsa(bits, saltLength) {
3164
+ const subtle = {
3165
+ name: saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
3166
+ hash: `SHA-${bits}`
3167
+ };
3168
+ return {
3169
+ kty: ["RSA"],
3170
+ subtle,
3171
+ signing: saltLength ? {
3172
+ ...subtle,
3173
+ saltLength
3174
+ } : subtle,
3175
+ usages: sig,
3176
+ minRsaBits: 2048
3177
+ };
3178
+ }
3179
+ function ecdsa(crv, bits) {
3180
+ return {
3181
+ kty: ["EC"],
3182
+ crv,
3183
+ subtle: {
3184
+ name: "ECDSA",
3185
+ namedCurve: crv
3186
+ },
3187
+ signing: {
3188
+ name: "ECDSA",
3189
+ hash: `SHA-${bits}`
3190
+ },
3191
+ usages: sig
3192
+ };
3193
+ }
3194
+ function eddsa() {
3195
+ const subtle = { name: "Ed25519" };
3196
+ return {
3197
+ kty: ["OKP"],
3198
+ crv: "Ed25519",
3199
+ subtle,
3200
+ signing: subtle,
3201
+ usages: sig
3202
+ };
3203
+ }
3204
+ function mldsa(bits) {
3205
+ const subtle = { name: `ML-DSA-${bits}` };
3206
+ return {
3207
+ kty: ["AKP"],
3208
+ subtle,
3209
+ signing: subtle,
3210
+ usages: sig
3211
+ };
3212
+ }
3213
+ table({
3214
+ HS256: hmac(256),
3215
+ HS384: hmac(384),
3216
+ HS512: hmac(512),
3217
+ RS256: rsa(256),
3218
+ RS384: rsa(384),
3219
+ RS512: rsa(512),
3220
+ PS256: rsa(256, 32),
3221
+ PS384: rsa(384, 48),
3222
+ PS512: rsa(512, 64),
3223
+ ES256: ecdsa("P-256", 256),
3224
+ ES384: ecdsa("P-384", 384),
3225
+ ES512: ecdsa("P-521", 512),
3226
+ EdDSA: eddsa(),
3227
+ Ed25519: eddsa(),
3228
+ "ML-DSA-44": mldsa(44),
3229
+ "ML-DSA-65": mldsa(65),
3230
+ "ML-DSA-87": mldsa(87)
3231
+ });
3232
+ typeof navigator > "u" || navigator.userAgent?.startsWith?.("Mozilla/5.0 ");
3233
+ var PERMISSION_STORAGE_KEY = /* @__PURE__ */ Symbol.for("smrt:session-permission-context-storage");
3234
+ function resolvePermissionContextStorage() {
3235
+ const root = globalThis;
3236
+ root[PERMISSION_STORAGE_KEY] ??= new AsyncLocalStorage();
3237
+ return root[PERMISSION_STORAGE_KEY];
3238
+ }
3239
+ var requestPermissionContextStorage = resolvePermissionContextStorage();
3240
+ function getCurrentSessionPermissionContext() {
3241
+ return requestPermissionContextStorage.getStore();
3242
+ }
3243
+ function getRequestScopedDatabase() {
3244
+ return getCurrentSessionPermissionContext()?.database;
3245
+ }
3246
+ globalThis.__smrtGetRequestPermissionContext ??= getCurrentSessionPermissionContext;
3247
+ globalThis.__smrtGetRequestScopedDatabase ??= getRequestScopedDatabase;
3248
+ //#endregion
3249
+ //#region ../users/dist/index.js
3250
+ var __defProp$3 = Object.defineProperty;
3251
+ var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
3252
+ var __decorateClass$3 = (decorators, target, key, kind) => {
3253
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
3254
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
3255
+ if (kind && result) __defProp$3(target, key, result);
3256
+ return result;
3257
+ };
3258
+ var UsersMagicLinkToken = class extends SmrtObject {
3259
+ nonce = "";
3260
+ /** Email address this token was generated for */
3261
+ email = "";
3262
+ /** Whether this token has been used */
3263
+ used = false;
3264
+ expiresAt = new Date(Date.now() + 600 * 1e3);
3265
+ constructor(options = {}) {
3266
+ super(options);
3267
+ if (options.nonce !== void 0) this.nonce = options.nonce;
3268
+ if (options.email !== void 0) this.email = options.email;
3269
+ if (options.used !== void 0) this.used = options.used;
3270
+ if (options.expiresAt !== void 0) this.expiresAt = options.expiresAt instanceof Date ? options.expiresAt : new Date(options.expiresAt);
3271
+ }
3272
+ /** Check if the token has expired */
3273
+ isExpired() {
3274
+ return /* @__PURE__ */ new Date() > this.expiresAt;
3275
+ }
3276
+ /** Check if the token is still valid (unused and not expired) */
3277
+ isValid() {
3278
+ return !this.used && !this.isExpired();
3279
+ }
3280
+ };
3281
+ __decorateClass$3([field({
3282
+ required: true,
3283
+ unique: true
3284
+ })], UsersMagicLinkToken.prototype, "nonce", 2);
3285
+ __decorateClass$3([field({
3286
+ type: "datetime",
3287
+ indexed: true
3288
+ })], UsersMagicLinkToken.prototype, "expiresAt", 2);
3289
+ UsersMagicLinkToken = __decorateClass$3([smrt({
3290
+ tableName: "users_magic_link_tokens",
3291
+ sensitive: true,
3292
+ api: { include: [] },
3293
+ mcp: { include: [] },
3294
+ cli: { skipApiCheck: true }
3295
+ })], UsersMagicLinkToken);
3296
+ var UsersMagicLinkTokenCollection = class extends SmrtCollection {
3297
+ static _itemClass = UsersMagicLinkToken;
3298
+ /**
3299
+ * Find a token by its nonce
3300
+ */
3301
+ async findByNonce(nonce) {
3302
+ return this.findOne({ where: { nonce } });
3303
+ }
3304
+ /**
3305
+ * Atomically mark a token as used (single-use enforcement).
3306
+ *
3307
+ * Returns true if the nonce was successfully claimed (transitioned from
3308
+ * unused to used). Returns false if the nonce was already used, expired,
3309
+ * or doesn't exist — preventing race conditions in concurrent verify() calls.
3310
+ */
3311
+ async markUsed(nonce) {
3312
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3313
+ const { rowCount } = await this.db.query(`UPDATE ${this.tableName}
3314
+ SET used = ?, updated_at = ?
3315
+ WHERE nonce = ? AND used = ? AND expires_at > ?`, true, now, nonce, false, now);
3316
+ return rowCount > 0;
3317
+ }
3318
+ /**
3319
+ * Delete expired tokens (cleanup job)
3320
+ *
3321
+ * Scheduled by the framework retention sweep (#2375); `expiresAt` carries an
3322
+ * index for this predicate.
3323
+ *
3324
+ * @param options.dryRun - Count the tokens the predicate selects without
3325
+ * deleting them.
3326
+ * @returns Number of tokens deleted (or, under `dryRun`, matched)
3327
+ */
3328
+ async deleteExpired(options = {}) {
3329
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3330
+ const predicate = "expires_at < ?";
3331
+ const counted = await this.db.query(`SELECT COUNT(*) AS total FROM ${this.tableName} WHERE ${predicate}`, now);
3332
+ const total = Number(counted.rows?.[0]?.total ?? 0);
3333
+ if (!Number.isFinite(total) || total <= 0) return 0;
3334
+ if (!options.dryRun) await this.db.query(`DELETE FROM ${this.tableName} WHERE ${predicate}`, now);
3335
+ return total;
3336
+ }
3337
+ };
3338
+ var SESSIONS_RETENTION_TASK = "users-sessions";
3339
+ var MAGIC_LINK_RETENTION_TASK = "users-magic-link-tokens";
3340
+ var CLI_AUTH_RETENTION_TASK = "users-cli-auth-requests";
3341
+ function registerUserRetentionTasks() {
3342
+ registerRetentionTask({
3343
+ name: SESSIONS_RETENTION_TASK,
3344
+ description: "Delete expired and revoked sessions",
3345
+ run: async (db, context) => {
3346
+ return (await SessionCollection.create({ db })).deleteExpired({ dryRun: context.dryRun });
3347
+ }
3348
+ });
3349
+ registerRetentionTask({
3350
+ name: MAGIC_LINK_RETENTION_TASK,
3351
+ description: "Delete expired magic-link tokens",
3352
+ run: async (db, context) => {
3353
+ return (await UsersMagicLinkTokenCollection.create({ db })).deleteExpired({ dryRun: context.dryRun });
3354
+ }
3355
+ });
3356
+ registerRetentionTask({
3357
+ name: CLI_AUTH_RETENTION_TASK,
3358
+ description: "Delete expired pending, lazily-expired, and consumed CLI auth requests",
3359
+ run: async (db, context) => {
3360
+ return (await UsersCliAuthRequestCollection.create({ db })).deleteExpired({ dryRun: context.dryRun });
3361
+ }
3362
+ });
3363
+ }
3364
+ var __defProp$2 = Object.defineProperty;
3365
+ var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
3366
+ var __decorateClass$2 = (decorators, target, key, kind) => {
3367
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
3368
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
3369
+ if (kind && result) __defProp$2(target, key, result);
3370
+ return result;
3371
+ };
3372
+ var AccessRequest = class extends SmrtObject {
3373
+ email = "";
3374
+ name = null;
3375
+ status = AccessRequestStatus.REQUESTED;
3376
+ source = "";
3377
+ requestContext = "{}";
3378
+ note = null;
3379
+ requestedAt = /* @__PURE__ */ new Date();
3380
+ decidedAt = null;
3381
+ decidedBy = null;
3382
+ resultingUserId = null;
3383
+ tenantHint = null;
3384
+ constructor(options = {}) {
3385
+ super(options);
3386
+ if (options.email !== void 0) this.email = normalizeEmail(options.email);
3387
+ if (options.name !== void 0) this.name = options.name;
3388
+ if (options.status !== void 0) this.status = options.status;
3389
+ if (options.source !== void 0) this.source = options.source;
3390
+ if (options.requestContext !== void 0) this.requestContext = options.requestContext;
3391
+ if (options.note !== void 0) this.note = options.note;
3392
+ if (options.requestedAt !== void 0) this.requestedAt = options.requestedAt;
3393
+ if (options.decidedAt !== void 0) this.decidedAt = options.decidedAt;
3394
+ if (options.decidedBy !== void 0) this.decidedBy = options.decidedBy;
3395
+ if (options.resultingUserId !== void 0) this.resultingUserId = options.resultingUserId;
3396
+ if (options.tenantHint !== void 0) this.tenantHint = options.tenantHint;
3397
+ }
3398
+ /**
3399
+ * Parse {@link requestContext} into an object. Returns `{}` on missing or
3400
+ * malformed JSON (graceful — never throws).
3401
+ */
3402
+ getRequestContext() {
3403
+ try {
3404
+ const parsed = JSON.parse(this.requestContext);
3405
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
3406
+ } catch {
3407
+ return {};
3408
+ }
3409
+ }
3410
+ /**
3411
+ * Serialize and store {@link requestContext} from an object.
3412
+ */
3413
+ setRequestContext(value) {
3414
+ this.requestContext = JSON.stringify(value ?? {});
3415
+ }
3416
+ /**
3417
+ * Parse {@link tenantHint} into an object, or `null` when unset / malformed.
3418
+ */
3419
+ getTenantHint() {
3420
+ if (!this.tenantHint) return null;
3421
+ try {
3422
+ const parsed = JSON.parse(this.tenantHint);
3423
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
3424
+ } catch {
3425
+ return null;
3426
+ }
3427
+ }
3428
+ /**
3429
+ * Serialize and store {@link tenantHint} from an object (or clear with null).
3430
+ */
3431
+ setTenantHint(value) {
3432
+ this.tenantHint = value ? JSON.stringify(value) : null;
3433
+ }
3434
+ /**
3435
+ * Whether the request is still open (awaiting a decision).
3436
+ */
3437
+ isOpen() {
3438
+ return this.status === AccessRequestStatus.REQUESTED;
3439
+ }
3440
+ /**
3441
+ * Whether the request has been approved (and not yet graduated).
3442
+ */
3443
+ isApproved() {
3444
+ return this.status === AccessRequestStatus.APPROVED;
3445
+ }
3446
+ /**
3447
+ * Whether the request reached a terminal state (declined, graduated, or
3448
+ * canceled) and can no longer transition.
3449
+ */
3450
+ isTerminal() {
3451
+ return this.status === AccessRequestStatus.DECLINED || this.status === AccessRequestStatus.GRADUATED || this.status === AccessRequestStatus.CANCELED;
3452
+ }
3453
+ };
3454
+ __decorateClass$2([field({
3455
+ required: true,
3456
+ indexed: true
3457
+ })], AccessRequest.prototype, "email", 2);
3458
+ __decorateClass$2([field({ nullable: true })], AccessRequest.prototype, "name", 2);
3459
+ __decorateClass$2([field({
3460
+ type: "text",
3461
+ indexed: true
3462
+ })], AccessRequest.prototype, "status", 2);
3463
+ __decorateClass$2([field({ indexed: true })], AccessRequest.prototype, "source", 2);
3464
+ __decorateClass$2([field()], AccessRequest.prototype, "requestContext", 2);
3465
+ __decorateClass$2([field({ nullable: true })], AccessRequest.prototype, "note", 2);
3466
+ __decorateClass$2([field()], AccessRequest.prototype, "requestedAt", 2);
3467
+ __decorateClass$2([field({ nullable: true })], AccessRequest.prototype, "decidedAt", 2);
3468
+ __decorateClass$2([field({ nullable: true })], AccessRequest.prototype, "decidedBy", 2);
3469
+ __decorateClass$2([field({ nullable: true })], AccessRequest.prototype, "resultingUserId", 2);
3470
+ __decorateClass$2([field({ nullable: true })], AccessRequest.prototype, "tenantHint", 2);
3471
+ AccessRequest = __decorateClass$2([smrt({
3472
+ tableName: "access_requests",
3473
+ conflictColumns: ["id"],
3474
+ api: { include: [] },
3475
+ mcp: { include: [] },
3476
+ cli: { include: [] }
3477
+ })], AccessRequest);
3478
+ var __defProp$1 = Object.defineProperty;
3479
+ var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
3480
+ var __decorateClass$1 = (decorators, target, key, kind) => {
3481
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
3482
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
3483
+ if (kind && result) __defProp$1(target, key, result);
3484
+ return result;
3485
+ };
3486
+ var ResourceGrant = class extends SmrtObject {
3487
+ tenantId;
3488
+ userId;
3489
+ resourceType = "";
3490
+ resourceId = "";
3491
+ permission = "";
3492
+ effect = "grant";
3493
+ canDelegate = false;
3494
+ parentGrantId;
3495
+ revokedAt;
3496
+ constructor(options = {}) {
3497
+ super(options);
3498
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
3499
+ if (options.userId !== void 0) this.userId = options.userId;
3500
+ if (options.resourceType !== void 0) this.resourceType = options.resourceType;
3501
+ if (options.resourceId !== void 0) this.resourceId = options.resourceId;
3502
+ if (options.permission !== void 0) this.permission = options.permission;
3503
+ if (options.effect !== void 0) this.effect = options.effect;
3504
+ if (options.canDelegate !== void 0) this.canDelegate = options.canDelegate;
3505
+ if (options.parentGrantId !== void 0) this.parentGrantId = options.parentGrantId;
3506
+ if (options.revokedAt !== void 0) this.revokedAt = options.revokedAt;
3507
+ }
3508
+ isActive() {
3509
+ return !this.revokedAt;
3510
+ }
3511
+ };
3512
+ __decorateClass$1([foreignKey("Tenant", { required: true })], ResourceGrant.prototype, "tenantId", 2);
3513
+ __decorateClass$1([foreignKey("User", { required: true })], ResourceGrant.prototype, "userId", 2);
3514
+ __decorateClass$1([field({ type: "text" })], ResourceGrant.prototype, "resourceType", 2);
3515
+ __decorateClass$1([field({ type: "text" })], ResourceGrant.prototype, "resourceId", 2);
3516
+ __decorateClass$1([field({ type: "text" })], ResourceGrant.prototype, "permission", 2);
3517
+ __decorateClass$1([field({ type: "text" })], ResourceGrant.prototype, "effect", 2);
3518
+ __decorateClass$1([foreignKey("ResourceGrant")], ResourceGrant.prototype, "parentGrantId", 2);
3519
+ __decorateClass$1([field({ type: "text" })], ResourceGrant.prototype, "revokedAt", 2);
3520
+ ResourceGrant = __decorateClass$1([smrt({
3521
+ tenantScoped: true,
3522
+ api: { include: [] },
3523
+ mcp: { include: [] },
3524
+ cli: { skipApiCheck: true },
3525
+ indexes: [{
3526
+ name: "resource_grants_lookup_idx",
3527
+ columns: ["tenantId", "userId"]
3528
+ }]
3529
+ })], ResourceGrant);
3530
+ var __defProp = Object.defineProperty;
3531
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3532
+ var __decorateClass = (decorators, target, key, kind) => {
3533
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
3534
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
3535
+ if (kind && result) __defProp(target, key, result);
3536
+ return result;
3537
+ };
3538
+ function parseExternalIds(raw) {
3539
+ if (!raw) return {};
3540
+ if (typeof raw === "object" && !Array.isArray(raw)) return Object.fromEntries(Object.entries(raw).filter(([, value]) => typeof value === "string"));
3541
+ if (typeof raw !== "string") return {};
3542
+ try {
3543
+ const parsed = JSON.parse(raw);
3544
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
3545
+ return Object.fromEntries(Object.entries(parsed).filter(([, value]) => typeof value === "string"));
3546
+ } catch {
3547
+ return {};
3548
+ }
3549
+ }
3550
+ function stringifyExternalIds(externalIds) {
3551
+ for (const [key, value] of Object.entries(externalIds)) if (typeof value !== "string") throw new TypeError(`TenantIntegration external id '${key}' must be a string`);
3552
+ return JSON.stringify(externalIds);
3553
+ }
3554
+ function parseCheckSummary(raw) {
3555
+ if (!raw) return [];
3556
+ if (Array.isArray(raw)) return normalizeCheckSummary(raw);
3557
+ if (typeof raw !== "string") return [];
3558
+ try {
3559
+ const parsed = JSON.parse(raw);
3560
+ return Array.isArray(parsed) ? normalizeCheckSummary(parsed) : [];
3561
+ } catch {
3562
+ return [];
3563
+ }
3564
+ }
3565
+ function normalizeCheckSummary(raw) {
3566
+ return raw.filter((entry) => !!entry && typeof entry === "object" && !Array.isArray(entry)).map((entry) => ({
3567
+ name: typeof entry.name === "string" ? entry.name : "",
3568
+ ok: entry.ok === true,
3569
+ ...typeof entry.message === "string" ? { message: entry.message } : {}
3570
+ })).filter((entry) => entry.name.length > 0);
3571
+ }
3572
+ function stringifyCheckSummary(summary) {
3573
+ return JSON.stringify(summary);
3574
+ }
3575
+ var TenantIntegration = class extends SmrtObject {
3576
+ tenantId = "";
3577
+ /**
3578
+ * Provider identifier, such as `aws`, `matomo`, `glitchtip`, or an
3579
+ * app-defined provider string.
3580
+ */
3581
+ provider = "aws";
3582
+ /**
3583
+ * Provider-side identifiers. Shape depends on the provider. This must not
3584
+ * contain provider credentials or secret material.
3585
+ */
3586
+ externalIds = "{}";
3587
+ /**
3588
+ * Current provisioning/health status.
3589
+ */
3590
+ status = "unprovisioned";
3591
+ /**
3592
+ * UTC timestamp of the most recent doctor/provisioning check.
3593
+ */
3594
+ lastCheckedAt = null;
3595
+ /**
3596
+ * Per-check pass/fail summary from the most recent doctor run.
3597
+ */
3598
+ lastCheckSummary = "[]";
3599
+ /**
3600
+ * Most recent error message when `status === 'failed'`, or null otherwise.
3601
+ */
3602
+ lastError = null;
3603
+ constructor(options = {}) {
3604
+ super(options);
3605
+ if (options.tenantId !== void 0) this.tenantId = options.tenantId;
3606
+ if (options.provider !== void 0) this.provider = options.provider;
3607
+ if (options.externalIds !== void 0) this.setExternalIds(options.externalIds);
3608
+ if (options.status !== void 0) this.status = options.status;
3609
+ if (options.lastCheckedAt !== void 0) this.lastCheckedAt = options.lastCheckedAt;
3610
+ if (options.lastCheckSummary !== void 0) this.setLastCheckSummary(options.lastCheckSummary);
3611
+ if (options.lastError !== void 0) this.lastError = options.lastError;
3612
+ }
3613
+ async initialize() {
3614
+ await super.initialize();
3615
+ this.normalizeJsonFields();
3616
+ return this;
3617
+ }
3618
+ normalizeJsonFields() {
3619
+ const fields = this;
3620
+ if (fields.externalIds == null) this.externalIds = "{}";
3621
+ else if (typeof fields.externalIds !== "string") this.setExternalIds(fields.externalIds);
3622
+ if (fields.lastCheckSummary == null) this.lastCheckSummary = "[]";
3623
+ else if (typeof fields.lastCheckSummary !== "string") this.setLastCheckSummary(fields.lastCheckSummary);
3624
+ }
3625
+ getExternalIds() {
3626
+ return parseExternalIds(this.externalIds);
3627
+ }
3628
+ setExternalIds(externalIds) {
3629
+ this.externalIds = typeof externalIds === "string" ? externalIds : stringifyExternalIds(externalIds);
3630
+ }
3631
+ getExternalId(key) {
3632
+ const value = this.getExternalIds()[key];
3633
+ return typeof value === "string" && value.length > 0 ? value : void 0;
3634
+ }
3635
+ setExternalId(key, value) {
3636
+ const externalIds = this.getExternalIds();
3637
+ if (value === void 0) delete externalIds[key];
3638
+ else externalIds[key] = value;
3639
+ this.setExternalIds(externalIds);
3640
+ }
3641
+ getLastCheckSummary() {
3642
+ return parseCheckSummary(this.lastCheckSummary);
3643
+ }
3644
+ setLastCheckSummary(summary) {
3645
+ this.lastCheckSummary = typeof summary === "string" ? summary : stringifyCheckSummary(summary);
3646
+ }
3647
+ recordDoctorRun(outcome) {
3648
+ this.status = outcome.status;
3649
+ this.setLastCheckSummary(outcome.summary);
3650
+ this.lastCheckedAt = /* @__PURE__ */ new Date();
3651
+ this.lastError = outcome.error ?? null;
3652
+ }
3653
+ };
3654
+ __decorateClass([tenantId()], TenantIntegration.prototype, "tenantId", 2);
3655
+ TenantIntegration = __decorateClass([TenantScoped({ mode: "required" }), smrt({
3656
+ tableName: "tenant_integrations",
3657
+ conflictColumns: ["tenant_id", "provider"],
3658
+ api: { include: ["list", "get"] },
3659
+ mcp: { include: ["list", "get"] },
3660
+ cli: { skipApiCheck: true }
3661
+ })], TenantIntegration);
3662
+ var TenantHierarchyMaterializationError = class extends Error {
3663
+ constructor(problems) {
3664
+ super(`Cannot materialize the tenant hierarchy: ${problems.length} tenant(s) have a broken parent chain. ` + problems.map((problem) => problem.message).join(" "));
3665
+ this.problems = problems;
3666
+ this.name = "TenantHierarchyMaterializationError";
3667
+ }
3668
+ problems;
3669
+ };
3670
+ function toRow(row) {
3671
+ const id = row.id === null || row.id === void 0 ? "" : String(row.id);
3672
+ if (!id) throw new Error("Tenant hierarchy backfill found a row without an id.");
3673
+ const parent = row.parent_tenant_id === null || row.parent_tenant_id === void 0 ? null : String(row.parent_tenant_id);
3674
+ const level = row.hierarchy_level === null || row.hierarchy_level === void 0 ? null : Number(row.hierarchy_level);
3675
+ return {
3676
+ id,
3677
+ parentTenantId: parent === "" ? null : parent,
3678
+ hierarchyPath: row.hierarchy_path === null || row.hierarchy_path === void 0 ? null : String(row.hierarchy_path),
3679
+ hierarchyLevel: Number.isFinite(level) ? level : null
3680
+ };
3681
+ }
3682
+ async function planFrom(db, table) {
3683
+ const { rows } = await db.query(`SELECT id, parent_tenant_id, hierarchy_path, hierarchy_level FROM ${table} ORDER BY id`);
3684
+ return planTenantHierarchy(rows.map(toRow));
3685
+ }
3686
+ async function materializeTenantHierarchy(db, options = {}) {
3687
+ const table = assertTenantTableName(options.tableName ?? "tenants");
3688
+ if (options.dryRun) return {
3689
+ ...await planFrom(db, table),
3690
+ applied: false
3691
+ };
3692
+ const run = async (handle) => {
3693
+ const plan = await planFrom(handle, table);
3694
+ if (plan.problems.length > 0) throw new TenantHierarchyMaterializationError(plan.problems);
3695
+ await applyTenantHierarchyUpdates(handle, table, plan.changes);
3696
+ return {
3697
+ ...plan,
3698
+ applied: true
3699
+ };
3700
+ };
3701
+ if (!db.transaction) throw new Error("Tenant hierarchy materialization requires a database with transaction(); no changes were made.");
3702
+ const result = await db.transaction((tx) => run(tx));
3703
+ if (result.changes.length > 0) await recordTenantHierarchyChanges(db, table);
3704
+ return result;
3705
+ }
3706
+ createLogger({ level: "info" });
3707
+ AccessRequestStatus.REQUESTED;
3708
+ AccessRequestStatus.REQUESTED, AccessRequestStatus.APPROVED;
3709
+ AccessRequestStatus.REQUESTED, AccessRequestStatus.APPROVED;
3710
+ registerUserRetentionTasks();
3711
+ //#endregion
3712
+ export { ApiKeyCollection as A, OidcIdentityCollection as C, AuditLog as D, NostrIdentityCollection_exports as E, AuditLogCollection as O, AmbiguousOidcIdentityError as S, NostrIdentityCollection as T, TenantHierarchyMaterializationError, ProfileMetadataCollection as _, ProfileRelationshipTypeCollection as a, ProfileAssetCollection as b, ProfileRelationshipTermCollection as c, ProfileRelationshipCollection as d, ProfileRelationshipCollection_exports as f, ProfileMetadata as g, ProfileMetafieldCollection_exports as h, resolveIdentity_exports as i, ApiKeyCollection_exports as j, AuditLogCollection_exports as k, ProfileRelationshipTermCollection_exports as l, ProfileMetafieldCollection as m, materializeTenantHierarchy, createProfileFromOidc as n, ProfileRelationshipTypeCollection_exports as o, ProfileMetafield as p, resolveIdentity as r, ProfileRelationshipTerm as s, createProfileFromNostr as t, ProfileRelationship as u, ProfileMetadataCollection_exports as v, OidcIdentityCollection_exports as w, ProfileAssetCollection_exports as x, ProfileAsset as y };