@happyvertical/smrt-profiles 0.40.69 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/AGENTS.md +10 -5
  2. package/dist/chunks/{ApiKey-Br9NGBnr.js → ApiKey-CMm509C4.js} +5 -7
  3. package/dist/chunks/ApiKey-CMm509C4.js.map +1 -0
  4. package/dist/chunks/{ApiKeyCollection-CrTjdMz8.js → ApiKeyCollection-C6p7XgTz.js} +3 -3
  5. package/dist/chunks/{ApiKeyCollection-CrTjdMz8.js.map → ApiKeyCollection-C6p7XgTz.js.map} +1 -1
  6. package/dist/chunks/{AuditLogCollection-BBIEI6BD.js → AuditLogCollection-lJfGFdIQ.js} +2 -2
  7. package/dist/chunks/{AuditLogCollection-BBIEI6BD.js.map → AuditLogCollection-lJfGFdIQ.js.map} +1 -1
  8. package/dist/chunks/{NostrIdentity-DF_a_WZk.js → NostrIdentity-CgdM4ng0.js} +6 -8
  9. package/dist/chunks/{NostrIdentity-DF_a_WZk.js.map → NostrIdentity-CgdM4ng0.js.map} +1 -1
  10. package/dist/chunks/{NostrIdentityCollection-BRYUgt47.js → NostrIdentityCollection-BnHZOsUI.js} +2 -2
  11. package/dist/chunks/{NostrIdentityCollection-BRYUgt47.js.map → NostrIdentityCollection-BnHZOsUI.js.map} +1 -1
  12. package/dist/chunks/{OidcIdentity-CFbUlB_Z.js → OidcIdentity-DANnAbfU.js} +3 -3
  13. package/dist/chunks/{OidcIdentity-CFbUlB_Z.js.map → OidcIdentity-DANnAbfU.js.map} +1 -1
  14. package/dist/chunks/{OidcIdentityCollection-BLxSaqJT.js → OidcIdentityCollection-eSM4gzHL.js} +3 -3
  15. package/dist/chunks/{OidcIdentityCollection-BLxSaqJT.js.map → OidcIdentityCollection-eSM4gzHL.js.map} +1 -1
  16. package/dist/chunks/{ProfileAssetCollection-FhW8q7_1.js → ProfileAssetCollection-A_PpEaDq.js} +3 -3
  17. package/dist/chunks/{ProfileAssetCollection-FhW8q7_1.js.map → ProfileAssetCollection-A_PpEaDq.js.map} +1 -1
  18. package/dist/chunks/{ProfileCollection-DdJ3W4GG.js → ProfileCollection-BsKhR5Dp.js} +27 -35
  19. package/dist/chunks/{ProfileCollection-DdJ3W4GG.js.map → ProfileCollection-BsKhR5Dp.js.map} +1 -1
  20. package/dist/chunks/{ProfileMetadataCollection-loKVv_pj.js → ProfileMetadataCollection-Ceq-QV-1.js} +2 -2
  21. package/dist/chunks/{ProfileMetadataCollection-loKVv_pj.js.map → ProfileMetadataCollection-Ceq-QV-1.js.map} +1 -1
  22. package/dist/chunks/{ProfileMetafieldCollection-CACMY1hl.js → ProfileMetafieldCollection-CM374Dbh.js} +2 -2
  23. package/dist/chunks/{ProfileMetafieldCollection-CACMY1hl.js.map → ProfileMetafieldCollection-CM374Dbh.js.map} +1 -1
  24. package/dist/chunks/{ProfileRelationshipCollection-CzQKfvMy.js → ProfileRelationshipCollection-DuPcpzp1.js} +5 -5
  25. package/dist/chunks/{ProfileRelationshipCollection-CzQKfvMy.js.map → ProfileRelationshipCollection-DuPcpzp1.js.map} +1 -1
  26. package/dist/chunks/{ProfileRelationshipTermCollection-DzmU48P6.js → ProfileRelationshipTermCollection-Bw32vYB8.js} +2 -2
  27. package/dist/chunks/{ProfileRelationshipTermCollection-DzmU48P6.js.map → ProfileRelationshipTermCollection-Bw32vYB8.js.map} +1 -1
  28. package/dist/chunks/{ProfileRelationshipType-BjoaCt-u.js → ProfileRelationshipType-CZm2X1qY.js} +2 -2
  29. package/dist/chunks/{ProfileRelationshipType-BjoaCt-u.js.map → ProfileRelationshipType-CZm2X1qY.js.map} +1 -1
  30. package/dist/chunks/{ProfileRelationshipTypeCollection-Bh4xJ4-I.js → ProfileRelationshipTypeCollection-CtoeCpp_.js} +3 -3
  31. package/dist/chunks/{ProfileRelationshipTypeCollection-Bh4xJ4-I.js.map → ProfileRelationshipTypeCollection-CtoeCpp_.js.map} +1 -1
  32. package/dist/chunks/{oidcProvisioningPrimitives-C9XSQNZj.js → oidcProvisioningPrimitives-Bzv4VTcn.js} +23 -8
  33. package/dist/chunks/oidcProvisioningPrimitives-Bzv4VTcn.js.map +1 -0
  34. package/dist/chunks/{resolveIdentity-BpkxPkz7.js → resolveIdentity-DusCiNZo.js} +17 -17
  35. package/dist/chunks/{resolveIdentity-BpkxPkz7.js.map → resolveIdentity-DusCiNZo.js.map} +1 -1
  36. package/dist/index.d.ts +12 -3
  37. package/dist/index.js +24 -26
  38. package/dist/index.js.map +1 -1
  39. package/dist/internal/oidc-provisioning.js +2 -2
  40. package/dist/manifest.json +399 -215
  41. package/dist/oidc-provisioning.d.ts +13 -1
  42. package/dist/smrt-knowledge.json +40 -5
  43. package/dist/types.d.ts +8 -2
  44. package/dist/utils.d.ts +8 -2
  45. package/dist/utils.js +4 -4
  46. package/package.json +6 -6
  47. package/dist/chunks/ApiKey-Br9NGBnr.js.map +0 -1
  48. package/dist/chunks/oidcProvisioningPrimitives-C9XSQNZj.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { c as generateNostrKeypair, s as encryptPrivkey, t as NostrIdentity, y as __exportAll } from "./NostrIdentity-DF_a_WZk.js";
1
+ import { c as generateNostrKeypair, s as encryptPrivkey, t as NostrIdentity, y as __exportAll } from "./NostrIdentity-CgdM4ng0.js";
2
2
  import { SmrtCollection } from "@happyvertical/smrt-core";
3
3
  //#region src/collections/NostrIdentityCollection.ts
4
4
  var NostrIdentityCollection_exports = /* @__PURE__ */ __exportAll({ NostrIdentityCollection: () => NostrIdentityCollection });
