@happyvertical/smrt-profiles 0.55.1 → 0.55.2

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 (30) hide show
  1. package/README.md +1 -1
  2. package/dist/chunks/{OidcIdentity-BjRu3n1g.js → OidcIdentity-BUblgQLs.js} +3 -3
  3. package/dist/chunks/{OidcIdentity-BjRu3n1g.js.map → OidcIdentity-BUblgQLs.js.map} +1 -1
  4. package/dist/chunks/{OidcIdentityCollection-B4jYh36_.js → OidcIdentityCollection-ClOyaHeF.js} +2 -2
  5. package/dist/chunks/{OidcIdentityCollection-B4jYh36_.js.map → OidcIdentityCollection-ClOyaHeF.js.map} +1 -1
  6. package/dist/chunks/{ProfileAssetCollection-HeMtjBc0.js → ProfileAssetCollection-CRMcjLJ-.js} +2 -2
  7. package/dist/chunks/{ProfileAssetCollection-HeMtjBc0.js.map → ProfileAssetCollection-CRMcjLJ-.js.map} +1 -1
  8. package/dist/chunks/{ProfileCollection-Bt6IJK49.js → ProfileCollection-C4INKh7Y.js} +10 -5
  9. package/dist/chunks/ProfileCollection-C4INKh7Y.js.map +1 -0
  10. package/dist/chunks/{ProfileLinkCollection-u1hhzKTm.js → ProfileLinkCollection-DFfZRsgv.js} +2 -2
  11. package/dist/chunks/{ProfileLinkCollection-u1hhzKTm.js.map → ProfileLinkCollection-DFfZRsgv.js.map} +1 -1
  12. package/dist/chunks/ProfileTypeCollection-B7kwi1mU.js +100 -0
  13. package/dist/chunks/ProfileTypeCollection-B7kwi1mU.js.map +1 -0
  14. package/dist/chunks/oidcProvisioningPrimitives-DNP9EZlU.js +88 -0
  15. package/dist/chunks/oidcProvisioningPrimitives-DNP9EZlU.js.map +1 -0
  16. package/dist/chunks/{resolveIdentity-CvGDegU6.js → resolveIdentity-CkyqvctR.js} +14 -14
  17. package/dist/chunks/{resolveIdentity-CvGDegU6.js.map → resolveIdentity-CkyqvctR.js.map} +1 -1
  18. package/dist/collections/ProfileTypeCollection.d.ts +10 -0
  19. package/dist/collections/ProfileTypeCollection.d.ts.map +1 -1
  20. package/dist/index.js +12 -11
  21. package/dist/index.js.map +1 -1
  22. package/dist/internal/oidc-provisioning.js +2 -2
  23. package/dist/manifest.json +37 -2
  24. package/dist/models/Profile.d.ts.map +1 -1
  25. package/dist/smrt-knowledge.json +62 -3
  26. package/dist/utils.js +1 -1
  27. package/package.json +11 -11
  28. package/dist/chunks/ProfileCollection-Bt6IJK49.js.map +0 -1
  29. package/dist/chunks/oidcProvisioningPrimitives-CYood-2M.js +0 -166
  30. package/dist/chunks/oidcProvisioningPrimitives-CYood-2M.js.map +0 -1
@@ -1,166 +0,0 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
2
- import { a as Profile, f as saveOidcRaceArbiter, m as ProfileType, n as ProfileCollection } from "./ProfileCollection-Bt6IJK49.js";
3
- import { t as OidcIdentity } from "./OidcIdentity-BjRu3n1g.js";
4
- import { SmrtCollection, smrt } from "@happyvertical/smrt-core";
5
- import { isSystemContext } from "@happyvertical/smrt-tenancy";
6
- //#region src/collections/ProfileTypeCollection.ts
7
- var ProfileTypeCollection_exports = /* @__PURE__ */ __exportAll({ ProfileTypeCollection: () => ProfileTypeCollection });
8
- function isPostgresUrl(url) {
9
- return /^postgres(?:ql)?:/iu.test(url ?? "");
10
- }
11
- var ProfileTypeCollection = class extends SmrtCollection {
12
- static _itemClass = ProfileType;
13
- /**
14
- * Get profile type by slug
15
- *
16
- * @param slug - The slug to search for
17
- * @returns ProfileType instance or null
18
- */
19
- async getBySlug(slug) {
20
- return await this.get({ slug });
21
- }
22
- /**
23
- * Get or create a profile type by slug
24
- *
25
- * @param slug - The slug to search for
26
- * @param defaults - Default values if creating
27
- * @returns ProfileType instance
28
- */
29
- async getOrCreateBySlug(slug, defaults) {
30
- const existing = await this.getBySlug(slug);
31
- if (existing) return existing;
32
- const profileType = await this.create({
33
- slug,
34
- ...defaults
35
- });
36
- await profileType.save();
37
- return profileType;
38
- }
39
- /**
40
- * Atomically create or load a global ProfileType from trusted system code.
41
- *
42
- * This intentionally bypasses tenant auto-population and therefore refuses
43
- * to run outside an explicit `withSystemContext()` boundary.
44
- */
45
- async getOrCreateGlobalBySlug(slug, defaults) {
46
- if (!isSystemContext()) throw new Error("Global ProfileType creation requires an explicit system context.");
47
- const existing = await this.loadGlobalBySlug(slug);
48
- if (existing) return existing;
49
- const insertIfAbsent = async (db) => {
50
- if (isPostgresUrl(db.url)) await db.query("SELECT pg_advisory_xact_lock(hashtext(?), hashtext(?))", "@happyvertical/smrt-profiles:profile_types:global", slug);
51
- await db.query(`INSERT INTO profile_types
52
- (id, slug, context, _meta_type, tenant_id, name, description)
53
- SELECT ?, ?, '', '@happyvertical/smrt-profiles:ProfileType', NULL, ?, ?
54
- WHERE NOT EXISTS (
55
- SELECT 1 FROM profile_types
56
- WHERE slug = ?
57
- AND context = ''
58
- AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'
59
- AND tenant_id IS NULL
60
- )`, crypto.randomUUID(), slug, defaults.name, defaults.description ?? null, slug);
61
- };
62
- const isTransactionBound = typeof this.db.commit === "function";
63
- if (isPostgresUrl(this.db.url) && !isTransactionBound && typeof this.db.transaction === "function") await this.db.transaction((tx) => insertIfAbsent(tx));
64
- else await insertIfAbsent(this.db);
65
- const profileType = await this.loadGlobalBySlug(slug);
66
- if (!profileType) throw new Error(`Global ProfileType '${slug}' could not be created or loaded.`);
67
- return profileType;
68
- }
69
- async loadGlobalBySlug(slug) {
70
- const id = (await this.db.query(`SELECT CAST(id AS VARCHAR) AS id
71
- FROM profile_types
72
- WHERE slug = ?
73
- AND context = ''
74
- AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'
75
- AND tenant_id IS NULL
76
- LIMIT 1`, slug)).rows[0]?.id;
77
- if (typeof id !== "string") return null;
78
- const profileType = await this.get({ id });
79
- if (profileType) profileType.id = id;
80
- return profileType;
81
- }
82
- };
83
- //#endregion
84
- //#region src/models/ProfileTypes.ts
85
- var ProfileTypes_exports = /* @__PURE__ */ __exportAll({
86
- Bot: () => Bot,
87
- Organization: () => Organization,
88
- Person: () => Person
89
- });
90
- var __defProp = Object.defineProperty;
91
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
92
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
93
- enumerable: true,
94
- configurable: true,
95
- writable: true,
96
- value
97
- }) : obj[key] = value;
98
- var __decorateClass = (decorators, target, key, kind) => {
99
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
100
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
101
- if (kind && result) __defProp(target, key, result);
102
- return result;
103
- };
104
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
105
- var Person = class extends Profile {
106
- constructor(options = {}) {
107
- super(options);
108
- }
109
- };
110
- __publicField(Person, "__smrtPackage__", "@happyvertical/smrt-profiles");
111
- Person = __decorateClass([smrt({ tableStrategy: "sti" })], Person);
112
- var Organization = class extends Profile {
113
- constructor(options = {}) {
114
- super(options);
115
- }
116
- };
117
- __publicField(Organization, "__smrtPackage__", "@happyvertical/smrt-profiles");
118
- Organization = __decorateClass([smrt({ tableStrategy: "sti" })], Organization);
119
- var Bot = class extends Profile {
120
- constructor(options = {}) {
121
- super(options);
122
- }
123
- };
124
- __publicField(Bot, "__smrtPackage__", "@happyvertical/smrt-profiles");
125
- Bot = __decorateClass([smrt({ tableStrategy: "sti" })], Bot);
126
- //#endregion
127
- //#region src/auth/oidcProvisioningPrimitives.ts
128
- async function createOidcProvisioningPerson(db, input) {
129
- const typeId = requireProvisioningId((await (await ProfileTypeCollection.create({ db })).getOrCreateGlobalBySlug("person", {
130
- name: "Person",
131
- description: "Individual person profile"
132
- })).id, "Person ProfileType");
133
- let profile = new Person({
134
- db,
135
- slug: `oidc-${crypto.randomUUID()}`,
136
- tenantId: null,
137
- typeId,
138
- email: input.email ?? "",
139
- name: input.name || input.preferredUsername || input.subject
140
- });
141
- await profile.initialize();
142
- await saveOidcRaceArbiter(() => profile.save());
143
- if (input.email) profile = await (await ProfileCollection.create({ db })).reserveCanonicalIdentityEmail(requireProvisioningId(profile.id, "Created Profile"), input.email);
144
- return profile;
145
- }
146
- async function insertOidcProvisioningIdentity(db, input) {
147
- const identity = new OidcIdentity({
148
- db,
149
- email: input.email ?? "",
150
- issuer: input.issuer,
151
- profileId: input.profileId,
152
- provider: input.provider,
153
- subject: input.subject
154
- });
155
- await identity.initialize();
156
- await saveOidcRaceArbiter(() => identity.save());
157
- return identity;
158
- }
159
- function requireProvisioningId(value, label) {
160
- if (typeof value !== "string" || !value) throw new Error(`${label} did not produce an id.`);
161
- return value;
162
- }
163
- //#endregion
164
- export { Person as a, ProfileTypeCollection_exports as c, Organization as i, insertOidcProvisioningIdentity as n, ProfileTypes_exports as o, Bot as r, ProfileTypeCollection as s, createOidcProvisioningPerson as t };
165
-
166
- //# sourceMappingURL=oidcProvisioningPrimitives-CYood-2M.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"oidcProvisioningPrimitives-CYood-2M.js","names":[],"sources":["../../src/collections/ProfileTypeCollection.ts","../../src/models/ProfileTypes.ts","../../src/auth/oidcProvisioningPrimitives.ts"],"sourcesContent":["/**\n * ProfileTypeCollection - Collection manager for ProfileType objects\n *\n * Provides querying for profile type lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { isSystemContext } from '@happyvertical/smrt-tenancy';\nimport { ProfileType } from '../models/ProfileType';\n\nfunction isPostgresUrl(url: string | undefined): boolean {\n return /^postgres(?:ql)?:/iu.test(url ?? '');\n}\n\nexport class ProfileTypeCollection extends SmrtCollection<ProfileType> {\n static readonly _itemClass = ProfileType;\n\n /**\n * Get profile type by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileType instance or null\n */\n async getBySlug(slug: string): Promise<ProfileType | null> {\n return await this.get({ slug });\n }\n\n /**\n * Get or create a profile type by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileType instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: { name: string; description?: string },\n ): Promise<ProfileType> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const profileType = await this.create({ slug, ...defaults });\n await profileType.save();\n return profileType;\n }\n\n /**\n * Atomically create or load a global ProfileType from trusted system code.\n *\n * This intentionally bypasses tenant auto-population and therefore refuses\n * to run outside an explicit `withSystemContext()` boundary.\n */\n async getOrCreateGlobalBySlug(\n slug: string,\n defaults: { name: string; description?: string },\n ): Promise<ProfileType> {\n if (!isSystemContext()) {\n throw new Error(\n 'Global ProfileType creation requires an explicit system context.',\n );\n }\n\n const existing = await this.loadGlobalBySlug(slug);\n if (existing) return existing;\n\n // A plain SMRT create is an upsert and may replace the winning row's id\n // when two first-login transactions race. Keep the canonical id stable by\n // using a cross-adapter insert-if-absent and then hydrating the winner.\n //\n // The table's unique key is `(tenant_id, slug, context, _meta_type)` since\n // smrt#2360, and a global row's NULL tenant never conflicts at the\n // database level (NULLs are distinct in a unique index), so a raw\n // `ON CONFLICT (…) DO NOTHING` can no longer arbitrate this race. Serialize\n // the global create per slug instead: PostgreSQL through a\n // transaction-scoped advisory lock (the arbiter the SDK's null-aware\n // upsert uses too); the embedded engines through the provisioning\n // coordinator's in-process lock plus their single-writer transactions.\n const insertIfAbsent = async (db: typeof this.db): Promise<void> => {\n if (isPostgresUrl(db.url)) {\n await db.query(\n 'SELECT pg_advisory_xact_lock(hashtext(?), hashtext(?))',\n '@happyvertical/smrt-profiles:profile_types:global',\n slug,\n );\n }\n await db.query(\n `INSERT INTO profile_types\n (id, slug, context, _meta_type, tenant_id, name, description)\n SELECT ?, ?, '', '@happyvertical/smrt-profiles:ProfileType', NULL, ?, ?\n WHERE NOT EXISTS (\n SELECT 1 FROM profile_types\n WHERE slug = ?\n AND context = ''\n AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'\n AND tenant_id IS NULL\n )`,\n crypto.randomUUID(),\n slug,\n defaults.name,\n defaults.description ?? null,\n slug,\n );\n };\n\n // A transaction-scoped advisory lock only spans both statements when they\n // run on one transaction. On PostgreSQL, any handle that is NOT already\n // transaction-bound may route each query to a different pooled connection\n // — a root adapter (`beginTransaction` present) and equally a view\n // wrapper (only `transaction()` present) — so open a transaction for the\n // pair on every such handle. A transaction-bound handle (fingerprint: it\n // carries `commit`) already keeps both statements on one client and must\n // not nest. Embedded engines run directly: a nested root transaction\n // would deadlock their single-writer adapters, and the provisioning\n // coordinator's in-process lock already serializes them.\n const isTransactionBound =\n typeof (this.db as { commit?: unknown }).commit === 'function';\n if (\n isPostgresUrl(this.db.url) &&\n !isTransactionBound &&\n typeof this.db.transaction === 'function'\n ) {\n await this.db.transaction((tx) => insertIfAbsent(tx));\n } else {\n await insertIfAbsent(this.db);\n }\n const profileType = await this.loadGlobalBySlug(slug);\n if (!profileType) {\n throw new Error(\n `Global ProfileType '${slug}' could not be created or loaded.`,\n );\n }\n return profileType;\n }\n\n private async loadGlobalBySlug(slug: string): Promise<ProfileType | null> {\n const result = await this.db.query(\n `SELECT CAST(id AS VARCHAR) AS id\n FROM profile_types\n WHERE slug = ?\n AND context = ''\n AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'\n AND tenant_id IS NULL\n LIMIT 1`,\n slug,\n );\n const id = result.rows[0]?.id;\n if (typeof id !== 'string') return null;\n const profileType = await this.get({ id });\n // @happyvertical/sql 0.88 exposes native DuckDB UUID result values as an\n // internal object. The cast above is the portable identity boundary for\n // this lookup; retain it on the hydrated object used by provisioning.\n if (profileType) profileType.id = id;\n return profileType;\n }\n}\n","/**\n * Profile subclasses for STI (Single Table Inheritance)\n *\n * These classes inherit from Profile and automatically use the shared\n * profiles table with _meta_type discriminator.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport { Profile, type ProfileOptions } from './Profile';\n\n/**\n * Person profile type\n *\n * Represents individual people/users.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Person extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Person-specific initialization can go here\n }\n}\n\n/**\n * Organization profile type\n *\n * Represents companies, groups, institutions, and other organizational entities.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Organization extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Organization-specific initialization can go here\n }\n}\n\n/**\n * Bot profile type\n *\n * Represents automated agents, bots, and AI entities.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Bot extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Bot-specific initialization can go here\n }\n}\n","import type { getDatabase } from '@happyvertical/sql';\nimport { ProfileCollection } from '../collections/ProfileCollection';\nimport { ProfileTypeCollection } from '../collections/ProfileTypeCollection';\nimport { OidcIdentity } from '../models/OidcIdentity';\nimport type { Profile } from '../models/Profile';\nimport { Person } from '../models/ProfileTypes';\nimport { saveOidcRaceArbiter } from './oidcProvisioningCoordinator';\n\ntype DatabaseInterface = Awaited<ReturnType<typeof getDatabase>>;\n\nexport interface OidcProvisioningPersonInput {\n email?: string;\n name?: string;\n preferredUsername?: string;\n subject: string;\n}\n\nexport interface OidcProvisioningIdentityInput {\n email?: string;\n issuer: string;\n profileId: string;\n provider: string;\n subject: string;\n}\n\n/** Create and reserve a fresh global Person inside the caller's transaction. */\nexport async function createOidcProvisioningPerson(\n db: DatabaseInterface,\n input: OidcProvisioningPersonInput,\n): Promise<Profile> {\n const typeCollection = await ProfileTypeCollection.create({ db });\n const personType = await typeCollection.getOrCreateGlobalBySlug('person', {\n name: 'Person',\n description: 'Individual person profile',\n });\n const typeId = requireProvisioningId(personType.id, 'Person ProfileType');\n let profile: Profile = new Person({\n db,\n // OIDC display names are not identity keys. A per-profile slug keeps\n // SMRT's natural-key upsert from replacing an unrelated Person.\n slug: `oidc-${crypto.randomUUID()}`,\n tenantId: null,\n typeId,\n email: input.email ?? '',\n name: input.name || input.preferredUsername || input.subject,\n });\n await profile.initialize();\n await saveOidcRaceArbiter(() => profile.save());\n\n if (input.email) {\n const profiles = await ProfileCollection.create({ db });\n profile = await profiles.reserveCanonicalIdentityEmail(\n requireProvisioningId(profile.id, 'Created Profile'),\n input.email,\n );\n }\n return profile;\n}\n\n/** Insert the identity after the caller proves Profile ownership. */\nexport async function insertOidcProvisioningIdentity(\n db: DatabaseInterface,\n input: OidcProvisioningIdentityInput,\n): Promise<OidcIdentity> {\n const identity = new OidcIdentity({\n db,\n email: input.email ?? '',\n issuer: input.issuer,\n profileId: input.profileId,\n provider: input.provider,\n subject: input.subject,\n });\n await identity.initialize();\n await saveOidcRaceArbiter(() => identity.save());\n return identity;\n}\n\nfunction requireProvisioningId(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value) {\n throw new Error(`${label} did not produce an id.`);\n }\n return value;\n}\n"],"mappings":"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"}