@@ -121,4 +121,4 @@ var NostrIdentityCollection = class extends SmrtCollection {
121
121
  //#endregion
122
122
  export { NostrIdentityCollection_exports as n, NostrIdentityCollection as t };
123
123
 
124
- //# sourceMappingURL=NostrIdentityCollection-BRYUgt47.js.map
124
+ //# sourceMappingURL=NostrIdentityCollection-BnHZOsUI.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NostrIdentityCollection-BRYUgt47.js","names":[],"sources":["../../src/collections/NostrIdentityCollection.ts"],"sourcesContent":["/**\n * NostrIdentityCollection - Collection for managing Nostr identity records\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { encryptPrivkey, generateNostrKeypair } from '../auth/nostrCrypto';\nimport { NostrIdentity } from '../models/NostrIdentity';\nimport type { Profile } from '../models/Profile';\n\nexport interface Nip05Response {\n names: Record<string, string>;\n relays?: Record<string, string[]>;\n}\n\nexport class NostrIdentityCollection extends SmrtCollection<NostrIdentity> {\n static readonly _itemClass = NostrIdentity;\n\n /**\n * Find identities for a profile\n */\n async findByProfile(profileId: string): Promise<NostrIdentity[]> {\n return await this.list({\n where: { profileId },\n });\n }\n\n /**\n * Find identity by public key\n */\n async findByPubkey(pubkey: string): Promise<NostrIdentity | null> {\n return await this.findOne({\n where: { pubkey },\n });\n }\n\n /**\n * Find identity by email\n */\n async findByEmail(email: string): Promise<NostrIdentity | null> {\n return await this.findOne({\n where: { email: email.toLowerCase() },\n });\n }\n\n /**\n * Find identity by NIP-05 username\n */\n async findByNip05(username: string): Promise<NostrIdentity | null> {\n return await this.findOne({\n where: { nip05Username: username.toLowerCase() },\n });\n }\n\n /**\n * Link a new Nostr identity to a profile with a new keypair\n * @param profile - The profile to link to\n * @param email - Email address for this identity\n * @param masterSecret - Server master secret for encryption\n * @param nip05Username - Optional NIP-05 username (defaults to email local part)\n */\n async createForProfile(\n profile: Profile,\n email: string,\n masterSecret: string,\n nip05Username?: string,\n ): Promise<NostrIdentity> {\n const normalizedEmail = email.toLowerCase();\n\n // Check if already exists for this email\n const existing = await this.findByEmail(normalizedEmail);\n if (existing) {\n throw new Error(`Nostr identity already exists for email: ${email}`);\n }\n\n // Generate new keypair\n const keypair = generateNostrKeypair();\n\n // Encrypt private key\n const encrypted = encryptPrivkey(keypair.privkey, masterSecret);\n\n // Derive NIP-05 username from email if not provided\n const username =\n nip05Username?.toLowerCase() || normalizedEmail.split('@')[0];\n\n // Create identity\n const identity = new NostrIdentity({\n ...this.options,\n profileId: profile.id as string,\n pubkey: keypair.pubkey,\n encryptedPrivkey: encrypted.ciphertext,\n encryptionIv: encrypted.iv,\n encryptionTag: encrypted.tag,\n email: normalizedEmail,\n nip05Username: username,\n });\n\n await identity.initialize();\n await identity.save();\n\n return identity;\n }\n\n /**\n * Link an existing Nostr identity (with encrypted keypair) to a profile\n */\n async linkToProfile(\n profile: Profile,\n nostrData: {\n pubkey: string;\n encryptedPrivkey: string;\n encryptionIv: string;\n encryptionTag: string;\n email: string;\n nip05Username?: string;\n },\n ): Promise<NostrIdentity> {\n // Check if pubkey already exists\n const existingPubkey = await this.findByPubkey(nostrData.pubkey);\n if (existingPubkey) {\n throw new Error('Nostr identity with this public key already exists');\n }\n\n // Check if email already exists\n const existingEmail = await this.findByEmail(nostrData.email);\n if (existingEmail) {\n throw new Error('Nostr identity with this email already exists');\n }\n\n const identity = new NostrIdentity({\n ...this.options,\n profileId: profile.id as string,\n pubkey: nostrData.pubkey,\n encryptedPrivkey: nostrData.encryptedPrivkey,\n encryptionIv: nostrData.encryptionIv,\n encryptionTag: nostrData.encryptionTag,\n email: nostrData.email.toLowerCase(),\n nip05Username:\n nostrData.nip05Username?.toLowerCase() ||\n nostrData.email.toLowerCase().split('@')[0],\n });\n\n await identity.initialize();\n await identity.save();\n\n return identity;\n }\n\n /**\n * Unlink a Nostr identity from a profile\n */\n async unlinkFromProfile(profileId: string, pubkey: string): Promise<boolean> {\n const identity = await this.findOne({\n where: { profileId, pubkey },\n });\n\n if (identity) {\n await identity.delete();\n return true;\n }\n return false;\n }\n\n /**\n * Get NIP-05 response data for the /.well-known/nostr.json endpoint\n * @param username - Optional username filter, returns all if not provided\n */\n async getNip05Response(username?: string): Promise<Nip05Response> {\n const where = username ? { nip05Username: username.toLowerCase() } : {};\n\n const identities = await this.list({\n where,\n // Only return verified identities for NIP-05\n // Uncomment if you want to require verification:\n // where: { ...where, 'verifiedAt IS NOT': null },\n });\n\n const names: Record<string, string> = {};\n for (const identity of identities) {\n if (identity.nip05Username && identity.pubkey) {\n names[identity.nip05Username] = identity.pubkey;\n }\n }\n\n return { names };\n }\n\n /**\n * Check if a NIP-05 username is available\n */\n async isNip05Available(username: string): Promise<boolean> {\n const existing = await this.findByNip05(username);\n return existing === null;\n }\n\n /**\n * Update NIP-05 username for an identity\n */\n async updateNip05Username(\n identity: NostrIdentity,\n newUsername: string,\n ): Promise<NostrIdentity> {\n const normalizedUsername = newUsername.toLowerCase();\n\n // Check if username is available\n const existing = await this.findByNip05(normalizedUsername);\n if (existing && existing.id !== identity.id) {\n throw new Error(`NIP-05 username \"${newUsername}\" is already taken`);\n }\n\n identity.nip05Username = normalizedUsername;\n await identity.save();\n\n return identity;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NostrIdentityCollection-BnHZOsUI.js","names":[],"sources":["../../src/collections/NostrIdentityCollection.ts"],"sourcesContent":["/**\n * NostrIdentityCollection - Collection for managing Nostr identity records\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { encryptPrivkey, generateNostrKeypair } from '../auth/nostrCrypto';\nimport { NostrIdentity } from '../models/NostrIdentity';\nimport type { Profile } from '../models/Profile';\n\nexport interface Nip05Response {\n names: Record<string, string>;\n relays?: Record<string, string[]>;\n}\n\nexport class NostrIdentityCollection extends SmrtCollection<NostrIdentity> {\n static readonly _itemClass = NostrIdentity;\n\n /**\n * Find identities for a profile\n */\n async findByProfile(profileId: string): Promise<NostrIdentity[]> {\n return await this.list({\n where: { profileId },\n });\n }\n\n /**\n * Find identity by public key\n */\n async findByPubkey(pubkey: string): Promise<NostrIdentity | null> {\n return await this.findOne({\n where: { pubkey },\n });\n }\n\n /**\n * Find identity by email\n */\n async findByEmail(email: string): Promise<NostrIdentity | null> {\n return await this.findOne({\n where: { email: email.toLowerCase() },\n });\n }\n\n /**\n * Find identity by NIP-05 username\n */\n async findByNip05(username: string): Promise<NostrIdentity | null> {\n return await this.findOne({\n where: { nip05Username: username.toLowerCase() },\n });\n }\n\n /**\n * Link a new Nostr identity to a profile with a new keypair\n * @param profile - The profile to link to\n * @param email - Email address for this identity\n * @param masterSecret - Server master secret for encryption\n * @param nip05Username - Optional NIP-05 username (defaults to email local part)\n */\n async createForProfile(\n profile: Profile,\n email: string,\n masterSecret: string,\n nip05Username?: string,\n ): Promise<NostrIdentity> {\n const normalizedEmail = email.toLowerCase();\n\n // Check if already exists for this email\n const existing = await this.findByEmail(normalizedEmail);\n if (existing) {\n throw new Error(`Nostr identity already exists for email: ${email}`);\n }\n\n // Generate new keypair\n const keypair = generateNostrKeypair();\n\n // Encrypt private key\n const encrypted = encryptPrivkey(keypair.privkey, masterSecret);\n\n // Derive NIP-05 username from email if not provided\n const username =\n nip05Username?.toLowerCase() || normalizedEmail.split('@')[0];\n\n // Create identity\n const identity = new NostrIdentity({\n ...this.options,\n profileId: profile.id as string,\n pubkey: keypair.pubkey,\n encryptedPrivkey: encrypted.ciphertext,\n encryptionIv: encrypted.iv,\n encryptionTag: encrypted.tag,\n email: normalizedEmail,\n nip05Username: username,\n });\n\n await identity.initialize();\n await identity.save();\n\n return identity;\n }\n\n /**\n * Link an existing Nostr identity (with encrypted keypair) to a profile\n */\n async linkToProfile(\n profile: Profile,\n nostrData: {\n pubkey: string;\n encryptedPrivkey: string;\n encryptionIv: string;\n encryptionTag: string;\n email: string;\n nip05Username?: string;\n },\n ): Promise<NostrIdentity> {\n // Check if pubkey already exists\n const existingPubkey = await this.findByPubkey(nostrData.pubkey);\n if (existingPubkey) {\n throw new Error('Nostr identity with this public key already exists');\n }\n\n // Check if email already exists\n const existingEmail = await this.findByEmail(nostrData.email);\n if (existingEmail) {\n throw new Error('Nostr identity with this email already exists');\n }\n\n const identity = new NostrIdentity({\n ...this.options,\n profileId: profile.id as string,\n pubkey: nostrData.pubkey,\n encryptedPrivkey: nostrData.encryptedPrivkey,\n encryptionIv: nostrData.encryptionIv,\n encryptionTag: nostrData.encryptionTag,\n email: nostrData.email.toLowerCase(),\n nip05Username:\n nostrData.nip05Username?.toLowerCase() ||\n nostrData.email.toLowerCase().split('@')[0],\n });\n\n await identity.initialize();\n await identity.save();\n\n return identity;\n }\n\n /**\n * Unlink a Nostr identity from a profile\n */\n async unlinkFromProfile(profileId: string, pubkey: string): Promise<boolean> {\n const identity = await this.findOne({\n where: { profileId, pubkey },\n });\n\n if (identity) {\n await identity.delete();\n return true;\n }\n return false;\n }\n\n /**\n * Get NIP-05 response data for the /.well-known/nostr.json endpoint\n * @param username - Optional username filter, returns all if not provided\n */\n async getNip05Response(username?: string): Promise<Nip05Response> {\n const where = username ? { nip05Username: username.toLowerCase() } : {};\n\n const identities = await this.list({\n where,\n // Only return verified identities for NIP-05\n // Uncomment if you want to require verification:\n // where: { ...where, 'verifiedAt IS NOT': null },\n });\n\n const names: Record<string, string> = {};\n for (const identity of identities) {\n if (identity.nip05Username && identity.pubkey) {\n names[identity.nip05Username] = identity.pubkey;\n }\n }\n\n return { names };\n }\n\n /**\n * Check if a NIP-05 username is available\n */\n async isNip05Available(username: string): Promise<boolean> {\n const existing = await this.findByNip05(username);\n return existing === null;\n }\n\n /**\n * Update NIP-05 username for an identity\n */\n async updateNip05Username(\n identity: NostrIdentity,\n newUsername: string,\n ): Promise<NostrIdentity> {\n const normalizedUsername = newUsername.toLowerCase();\n\n // Check if username is available\n const existing = await this.findByNip05(normalizedUsername);\n if (existing && existing.id !== identity.id) {\n throw new Error(`NIP-05 username \"${newUsername}\" is already taken`);\n }\n\n identity.nip05Username = normalizedUsername;\n await identity.save();\n\n return identity;\n }\n}\n"],"mappings":"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"}
@@ -35,7 +35,7 @@ var OidcIdentity = class extends SmrtObject {
35
35
  * Find identity by issuer and subject
36
36
  */
37
37
  static async findBySubject(issuer, subject, options = {}) {
38
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-BLxSaqJT.js").then((n) => n.r);
38
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-eSM4gzHL.js").then((n) => n.r);
39
39
  return await (await OidcIdentityCollection.create(options)).findBySubject(issuer, subject);
40
40
  }
41
41
  /** Build the collision-free natural key for one OIDC issuer subject. */
@@ -58,7 +58,7 @@ var OidcIdentity = class extends SmrtObject {
58
58
  static async findOrCreate(profile, oidcData, options = {}) {
59
59
  const profileId = profile.id;
60
60
  if (typeof profileId !== "string" || !profileId) throw new Error("OidcIdentity.findOrCreate() requires a saved Profile.");
61
- const { reuseExistingOidcIdentityForProfile } = await import("./resolveIdentity-BpkxPkz7.js").then((n) => n.i);
61
+ const { reuseExistingOidcIdentityForProfile } = await import("./resolveIdentity-DusCiNZo.js").then((n) => n.i);
62
62
  const profileOptions = profile.options ?? {};
63
63
  return (await reuseExistingOidcIdentityForProfile(profileId, {
64
64
  email: oidcData.email,
@@ -108,4 +108,4 @@ OidcIdentity = __decorateClass([smrt({
108
108
  //#endregion
109
109
  export { OidcIdentity as t };
110
110
 
111
- //# sourceMappingURL=OidcIdentity-CFbUlB_Z.js.map
111
+ //# sourceMappingURL=OidcIdentity-DANnAbfU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OidcIdentity-CFbUlB_Z.js","names":[],"sources":["../../src/models/OidcIdentity.ts"],"sourcesContent":["/**\n * OidcIdentity - Links OIDC provider identities to Profile\n *\n * Stores the mapping between external OIDC providers (Keycloak, Google, GitHub)\n * and internal Profile records. Multiple identities can link to a single profile.\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { Profile } from './Profile';\n\nexport interface OidcIdentityOptions extends SmrtObjectOptions {\n profileId?: string;\n provider?: string;\n issuer?: string;\n subject?: string;\n email?: string;\n lastUsedAt?: Date | null;\n}\n\n@smrt({\n tableName: 'oidc_identities',\n // Identity linking is an authentication authority change. Generated routes\n // authenticate callers but do not authorize Profile ownership, so mutations\n // must stay behind the trusted provisioning APIs below.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class OidcIdentity extends SmrtObject {\n /**\n * Link to the Profile (Person, Organization, Bot)\n */\n @foreignKey('Profile', { required: true })\n profileId?: string;\n\n /**\n * Provider name (e.g., 'keycloak', 'google', 'github')\n */\n @field({ type: 'text' })\n provider: string = '';\n\n /**\n * OIDC issuer URL (e.g., https://keycloak.example.com/realms/bmp)\n */\n @field({ type: 'text', indexed: true })\n issuer: string = '';\n\n /**\n * OIDC subject claim - unique identifier from the provider\n */\n @field({ type: 'text', indexed: true })\n subject: string = '';\n\n /**\n * Stable issuer+subject key used as the database race arbiter.\n *\n * Nullable for legacy rows; every newly linked or reused identity backfills\n * it. A separate unique constraint makes concurrent first login fail with a\n * retryable conflict instead of creating two identities.\n */\n @field({ type: 'text', nullable: true, unique: true, readonly: true })\n identityKey: string | null = null;\n\n /**\n * Cached email from the IdP (for display/lookup)\n */\n @field({ type: 'text' })\n email: string = '';\n\n /**\n * Last time this identity was used for authentication\n */\n @field({ type: 'datetime', nullable: true })\n lastUsedAt: Date | null = null;\n\n constructor(options: OidcIdentityOptions = {}) {\n super(options);\n if (options.profileId) this.profileId = options.profileId;\n if (options.provider) this.provider = options.provider;\n if (options.issuer) this.issuer = options.issuer;\n if (options.subject) this.subject = options.subject;\n if (options.email) this.email = options.email;\n if (options.lastUsedAt !== undefined) this.lastUsedAt = options.lastUsedAt;\n }\n\n /**\n * Get the linked Profile\n */\n async getProfile(): Promise<Profile | null> {\n return (await this.getRelated('profileId')) as Profile | null;\n }\n\n /**\n * Find identity by issuer and subject\n */\n static async findBySubject(\n issuer: string,\n subject: string,\n options: SmrtObjectOptions = {},\n ): Promise<OidcIdentity | null> {\n const { OidcIdentityCollection } = await import(\n '../collections/OidcIdentityCollection'\n );\n const collection = await OidcIdentityCollection.create(options);\n return await collection.findBySubject(issuer, subject);\n }\n\n /** Build the collision-free natural key for one OIDC issuer subject. */\n static buildIdentityKey(issuer: string, subject: string): string {\n return JSON.stringify([issuer, subject]);\n }\n\n /** Keep the durable key derived from its natural-key source fields. */\n override async save(): Promise<this> {\n this.identityKey =\n this.issuer.trim() && this.subject.trim()\n ? OidcIdentity.buildIdentityKey(this.issuer, this.subject)\n : null;\n return super.save();\n }\n\n /**\n * Reuse an existing exact identity for its unchanged Profile.\n *\n * @deprecated Authentication links must be created through transactional\n * provisioning. This compatibility method only refreshes a unique mapping\n * that already belongs to the supplied Profile, including legacy Profile\n * types, and deliberately refuses to create or rebind authority.\n */\n static async findOrCreate(\n profile: Profile,\n oidcData: {\n provider: string;\n issuer: string;\n subject: string;\n email?: string;\n },\n options: SmrtObjectOptions = {},\n ): Promise<OidcIdentity> {\n const profileId = profile.id;\n if (typeof profileId !== 'string' || !profileId) {\n throw new Error('OidcIdentity.findOrCreate() requires a saved Profile.');\n }\n const { reuseExistingOidcIdentityForProfile } = await import(\n '../auth/resolveIdentity'\n );\n const profileOptions = profile.options ?? {};\n const result = await reuseExistingOidcIdentityForProfile(\n profileId,\n {\n email: oidcData.email,\n iss: oidcData.issuer,\n sub: oidcData.subject,\n },\n oidcData.provider,\n {\n ...profileOptions,\n ...options,\n db: options.db ?? profileOptions.db,\n },\n );\n return result.oidcIdentity;\n }\n\n /**\n * Record usage of this identity\n */\n async recordUsage(): Promise<void> {\n this.lastUsedAt = new Date();\n await this.save();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"OidcIdentity-DANnAbfU.js","names":[],"sources":["../../src/models/OidcIdentity.ts"],"sourcesContent":["/**\n * OidcIdentity - Links OIDC provider identities to Profile\n *\n * Stores the mapping between external OIDC providers (Keycloak, Google, GitHub)\n * and internal Profile records. Multiple identities can link to a single profile.\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { Profile } from './Profile';\n\nexport interface OidcIdentityOptions extends SmrtObjectOptions {\n profileId?: string;\n provider?: string;\n issuer?: string;\n subject?: string;\n email?: string;\n lastUsedAt?: Date | null;\n}\n\n@smrt({\n tableName: 'oidc_identities',\n // Identity linking is an authentication authority change. Generated routes\n // authenticate callers but do not authorize Profile ownership, so mutations\n // must stay behind the trusted provisioning APIs below.\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class OidcIdentity extends SmrtObject {\n /**\n * Link to the Profile (Person, Organization, Bot)\n */\n @foreignKey('Profile', { required: true })\n profileId?: string;\n\n /**\n * Provider name (e.g., 'keycloak', 'google', 'github')\n */\n @field({ type: 'text' })\n provider: string = '';\n\n /**\n * OIDC issuer URL (e.g., https://keycloak.example.com/realms/bmp)\n */\n @field({ type: 'text', indexed: true })\n issuer: string = '';\n\n /**\n * OIDC subject claim - unique identifier from the provider\n */\n @field({ type: 'text', indexed: true })\n subject: string = '';\n\n /**\n * Stable issuer+subject key used as the database race arbiter.\n *\n * Nullable for legacy rows; every newly linked or reused identity backfills\n * it. A separate unique constraint makes concurrent first login fail with a\n * retryable conflict instead of creating two identities.\n */\n @field({ type: 'text', nullable: true, unique: true, readonly: true })\n identityKey: string | null = null;\n\n /**\n * Cached email from the IdP (for display/lookup)\n */\n @field({ type: 'text' })\n email: string = '';\n\n /**\n * Last time this identity was used for authentication\n */\n @field({ type: 'datetime', nullable: true })\n lastUsedAt: Date | null = null;\n\n constructor(options: OidcIdentityOptions = {}) {\n super(options);\n if (options.profileId) this.profileId = options.profileId;\n if (options.provider) this.provider = options.provider;\n if (options.issuer) this.issuer = options.issuer;\n if (options.subject) this.subject = options.subject;\n if (options.email) this.email = options.email;\n if (options.lastUsedAt !== undefined) this.lastUsedAt = options.lastUsedAt;\n }\n\n /**\n * Get the linked Profile\n */\n async getProfile(): Promise<Profile | null> {\n return (await this.getRelated('profileId')) as Profile | null;\n }\n\n /**\n * Find identity by issuer and subject\n */\n static async findBySubject(\n issuer: string,\n subject: string,\n options: SmrtObjectOptions = {},\n ): Promise<OidcIdentity | null> {\n const { OidcIdentityCollection } = await import(\n '../collections/OidcIdentityCollection'\n );\n const collection = await OidcIdentityCollection.create(options);\n return await collection.findBySubject(issuer, subject);\n }\n\n /** Build the collision-free natural key for one OIDC issuer subject. */\n static buildIdentityKey(issuer: string, subject: string): string {\n return JSON.stringify([issuer, subject]);\n }\n\n /** Keep the durable key derived from its natural-key source fields. */\n override async save(): Promise<this> {\n this.identityKey =\n this.issuer.trim() && this.subject.trim()\n ? OidcIdentity.buildIdentityKey(this.issuer, this.subject)\n : null;\n return super.save();\n }\n\n /**\n * Reuse an existing exact identity for its unchanged Profile.\n *\n * @deprecated Authentication links must be created through transactional\n * provisioning. This compatibility method only refreshes a unique mapping\n * that already belongs to the supplied Profile, including legacy Profile\n * types, and deliberately refuses to create or rebind authority.\n */\n static async findOrCreate(\n profile: Profile,\n oidcData: {\n provider: string;\n issuer: string;\n subject: string;\n email?: string;\n },\n options: SmrtObjectOptions = {},\n ): Promise<OidcIdentity> {\n const profileId = profile.id;\n if (typeof profileId !== 'string' || !profileId) {\n throw new Error('OidcIdentity.findOrCreate() requires a saved Profile.');\n }\n const { reuseExistingOidcIdentityForProfile } = await import(\n '../auth/resolveIdentity'\n );\n const profileOptions = profile.options ?? {};\n const result = await reuseExistingOidcIdentityForProfile(\n profileId,\n {\n email: oidcData.email,\n iss: oidcData.issuer,\n sub: oidcData.subject,\n },\n oidcData.provider,\n {\n ...profileOptions,\n ...options,\n db: options.db ?? profileOptions.db,\n },\n );\n return result.oidcIdentity;\n }\n\n /**\n * Record usage of this identity\n */\n async recordUsage(): Promise<void> {\n this.lastUsedAt = new Date();\n await this.save();\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { y as __exportAll } from "./NostrIdentity-DF_a_WZk.js";
2
- import { t as OidcIdentity } from "./OidcIdentity-CFbUlB_Z.js";
1
+ import { y as __exportAll } from "./NostrIdentity-CgdM4ng0.js";
2
+ import { t as OidcIdentity } from "./OidcIdentity-DANnAbfU.js";
3
3
  import { SmrtCollection } from "@happyvertical/smrt-core";
4
4
  //#region src/collections/OidcIdentityCollection.ts
5
5
  var OidcIdentityCollection_exports = /* @__PURE__ */ __exportAll({
@@ -73,4 +73,4 @@ var OidcIdentityCollection = class extends SmrtCollection {
73
73
  //#endregion
74
74
  export { OidcIdentityCollection as n, OidcIdentityCollection_exports as r, AmbiguousOidcIdentityError as t };
75
75
 
76
- //# sourceMappingURL=OidcIdentityCollection-BLxSaqJT.js.map
76
+ //# sourceMappingURL=OidcIdentityCollection-eSM4gzHL.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OidcIdentityCollection-BLxSaqJT.js","names":[],"sources":["../../src/collections/OidcIdentityCollection.ts"],"sourcesContent":["/**\n * OidcIdentityCollection - Collection for managing OIDC identity records\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { OidcIdentity } from '../models/OidcIdentity';\nimport type { Profile } from '../models/Profile';\n\n/** More than one legacy row maps the same opaque OIDC issuer and subject. */\nexport class AmbiguousOidcIdentityError extends Error {\n constructor(\n readonly issuer: string,\n readonly subject: string,\n ) {\n super('Multiple OIDC identities match the same issuer and subject.');\n this.name = 'AmbiguousOidcIdentityError';\n }\n}\n\nexport class OidcIdentityCollection extends SmrtCollection<OidcIdentity> {\n static readonly _itemClass = OidcIdentity;\n\n /**\n * Find identities for a profile\n */\n async findByProfile(profileId: string): Promise<OidcIdentity[]> {\n return await this.list({\n where: { profileId },\n });\n }\n\n /**\n * Find identity by issuer and subject\n */\n async findBySubject(\n issuer: string,\n subject: string,\n ): Promise<OidcIdentity | null> {\n const matches = await this.list({\n where: { issuer, subject },\n limit: 2,\n });\n if (matches.length > 1) {\n throw new AmbiguousOidcIdentityError(issuer, subject);\n }\n return matches[0] ?? null;\n }\n\n /**\n * Find identities by provider\n */\n async findByProvider(provider: string): Promise<OidcIdentity[]> {\n return await this.list({\n where: { provider },\n });\n }\n\n /**\n * Reuse an existing exact OIDC identity for its unchanged Profile.\n *\n * @deprecated New authentication links require the owner-aware,\n * transactional provisioning APIs. This compatibility helper may refresh a\n * legacy Profile type, but refuses to create or rebind authority.\n */\n async linkToProfile(\n profile: Profile,\n oidcData: {\n provider: string;\n issuer: string;\n subject: string;\n email?: string;\n },\n ): Promise<OidcIdentity> {\n return OidcIdentity.findOrCreate(profile, oidcData, this.options);\n }\n\n /**\n * Unlink an OIDC identity from a profile\n */\n async unlinkFromProfile(\n profileId: string,\n issuer: string,\n subject: string,\n ): Promise<boolean> {\n const identity = await this.findOne({\n where: { profileId, issuer, subject },\n });\n\n if (identity) {\n await identity.delete();\n return true;\n }\n return false;\n }\n}\n"],"mappings":";;;;;;;;AASO,IAAM,6BAAN,cAAyC,MAAM;CACpD,YACW,QACA,SACT;EACA,MAAM,6DAA6D;EAH1D,KAAA,SAAA;EACA,KAAA,UAAA;EAGT,KAAK,OAAO;CACd;CALW;CACA;AAKb;AAEO,IAAM,yBAAN,cAAqC,eAA6B;CACvE,OAAgB,aAAa;;;;CAK7B,MAAM,cAAc,WAA4C;EAC9D,OAAO,MAAM,KAAK,KAAK,EACrB,OAAO,EAAE,UAAU,EACrB,CAAC;CACH;;;;CAKA,MAAM,cACJ,QACA,SAC8B;EAC9B,MAAM,UAAU,MAAM,KAAK,KAAK;GAC9B,OAAO;IAAE;IAAQ;GAAQ;GACzB,OAAO;EACT,CAAC;EACD,IAAI,QAAQ,SAAS,GACnB,MAAM,IAAI,2BAA2B,QAAQ,OAAO;EAEtD,OAAO,QAAQ,MAAM;CACvB;;;;CAKA,MAAM,eAAe,UAA2C;EAC9D,OAAO,MAAM,KAAK,KAAK,EACrB,OAAO,EAAE,SAAS,EACpB,CAAC;CACH;;;;;;;;CASA,MAAM,cACJ,SACA,UAMuB;EACvB,OAAO,aAAa,aAAa,SAAS,UAAU,KAAK,OAAO;CAClE;;;;CAKA,MAAM,kBACJ,WACA,QACA,SACkB;EAClB,MAAM,WAAW,MAAM,KAAK,QAAQ,EAClC,OAAO;GAAE;GAAW;GAAQ;EAAQ,EACtC,CAAC;EAED,IAAI,UAAU;GACZ,MAAM,SAAS,OAAO;GACtB,OAAO;EACT;EACA,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"OidcIdentityCollection-eSM4gzHL.js","names":[],"sources":["../../src/collections/OidcIdentityCollection.ts"],"sourcesContent":["/**\n * OidcIdentityCollection - Collection for managing OIDC identity records\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { OidcIdentity } from '../models/OidcIdentity';\nimport type { Profile } from '../models/Profile';\n\n/** More than one legacy row maps the same opaque OIDC issuer and subject. */\nexport class AmbiguousOidcIdentityError extends Error {\n constructor(\n readonly issuer: string,\n readonly subject: string,\n ) {\n super('Multiple OIDC identities match the same issuer and subject.');\n this.name = 'AmbiguousOidcIdentityError';\n }\n}\n\nexport class OidcIdentityCollection extends SmrtCollection<OidcIdentity> {\n static readonly _itemClass = OidcIdentity;\n\n /**\n * Find identities for a profile\n */\n async findByProfile(profileId: string): Promise<OidcIdentity[]> {\n return await this.list({\n where: { profileId },\n });\n }\n\n /**\n * Find identity by issuer and subject\n */\n async findBySubject(\n issuer: string,\n subject: string,\n ): Promise<OidcIdentity | null> {\n const matches = await this.list({\n where: { issuer, subject },\n limit: 2,\n });\n if (matches.length > 1) {\n throw new AmbiguousOidcIdentityError(issuer, subject);\n }\n return matches[0] ?? null;\n }\n\n /**\n * Find identities by provider\n */\n async findByProvider(provider: string): Promise<OidcIdentity[]> {\n return await this.list({\n where: { provider },\n });\n }\n\n /**\n * Reuse an existing exact OIDC identity for its unchanged Profile.\n *\n * @deprecated New authentication links require the owner-aware,\n * transactional provisioning APIs. This compatibility helper may refresh a\n * legacy Profile type, but refuses to create or rebind authority.\n */\n async linkToProfile(\n profile: Profile,\n oidcData: {\n provider: string;\n issuer: string;\n subject: string;\n email?: string;\n },\n ): Promise<OidcIdentity> {\n return OidcIdentity.findOrCreate(profile, oidcData, this.options);\n }\n\n /**\n * Unlink an OIDC identity from a profile\n */\n async unlinkFromProfile(\n profileId: string,\n issuer: string,\n subject: string,\n ): Promise<boolean> {\n const identity = await this.findOne({\n where: { profileId, issuer, subject },\n });\n\n if (identity) {\n await identity.delete();\n return true;\n }\n return false;\n }\n}\n"],"mappings":";;;;;;;;AASO,IAAM,6BAAN,cAAyC,MAAM;CACpD,YACW,QACA,SACT;EACA,MAAM,6DAA6D;EAH1D,KAAA,SAAA;EACA,KAAA,UAAA;EAGT,KAAK,OAAO;CACd;CALW;CACA;AAKb;AAEO,IAAM,yBAAN,cAAqC,eAA6B;CACvE,OAAgB,aAAa;;;;CAK7B,MAAM,cAAc,WAA4C;EAC9D,OAAO,MAAM,KAAK,KAAK,EACrB,OAAO,EAAE,UAAU,EACrB,CAAC;CACH;;;;CAKA,MAAM,cACJ,QACA,SAC8B;EAC9B,MAAM,UAAU,MAAM,KAAK,KAAK;GAC9B,OAAO;IAAE;IAAQ;GAAQ;GACzB,OAAO;EACT,CAAC;EACD,IAAI,QAAQ,SAAS,GACnB,MAAM,IAAI,2BAA2B,QAAQ,OAAO;EAEtD,OAAO,QAAQ,MAAM;CACvB;;;;CAKA,MAAM,eAAe,UAA2C;EAC9D,OAAO,MAAM,KAAK,KAAK,EACrB,OAAO,EAAE,SAAS,EACpB,CAAC;CACH;;;;;;;;CASA,MAAM,cACJ,SACA,UAMuB;EACvB,OAAO,aAAa,aAAa,SAAS,UAAU,KAAK,OAAO;CAClE;;;;CAKA,MAAM,kBACJ,WACA,QACA,SACkB;EAClB,MAAM,WAAW,MAAM,KAAK,QAAQ,EAClC,OAAO;GAAE;GAAW;GAAQ;EAAQ,EACtC,CAAC;EAED,IAAI,UAAU;GACZ,MAAM,SAAS,OAAO;GACtB,OAAO;EACT;EACA,OAAO;CACT;AACF"}
@@ -1,4 +1,4 @@
1
- import { y as __exportAll } from "./NostrIdentity-DF_a_WZk.js";
1
+ import { y as __exportAll } from "./NostrIdentity-CgdM4ng0.js";
2
2
  import { SmrtJunction, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
3
3
  import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
4
4
  import { addOwnedAssetFromCollection, getOwnedAssetsFromCollection, removeOwnedAssetFromCollection } from "@happyvertical/smrt-assets";
@@ -66,7 +66,7 @@ var ProfileAssetCollection = class extends SmrtJunction {
66
66
  profileCollectionPromise = null;
67
67
  async getProfileCollection() {
68
68
  if (!this.profileCollectionPromise) {
69
- const { ProfileCollection } = await import("./ProfileCollection-DdJ3W4GG.js").then((n) => n.r);
69
+ const { ProfileCollection } = await import("./ProfileCollection-BsKhR5Dp.js").then((n) => n.r);
70
70
  this.profileCollectionPromise = ProfileCollection.create({ db: this.db });
71
71
  }
72
72
  return this.profileCollectionPromise;
@@ -90,4 +90,4 @@ ProfileAssetCollection = __decorateClass([smrt({
90
90
  //#endregion
91
91
  export { ProfileAssetCollection_exports as n, ProfileAsset as r, ProfileAssetCollection as t };
92
92
 
93
- //# sourceMappingURL=ProfileAssetCollection-FhW8q7_1.js.map
93
+ //# sourceMappingURL=ProfileAssetCollection-A_PpEaDq.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileAssetCollection-FhW8q7_1.js","names":[],"sources":["../../src/models/ProfileAsset.ts","../../src/collections/ProfileAssetCollection.ts"],"sourcesContent":["import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ProfileAssetOptions extends SmrtObjectOptions {\n profileId?: string;\n assetId?: string;\n relationship?: string;\n sortOrder?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'profile_assets',\n conflictColumns: ['profile_id', 'asset_id', 'relationship'],\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAsset extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Profile', { required: true })\n profileId = '';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset', { required: true })\n assetId = '';\n\n @field({ required: true })\n relationship = 'attachment';\n\n @field()\n sortOrder = 0;\n\n constructor(options: ProfileAssetOptions = {}) {\n super(options);\n if (options.profileId) this.profileId = options.profileId;\n if (options.assetId) this.assetId = options.assetId;\n if (options.relationship) this.relationship = options.relationship;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n}\n","import type { Asset } from '@happyvertical/smrt-assets';\nimport {\n addOwnedAssetFromCollection,\n getOwnedAssetsFromCollection,\n removeOwnedAssetFromCollection,\n} from '@happyvertical/smrt-assets';\nimport type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ProfileAsset } from '../models/ProfileAsset';\nimport type { ProfileCollection } from './ProfileCollection';\n\nexport interface ProfileAssetCollectionOptions extends SmrtCollectionOptions {}\n\n@smrt({\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAssetCollection extends SmrtJunction<ProfileAsset> {\n static readonly _itemClass = ProfileAsset;\n protected leftField = 'profileId';\n protected rightField = 'assetId';\n\n private profileCollectionPromise: Promise<ProfileCollection> | null = null;\n\n private async getProfileCollection(): Promise<ProfileCollection> {\n if (!this.profileCollectionPromise) {\n const { ProfileCollection } = await import('./ProfileCollection');\n this.profileCollectionPromise = ProfileCollection.create({ db: this.db });\n }\n\n return this.profileCollectionPromise;\n }\n\n async getAssets(profileId: string, relationship?: string): Promise<Asset[]> {\n return getOwnedAssetsFromCollection(\n await this.getProfileCollection(),\n profileId,\n relationship,\n );\n }\n\n async addAsset(\n profileId: string,\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n await addOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n asset,\n relationship,\n sortOrder,\n );\n }\n\n async removeAsset(\n profileId: string,\n assetId: string,\n relationship?: string,\n ): Promise<void> {\n await removeOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n assetId,\n relationship,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA0BO,IAAM,eAAN,cAA2B,WAAW;CAE3C,WAA0B;CAG1B,YAAY;CAGZ,UAAU;CAGV,eAAe;CAGf,YAAY;CAEZ,YAAY,UAA+B,CAAC,GAAG;EAC7C,MAAM,OAAO;EACb,IAAI,QAAQ,WAAW,KAAK,YAAY,QAAQ;EAChD,IAAI,QAAQ,SAAS,KAAK,UAAU,QAAQ;EAC5C,IAAI,QAAQ,cAAc,KAAK,eAAe,QAAQ;EACtD,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;CAC9D;AACF;AAtBE,kBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GADjB,aAEX,WAAA,YAAA,CAAA;AAGA,kBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAJ9B,aAKX,WAAA,aAAA,CAAA;AAGA,kBAAA,CADC,gBAAgB,oCAAoC,EAAE,UAAU,KAAK,CAAC,CAAA,GAP5D,aAQX,WAAA,WAAA,CAAA;AAGA,kBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GAVd,aAWX,WAAA,gBAAA,CAAA;AAGA,kBAAA,CADC,MAAM,CAAA,GAbI,aAcX,WAAA,aAAA,CAAA;AAdW,eAAN,kBAAA,CARN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,WAAW;CACX,iBAAiB;EAAC;EAAc;EAAY;CAAc;CAC1D,KAAK;CACL,KAAK;CACL,KAAK;AACP,CAAC,CAAA,GACY,YAAA;;;;;;;;;;;;;;;;;;;ACRN,IAAM,yBAAN,cAAqC,aAA2B;CAE3D,YAAY;CACZ,aAAa;CAEf,2BAA8D;CAEtE,MAAc,uBAAmD;EAC/D,IAAI,CAAC,KAAK,0BAA0B;GAClC,MAAM,EAAE,sBAAsB,MAAM,OAAO,kCAAA,CAAA,MAAA,MAAA,EAAA,CAAA;GAC3C,KAAK,2BAA2B,kBAAkB,OAAO,EAAE,IAAI,KAAK,GAAG,CAAC;EAC1E;EAEA,OAAO,KAAK;CACd;CAEA,MAAM,UAAU,WAAmB,cAAyC;EAC1E,OAAO,6BACL,MAAM,KAAK,qBAAqB,GAChC,WACA,YACF;CACF;CAEA,MAAM,SACJ,WACA,OACA,eAAe,cACf,YAAY,GACG;EACf,MAAM,4BACJ,MAAM,KAAK,qBAAqB,GAChC,WACA,WACA,OACA,cACA,SACF;CACF;CAEA,MAAM,YACJ,WACA,SACA,cACe;EACf,MAAM,+BACJ,MAAM,KAAK,qBAAqB,GAChC,WACA,WACA,SACA,YACF;CACF;AACF;AApDE,cADW,wBACK,cAAa,YAAA;AADlB,yBAAN,gBAAA,CALN,KAAK;CACJ,KAAK;CACL,KAAK;CACL,KAAK;AACP,CAAC,CAAA,GACY,sBAAA"}
1
+ {"version":3,"file":"ProfileAssetCollection-A_PpEaDq.js","names":[],"sources":["../../src/models/ProfileAsset.ts","../../src/collections/ProfileAssetCollection.ts"],"sourcesContent":["import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ProfileAssetOptions extends SmrtObjectOptions {\n profileId?: string;\n assetId?: string;\n relationship?: string;\n sortOrder?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'profile_assets',\n conflictColumns: ['profile_id', 'asset_id', 'relationship'],\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAsset extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Profile', { required: true })\n profileId = '';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset', { required: true })\n assetId = '';\n\n @field({ required: true })\n relationship = 'attachment';\n\n @field()\n sortOrder = 0;\n\n constructor(options: ProfileAssetOptions = {}) {\n super(options);\n if (options.profileId) this.profileId = options.profileId;\n if (options.assetId) this.assetId = options.assetId;\n if (options.relationship) this.relationship = options.relationship;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n}\n","import type { Asset } from '@happyvertical/smrt-assets';\nimport {\n addOwnedAssetFromCollection,\n getOwnedAssetsFromCollection,\n removeOwnedAssetFromCollection,\n} from '@happyvertical/smrt-assets';\nimport type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ProfileAsset } from '../models/ProfileAsset';\nimport type { ProfileCollection } from './ProfileCollection';\n\nexport interface ProfileAssetCollectionOptions extends SmrtCollectionOptions {}\n\n@smrt({\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAssetCollection extends SmrtJunction<ProfileAsset> {\n static readonly _itemClass = ProfileAsset;\n protected leftField = 'profileId';\n protected rightField = 'assetId';\n\n private profileCollectionPromise: Promise<ProfileCollection> | null = null;\n\n private async getProfileCollection(): Promise<ProfileCollection> {\n if (!this.profileCollectionPromise) {\n const { ProfileCollection } = await import('./ProfileCollection');\n this.profileCollectionPromise = ProfileCollection.create({ db: this.db });\n }\n\n return this.profileCollectionPromise;\n }\n\n async getAssets(profileId: string, relationship?: string): Promise<Asset[]> {\n return getOwnedAssetsFromCollection(\n await this.getProfileCollection(),\n profileId,\n relationship,\n );\n }\n\n async addAsset(\n profileId: string,\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n await addOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n asset,\n relationship,\n sortOrder,\n );\n }\n\n async removeAsset(\n profileId: string,\n assetId: string,\n relationship?: string,\n ): Promise<void> {\n await removeOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n assetId,\n relationship,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA0BO,IAAM,eAAN,cAA2B,WAAW;CAE3C,WAA0B;CAG1B,YAAY;CAGZ,UAAU;CAGV,eAAe;CAGf,YAAY;CAEZ,YAAY,UAA+B,CAAC,GAAG;EAC7C,MAAM,OAAO;EACb,IAAI,QAAQ,WAAW,KAAK,YAAY,QAAQ;EAChD,IAAI,QAAQ,SAAS,KAAK,UAAU,QAAQ;EAC5C,IAAI,QAAQ,cAAc,KAAK,eAAe,QAAQ;EACtD,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;CAC9D;AACF;AAtBE,kBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GADjB,aAEX,WAAA,YAAA,CAAA;AAGA,kBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAJ9B,aAKX,WAAA,aAAA,CAAA;AAGA,kBAAA,CADC,gBAAgB,oCAAoC,EAAE,UAAU,KAAK,CAAC,CAAA,GAP5D,aAQX,WAAA,WAAA,CAAA;AAGA,kBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GAVd,aAWX,WAAA,gBAAA,CAAA;AAGA,kBAAA,CADC,MAAM,CAAA,GAbI,aAcX,WAAA,aAAA,CAAA;AAdW,eAAN,kBAAA,CARN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,WAAW;CACX,iBAAiB;EAAC;EAAc;EAAY;CAAc;CAC1D,KAAK;CACL,KAAK;CACL,KAAK;AACP,CAAC,CAAA,GACY,YAAA;;;;;;;;;;;;;;;;;;;ACRN,IAAM,yBAAN,cAAqC,aAA2B;CAE3D,YAAY;CACZ,aAAa;CAEf,2BAA8D;CAEtE,MAAc,uBAAmD;EAC/D,IAAI,CAAC,KAAK,0BAA0B;GAClC,MAAM,EAAE,sBAAsB,MAAM,OAAO,kCAAA,CAAA,MAAA,MAAA,EAAA,CAAA;GAC3C,KAAK,2BAA2B,kBAAkB,OAAO,EAAE,IAAI,KAAK,GAAG,CAAC;EAC1E;EAEA,OAAO,KAAK;CACd;CAEA,MAAM,UAAU,WAAmB,cAAyC;EAC1E,OAAO,6BACL,MAAM,KAAK,qBAAqB,GAChC,WACA,YACF;CACF;CAEA,MAAM,SACJ,WACA,OACA,eAAe,cACf,YAAY,GACG;EACf,MAAM,4BACJ,MAAM,KAAK,qBAAqB,GAChC,WACA,WACA,OACA,cACA,SACF;CACF;CAEA,MAAM,YACJ,WACA,SACA,cACe;EACf,MAAM,+BACJ,MAAM,KAAK,qBAAqB,GAChC,WACA,WACA,SACA,YACF;CACF;AACF;AApDE,cADW,wBACK,cAAa,YAAA;AADlB,yBAAN,gBAAA,CALN,KAAK;CACJ,KAAK;CACL,KAAK;CACL,KAAK;AACP,CAAC,CAAA,GACY,sBAAA"}
@@ -1,5 +1,5 @@
1
- import { y as __exportAll } from "./NostrIdentity-DF_a_WZk.js";
2
- import { SmrtCollection, SmrtObject, ValidationError, field, foreignKey, oneToMany, smrt } from "@happyvertical/smrt-core";
1
+ import { y as __exportAll } from "./NostrIdentity-CgdM4ng0.js";
2
+ import { SmrtCollection, SmrtObject, ValidationError, field, foreignKey, isAbortedTransactionError, oneToMany, smrt } from "@happyvertical/smrt-core";
3
3
  import { definePrompt, resolvePrompt } from "@happyvertical/smrt-prompts";
4
4
  import { TenantScoped, queryGlobal, queryWithGlobals, tenantId, withSystemContext } from "@happyvertical/smrt-tenancy";
5
5
  import { BackfillTableUnavailableError, BackfillTracker } from "@happyvertical/smrt-core/migrations";
@@ -68,8 +68,8 @@ var SavepointUnavailableError = class extends Error {
68
68
  };
69
69
  async function coordinateOidcProvisioning(options) {
70
70
  const rootBackfillTableReady = typeof options.db.beginTransaction === "function";
71
- if (rootBackfillTableReady) await new BackfillTracker({ db: options.db }).initialize();
72
71
  return withProvisioningLocks(options.db, options.lockKeys, async () => {
72
+ if (rootBackfillTableReady) await new BackfillTracker({ db: options.db }).initialize();
73
73
  const result = await retryProvisioning(options, () => withProvisioningTransaction(options.db, (tx) => {
74
74
  if (rootBackfillTableReady) BackfillTracker.inheritInitialization(tx, options.db);
75
75
  else BackfillTracker.requireExistingTable(tx);
@@ -84,14 +84,7 @@ async function withProvisioningLocks(db, lockKeys, callback) {
84
84
  return acquire(0);
85
85
  }
86
86
  function isOidcAbortedTransactionError(error) {
87
- const seen = /* @__PURE__ */ new Set();
88
- let current = error;
89
- while (current instanceof Error && !seen.has(current)) {
90
- seen.add(current);
91
- if (/current transaction is aborted|transaction.*aborted/iu.test(current.message)) return true;
92
- current = current.cause;
93
- }
94
- return false;
87
+ return isAbortedTransactionError(error);
95
88
  }
96
89
  function testRaceMessagePattern(pattern, message) {
97
90
  pattern.lastIndex = 0;
@@ -455,8 +448,8 @@ var Profile = class extends SmrtObject {
455
448
  * @param value - The value to set
456
449
  */
457
450
  async addMetadata(metafieldSlug, value) {
458
- const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-CACMY1hl.js").then((n) => n.n);
459
- const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-loKVv_pj.js").then((n) => n.n);
451
+ const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-CM374Dbh.js").then((n) => n.n);
452
+ const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-Ceq-QV-1.js").then((n) => n.n);
460
453
  const metafield = await (await ProfileMetafieldCollection.create(this.options)).getBySlug(metafieldSlug);
461
454
  if (!metafield) throw new Error(`Metafield '${metafieldSlug}' not found`);
462
455
  await metafield.validateValue(value);
@@ -487,7 +480,7 @@ var Profile = class extends SmrtObject {
487
480
  * @returns Object with metafield slugs as keys
488
481
  */
489
482
  async getMetadata() {
490
- const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-loKVv_pj.js").then((n) => n.n);
483
+ const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-Ceq-QV-1.js").then((n) => n.n);
491
484
  return await (await ProfileMetadataCollection.create(this.options)).getMetadataObject(this.id);
492
485
  }
493
486
  /**
@@ -504,8 +497,8 @@ var Profile = class extends SmrtObject {
504
497
  * @param metafieldSlug - The slug of the metafield to remove
505
498
  */
506
499
  async removeMetadata(metafieldSlug) {
507
- const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-CACMY1hl.js").then((n) => n.n);
508
- const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-loKVv_pj.js").then((n) => n.n);
500
+ const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-CM374Dbh.js").then((n) => n.n);
501
+ const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-Ceq-QV-1.js").then((n) => n.n);
509
502
  const metafield = await (await ProfileMetafieldCollection.create(this.options)).getBySlug(metafieldSlug);
510
503
  if (!metafield) throw new Error(`Metafield '${metafieldSlug}' not found`);
511
504
  const existing = await (await ProfileMetadataCollection.create(this.options)).list({
@@ -518,7 +511,7 @@ var Profile = class extends SmrtObject {
518
511
  if (existing.length > 0) await existing[0].delete();
519
512
  }
520
513
  async getProfileAssetCollection() {
521
- const { ProfileAssetCollection } = await import("./ProfileAssetCollection-FhW8q7_1.js").then((n) => n.n);
514
+ const { ProfileAssetCollection } = await import("./ProfileAssetCollection-A_PpEaDq.js").then((n) => n.n);
522
515
  return ProfileAssetCollection.create({ db: this.db });
523
516
  }
524
517
  async getAssets(relationship) {
@@ -548,9 +541,9 @@ var Profile = class extends SmrtObject {
548
541
  * @param contextProfile - Optional context profile for tertiary relationships
549
542
  */
550
543
  async addRelationship(toProfile, relationshipSlug, contextProfile) {
551
- const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-Bh4xJ4-I.js").then((n) => n.n);
552
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-CzQKfvMy.js").then((n) => n.n);
553
- const { ProfileRelationshipType } = await import("./ProfileRelationshipType-BjoaCt-u.js").then((n) => n.n);
544
+ const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CtoeCpp_.js").then((n) => n.n);
545
+ const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-DuPcpzp1.js").then((n) => n.n);
546
+ const { ProfileRelationshipType } = await import("./ProfileRelationshipType-CZm2X1qY.js").then((n) => n.n);
554
547
  const relationshipType = await (await ProfileRelationshipTypeCollection.create(this.options)).getBySlug(relationshipSlug);
555
548
  if (!relationshipType) throw new Error(`Relationship type '${relationshipSlug}' not found`);
556
549
  const relationshipCollection = await ProfileRelationshipCollection.create(this.options);
@@ -574,8 +567,8 @@ var Profile = class extends SmrtObject {
574
567
  * @returns Array of ProfileRelationship instances
575
568
  */
576
569
  async getRelationships(options) {
577
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-CzQKfvMy.js").then((n) => n.n);
578
- const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-Bh4xJ4-I.js").then((n) => n.n);
570
+ const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-DuPcpzp1.js").then((n) => n.n);
571
+ const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CtoeCpp_.js").then((n) => n.n);
579
572
  const relationshipCollection = await ProfileRelationshipCollection.create(this.options);
580
573
  const direction = options?.direction || "all";
581
574
  let typeId;
@@ -618,8 +611,8 @@ var Profile = class extends SmrtObject {
618
611
  * @param relationshipSlug - The type of relationship to remove
619
612
  */
620
613
  async removeRelationship(toProfile, relationshipSlug) {
621
- const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-Bh4xJ4-I.js").then((n) => n.n);
622
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-CzQKfvMy.js").then((n) => n.n);
614
+ const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CtoeCpp_.js").then((n) => n.n);
615
+ const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-DuPcpzp1.js").then((n) => n.n);
623
616
  const relationshipType = await (await ProfileRelationshipTypeCollection.create(this.options)).getBySlug(relationshipSlug);
624
617
  if (!relationshipType) throw new Error(`Relationship type '${relationshipSlug}' not found`);
625
618
  const relationshipCollection = await ProfileRelationshipCollection.create(this.options);
@@ -712,7 +705,7 @@ var Profile = class extends SmrtObject {
712
705
  * @returns Array of API keys
713
706
  */
714
707
  async getApiKeys() {
715
- const { ApiKeyCollection } = await import("./ApiKeyCollection-CrTjdMz8.js").then((n) => n.n);
708
+ const { ApiKeyCollection } = await import("./ApiKeyCollection-C6p7XgTz.js").then((n) => n.n);
716
709
  return await (await ApiKeyCollection.create(this.options)).findByProfile(this.id);
717
710
  }
718
711
  /**
@@ -721,7 +714,7 @@ var Profile = class extends SmrtObject {
721
714
  * @returns Array of active API keys
722
715
  */
723
716
  async getActiveApiKeys() {
724
- const { ApiKeyCollection } = await import("./ApiKeyCollection-CrTjdMz8.js").then((n) => n.n);
717
+ const { ApiKeyCollection } = await import("./ApiKeyCollection-C6p7XgTz.js").then((n) => n.n);
725
718
  return await (await ApiKeyCollection.create(this.options)).findActiveByProfile(this.id);
726
719
  }
727
720
  /**
@@ -731,7 +724,7 @@ var Profile = class extends SmrtObject {
731
724
  * @returns The generated key (plaintext) and ApiKey record
732
725
  */
733
726
  async generateApiKey(options) {
734
- const { ApiKey } = await import("./ApiKey-Br9NGBnr.js").then((n) => n.n);
727
+ const { ApiKey } = await import("./ApiKey-CMm509C4.js").then((n) => n.n);
735
728
  return await ApiKey.generate(this, {
736
729
  ...options,
737
730
  db: this.options?.db
@@ -743,7 +736,7 @@ var Profile = class extends SmrtObject {
743
736
  * @returns Array of OIDC identity records
744
737
  */
745
738
  async getOidcIdentities() {
746
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-BLxSaqJT.js").then((n) => n.r);
739
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-eSM4gzHL.js").then((n) => n.r);
747
740
  return await (await OidcIdentityCollection.create(this.options)).findByProfile(this.id);
748
741
  }
749
742
  /**
@@ -756,7 +749,7 @@ var Profile = class extends SmrtObject {
756
749
  * type, but refuses to create or rebind authority.
757
750
  */
758
751
  async linkOidcIdentity(oidcData) {
759
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-BLxSaqJT.js").then((n) => n.r);
752
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-eSM4gzHL.js").then((n) => n.r);
760
753
  return await (await OidcIdentityCollection.create(this.options)).linkToProfile(this, oidcData);
761
754
  }
762
755
  /**
@@ -765,7 +758,7 @@ var Profile = class extends SmrtObject {
765
758
  * @returns Array of Nostr identity records
766
759
  */
767
760
  async getNostrIdentities() {
768
- const { NostrIdentityCollection } = await import("./NostrIdentityCollection-BRYUgt47.js").then((n) => n.n);
761
+ const { NostrIdentityCollection } = await import("./NostrIdentityCollection-BnHZOsUI.js").then((n) => n.n);
769
762
  return await (await NostrIdentityCollection.create(this.options)).findByProfile(this.id);
770
763
  }
771
764
  /**
@@ -775,7 +768,7 @@ var Profile = class extends SmrtObject {
775
768
  * @returns The linked Nostr identity record
776
769
  */
777
770
  async linkNostrIdentity(nostrData) {
778
- const { NostrIdentityCollection } = await import("./NostrIdentityCollection-BRYUgt47.js").then((n) => n.n);
771
+ const { NostrIdentityCollection } = await import("./NostrIdentityCollection-BnHZOsUI.js").then((n) => n.n);
779
772
  return await (await NostrIdentityCollection.create(this.options)).linkToProfile(this, nostrData);
780
773
  }
781
774
  /**
@@ -785,7 +778,7 @@ var Profile = class extends SmrtObject {
785
778
  * @returns Array of audit log entries
786
779
  */
787
780
  async getAuditLogs(limit = 50) {
788
- const { AuditLogCollection } = await import("./AuditLogCollection-BBIEI6BD.js").then((n) => n.n);
781
+ const { AuditLogCollection } = await import("./AuditLogCollection-lJfGFdIQ.js").then((n) => n.n);
789
782
  return await (await AuditLogCollection.create(this.options)).getRecentActivity(this.id, limit);
790
783
  }
791
784
  /**
@@ -795,7 +788,7 @@ var Profile = class extends SmrtObject {
795
788
  * @returns The created audit log entry
796
789
  */
797
790
  async recordAction(options) {
798
- const { AuditLogCollection } = await import("./AuditLogCollection-BBIEI6BD.js").then((n) => n.n);
791
+ const { AuditLogCollection } = await import("./AuditLogCollection-lJfGFdIQ.js").then((n) => n.n);
799
792
  return await (await AuditLogCollection.create(this.options)).record({
800
793
  profile: this,
801
794
  ...options
@@ -804,7 +797,6 @@ var Profile = class extends SmrtObject {
804
797
  };
805
798
  __decorateClass([tenantId({ nullable: true })], Profile.prototype, "tenantId", 2);
806
799
  __decorateClass([foreignKey("ProfileType", { required: true })], Profile.prototype, "typeId", 2);
807
- __decorateClass([field({ unique: true })], Profile.prototype, "email", 2);
808
800
  __decorateClass([field({
809
801
  type: "text",
810
802
  nullable: true,
@@ -1158,4 +1150,4 @@ function readRequiredString(row, key) {
1158
1150
  //#endregion
1159
1151
  export { smrtProfilesGenerateBioPrompt as _, Profile as a, OidcProfileEmailReservation as c, coordinateOidcProvisioning as d, isOidcAbortedTransactionError as f, promptMessageOptions as g, normalizeIdentityEmail as h, OidcProfileEmailReservationCollection as i, PROFILE_EMAIL_KEY_BACKFILL_NAME as l, saveOidcRaceArbiter as m, ProfileCollection as n, ProfileType as o, isOidcProvisioningRaceConflict as p, ProfileCollection_exports as r, ProfileType_exports as s, CanonicalPersonProfileError as t, backfillProfileEmailKeys as u };
1160
1152
 
1161
- //# sourceMappingURL=ProfileCollection-DdJ3W4GG.js.map
1153
+ //# sourceMappingURL=ProfileCollection-BsKhR5Dp.js.map