@happyvertical/smrt-profiles 0.51.32 → 0.51.34

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 (100) hide show
  1. package/dist/__smrt-register__.d.ts +2 -0
  2. package/dist/__smrt-register__.d.ts.map +1 -0
  3. package/dist/agent-profile.d.ts +71 -0
  4. package/dist/agent-profile.d.ts.map +1 -0
  5. package/dist/auth/index.d.ts +12 -0
  6. package/dist/auth/index.d.ts.map +1 -0
  7. package/dist/auth/magicLinkService.d.ts +79 -0
  8. package/dist/auth/magicLinkService.d.ts.map +1 -0
  9. package/dist/auth/nip05Handler.d.ts +73 -0
  10. package/dist/auth/nip05Handler.d.ts.map +1 -0
  11. package/dist/auth/normalizeIdentityEmail.d.ts +8 -0
  12. package/dist/auth/normalizeIdentityEmail.d.ts.map +1 -0
  13. package/dist/auth/nostrCrypto.d.ts +111 -0
  14. package/dist/auth/nostrCrypto.d.ts.map +1 -0
  15. package/dist/auth/oidcProvisioningCoordinator.d.ts +58 -0
  16. package/dist/auth/oidcProvisioningCoordinator.d.ts.map +1 -0
  17. package/dist/auth/oidcProvisioningPrimitives.d.ts +23 -0
  18. package/dist/auth/oidcProvisioningPrimitives.d.ts.map +1 -0
  19. package/dist/auth/resolveIdentity.d.ts +188 -0
  20. package/dist/auth/resolveIdentity.d.ts.map +1 -0
  21. package/dist/collections/ApiKeyCollection.d.ts +46 -0
  22. package/dist/collections/ApiKeyCollection.d.ts.map +1 -0
  23. package/dist/collections/AuditLogCollection.d.ts +50 -0
  24. package/dist/collections/AuditLogCollection.d.ts.map +1 -0
  25. package/dist/collections/MagicLinkTokenCollection.d.ts +58 -0
  26. package/dist/collections/MagicLinkTokenCollection.d.ts.map +1 -0
  27. package/dist/collections/NostrIdentityCollection.d.ts +66 -0
  28. package/dist/collections/NostrIdentityCollection.d.ts.map +1 -0
  29. package/dist/collections/OidcIdentityCollection.d.ts +45 -0
  30. package/dist/collections/OidcIdentityCollection.d.ts.map +1 -0
  31. package/dist/collections/OidcProfileEmailReservationCollection.d.ts +7 -0
  32. package/dist/collections/OidcProfileEmailReservationCollection.d.ts.map +1 -0
  33. package/dist/collections/ProfileAssetCollection.d.ts +17 -0
  34. package/dist/collections/ProfileAssetCollection.d.ts.map +1 -0
  35. package/dist/collections/ProfileCollection.d.ts +130 -0
  36. package/dist/collections/ProfileCollection.d.ts.map +1 -0
  37. package/dist/collections/ProfileMetadataCollection.d.ts +33 -0
  38. package/dist/collections/ProfileMetadataCollection.d.ts.map +1 -0
  39. package/dist/collections/ProfileMetafieldCollection.d.ts +31 -0
  40. package/dist/collections/ProfileMetafieldCollection.d.ts.map +1 -0
  41. package/dist/collections/ProfileRelationshipCollection.d.ts +44 -0
  42. package/dist/collections/ProfileRelationshipCollection.d.ts.map +1 -0
  43. package/dist/collections/ProfileRelationshipTermCollection.d.ts +32 -0
  44. package/dist/collections/ProfileRelationshipTermCollection.d.ts.map +1 -0
  45. package/dist/collections/ProfileRelationshipTypeCollection.d.ts +41 -0
  46. package/dist/collections/ProfileRelationshipTypeCollection.d.ts.map +1 -0
  47. package/dist/collections/ProfileTypeCollection.d.ts +40 -0
  48. package/dist/collections/ProfileTypeCollection.d.ts.map +1 -0
  49. package/dist/collections/index.d.ts +18 -0
  50. package/dist/collections/index.d.ts.map +1 -0
  51. package/dist/index.d.ts +55 -2059
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +1 -1
  54. package/dist/internal/oidc-provisioning.d.ts +14 -119
  55. package/dist/internal/oidc-provisioning.d.ts.map +1 -0
  56. package/dist/manifest.json +1 -1
  57. package/dist/migrations/backfillProfileEmailKeys.d.ts +16 -0
  58. package/dist/migrations/backfillProfileEmailKeys.d.ts.map +1 -0
  59. package/dist/models/ApiKey.d.ts +94 -0
  60. package/dist/models/ApiKey.d.ts.map +1 -0
  61. package/dist/models/AuditLog.d.ts +71 -0
  62. package/dist/models/AuditLog.d.ts.map +1 -0
  63. package/dist/models/MagicLinkToken.d.ts +104 -0
  64. package/dist/models/MagicLinkToken.d.ts.map +1 -0
  65. package/dist/models/NostrIdentity.d.ts +112 -0
  66. package/dist/models/NostrIdentity.d.ts.map +1 -0
  67. package/dist/models/OidcIdentity.d.ts +82 -0
  68. package/dist/models/OidcIdentity.d.ts.map +1 -0
  69. package/dist/models/OidcProfileEmailReservation.d.ts +12 -0
  70. package/dist/models/OidcProfileEmailReservation.d.ts.map +1 -0
  71. package/dist/models/Profile.d.ts +243 -0
  72. package/dist/models/Profile.d.ts.map +1 -0
  73. package/dist/models/ProfileAsset.d.ts +18 -0
  74. package/dist/models/ProfileAsset.d.ts.map +1 -0
  75. package/dist/models/ProfileMetadata.d.ts +33 -0
  76. package/dist/models/ProfileMetadata.d.ts.map +1 -0
  77. package/dist/models/ProfileMetafield.d.ts +62 -0
  78. package/dist/models/ProfileMetafield.d.ts.map +1 -0
  79. package/dist/models/ProfileRelationship.d.ts +56 -0
  80. package/dist/models/ProfileRelationship.d.ts.map +1 -0
  81. package/dist/models/ProfileRelationshipTerm.d.ts +37 -0
  82. package/dist/models/ProfileRelationshipTerm.d.ts.map +1 -0
  83. package/dist/models/ProfileRelationshipType.d.ts +59 -0
  84. package/dist/models/ProfileRelationshipType.d.ts.map +1 -0
  85. package/dist/models/ProfileType.d.ts +27 -0
  86. package/dist/models/ProfileType.d.ts.map +1 -0
  87. package/dist/models/ProfileTypes.d.ts +32 -0
  88. package/dist/models/ProfileTypes.d.ts.map +1 -0
  89. package/dist/models/index.d.ts +18 -0
  90. package/dist/models/index.d.ts.map +1 -0
  91. package/dist/prompts.d.ts +17 -0
  92. package/dist/prompts.d.ts.map +1 -0
  93. package/dist/smrt-knowledge.json +4 -4
  94. package/dist/testing/oidcProvisioningDecisionMatrix.d.ts +1168 -0
  95. package/dist/testing/oidcProvisioningDecisionMatrix.d.ts.map +1 -0
  96. package/dist/types.d.ts +33 -732
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/utils.d.ts +52 -817
  99. package/dist/utils.d.ts.map +1 -0
  100. package/package.json +7 -7
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=__smrt-register__.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"__smrt-register__.d.ts","sourceRoot":"","sources":["../src/__smrt-register__.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Agent (bot) profile resolution (#2995).
3
+ *
4
+ * An automated agent that participates in a conversation is still an author,
5
+ * and every authoring seam in the framework — `ChatMessage.senderProfileId`,
6
+ * `ChatParticipant.profileId`, `ChatReaction.profileId`, a persona's
7
+ * `actsAsProfileId` — is a `crossPackageRef` to a {@link Profile} and therefore
8
+ * a native uuid column on PostgreSQL/DuckDB. A slug-style agent identifier
9
+ * (`anytown_site_assistant`) is not a representable author there: it fails the
10
+ * uuid cast (22P02) at the boundary that owns it.
11
+ *
12
+ * `Profile` already models this: the `bot` profile type is "automated agents,
13
+ * bots, and AI entities". This module is the owning-package API that turns a
14
+ * stable agent identifier into that Profile's uuid, so consumers never have to
15
+ * mint bot profiles themselves and never have to weaken a uuid column to text.
16
+ *
17
+ * Identity is keyed on `(tenantId, slug = agentId, context =
18
+ * {@link AGENT_PROFILE_CONTEXT})`. The reserved slug context keeps an agent
19
+ * profile from ever colliding with an unrelated human/organization profile that
20
+ * happens to share the slug, and matches the model's
21
+ * `(tenant_id, slug, context, _meta_type)` unique key.
22
+ *
23
+ * @module
24
+ */
25
+ import type { ProfileCollection } from './collections/ProfileCollection';
26
+ import type { Profile } from './models/Profile';
27
+ /**
28
+ * Reserved slug context for agent-owned profiles.
29
+ *
30
+ * Agent identifiers come from application configuration, not from the profile
31
+ * namespace, so they are scoped into their own slug context rather than
32
+ * competing with person/organization slugs.
33
+ */
34
+ export declare const AGENT_PROFILE_CONTEXT = "smrt:agent";
35
+ /** Slug of the {@link ProfileType} agent profiles are classified under. */
36
+ export declare const AGENT_PROFILE_TYPE_SLUG = "bot";
37
+ /** Inputs for {@link resolveAgentProfile}. */
38
+ export interface ResolveAgentProfileParams {
39
+ /** Stable agent identifier (e.g. `anytown_site_assistant`). */
40
+ agentId: string;
41
+ /** Owning tenant, or `null` for an untenanted agent. */
42
+ tenantId?: string | null;
43
+ /** Display name for a newly created profile. Defaults to `agentId`. */
44
+ name?: string;
45
+ }
46
+ /**
47
+ * Resolve — creating on first use — the {@link Profile} an agent authors as.
48
+ *
49
+ * The lookup is tenant-bound: an agent identifier resolves to a distinct
50
+ * profile per tenant, so one tenant's assistant can never author into another
51
+ * tenant's conversation. Resolution is idempotent; repeated calls for the same
52
+ * `(tenantId, agentId)` return the same profile.
53
+ *
54
+ * @param profiles - Profile collection bound to the caller's database options.
55
+ * @param params - Agent identity to resolve.
56
+ * @returns The agent's profile, whose `id` is a real uuid.
57
+ * @throws Error when `agentId` is empty.
58
+ */
59
+ export declare function resolveAgentProfile(profiles: ProfileCollection, params: ResolveAgentProfileParams): Promise<Profile>;
60
+ /**
61
+ * Resolve an agent profile and return its uuid.
62
+ *
63
+ * Convenience wrapper for the common case — an authoring seam that needs the
64
+ * id, not the row.
65
+ *
66
+ * @param profiles - Profile collection bound to the caller's database options.
67
+ * @param params - Agent identity to resolve.
68
+ * @returns The agent profile's uuid.
69
+ */
70
+ export declare function resolveAgentProfileId(profiles: ProfileCollection, params: ResolveAgentProfileParams): Promise<string>;
71
+ //# sourceMappingURL=agent-profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-profile.d.ts","sourceRoot":"","sources":["../src/agent-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD,2EAA2E;AAC3E,eAAO,MAAM,uBAAuB,QAAQ,CAAC;AAE7C,8CAA8C;AAC9C,MAAM,WAAW,yBAAyB;IACxC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,OAAO,CAAC,CAgDlB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,MAAM,CAAC,CASjB"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Auth module exports for smrt-profiles
3
+ *
4
+ * Provides identity resolution and authentication primitives.
5
+ * Apps configure auth (OIDC providers, Nostr), modules receive resolved profiles.
6
+ */
7
+ export { createMagicLinkService, type InitiateResult, type MagicLinkConfig, type MagicLinkService, type VerifyResult, } from './magicLinkService';
8
+ export { createNip05Handler, isValidNip05Identifier, type Nip05HandlerConfig, type Nip05HandlerResult, type Nip05Request, parseNip05Identifier, } from './nip05Handler';
9
+ export { normalizeIdentityEmail } from './normalizeIdentityEmail';
10
+ export { computeEventId, createAuthEvent, decryptPrivkey, deriveEncryptionKey, type EncryptedKey, encryptPrivkey, generateNostrKeypair, getPublicKey, isValidPrivkey, isValidPubkey, type NostrEvent, type NostrKeypair, npubToPubkey, nsecToPrivkey, privkeyToNsec, pubkeyToNpub, signEvent, verifyAuthEvent, verifyNostrSignature, } from './nostrCrypto';
11
+ export { type AuthContext, createProfileFromNostr, createProfileFromOidc, type ResolveIdentityResult, resolveIdentity, } from './resolveIdentity';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,EACL,cAAc,EACd,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,KAAK,YAAY,EACjB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,eAAe,EACf,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,WAAW,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,eAAe,GAChB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Magic Link Service
3
+ *
4
+ * Handles the magic link authentication flow including:
5
+ * - Token generation and storage
6
+ * - Email sending (via callback)
7
+ * - Token verification
8
+ * - Rate limiting checks
9
+ */
10
+ import type { SmrtObjectOptions } from '@happyvertical/smrt-core';
11
+ import type { NostrIdentity } from '../models/NostrIdentity';
12
+ import type { Profile } from '../models/Profile';
13
+ export interface MagicLinkConfig {
14
+ /** Base URL for magic links (e.g., "https://example.com") */
15
+ baseUrl: string;
16
+ /** Path for verification endpoint (default: "/auth/verify") */
17
+ verifyPath?: string;
18
+ /** Token expiration in minutes (default: 15) */
19
+ expiresInMinutes?: number;
20
+ /** Maximum tokens per email per hour (default: 5) */
21
+ maxTokensPerEmailPerHour?: number;
22
+ /** Maximum tokens per IP per hour (default: 10) */
23
+ maxTokensPerIpPerHour?: number;
24
+ /** Server master secret for encryption */
25
+ masterSecret: string;
26
+ /** Callback to send the email */
27
+ sendEmail: (to: string, magicLink: string) => Promise<void>;
28
+ /** Database options */
29
+ db: SmrtObjectOptions['db'];
30
+ }
31
+ export interface InitiateResult {
32
+ success: boolean;
33
+ /** The Nostr identity (existing or new) */
34
+ nostrIdentity?: NostrIdentity;
35
+ /** The profile (existing or new) */
36
+ profile?: Profile;
37
+ /** True if a new profile was created */
38
+ created: boolean;
39
+ /** Error message if success is false */
40
+ error?: string;
41
+ /** Error code for programmatic handling */
42
+ errorCode?: 'RATE_LIMITED_EMAIL' | 'RATE_LIMITED_IP' | 'EMAIL_SEND_FAILED';
43
+ }
44
+ export interface VerifyResult {
45
+ success: boolean;
46
+ /** The profile */
47
+ profile?: Profile;
48
+ /** The Nostr identity */
49
+ nostrIdentity?: NostrIdentity;
50
+ /** The decrypted keypair (only on success) */
51
+ keypair?: {
52
+ pubkey: string;
53
+ privkey: string;
54
+ npub: string;
55
+ nsec: string;
56
+ };
57
+ /** Error message if success is false */
58
+ error?: string;
59
+ /** Error code for programmatic handling */
60
+ errorCode?: 'INVALID_TOKEN' | 'EXPIRED_TOKEN' | 'USED_TOKEN' | 'NOT_FOUND';
61
+ }
62
+ export interface MagicLinkService {
63
+ /**
64
+ * Initiate magic link flow - generates token and sends email
65
+ */
66
+ initiate(email: string, options?: {
67
+ requestedFromIp?: string;
68
+ nip05Username?: string;
69
+ }): Promise<InitiateResult>;
70
+ /**
71
+ * Verify a magic link token and return decrypted keypair
72
+ */
73
+ verify(token: string): Promise<VerifyResult>;
74
+ }
75
+ /**
76
+ * Create a magic link service instance
77
+ */
78
+ export declare function createMagicLinkService(config: MagicLinkConfig): MagicLinkService;
79
+ //# sourceMappingURL=magicLinkService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magicLinkService.d.ts","sourceRoot":"","sources":["../../src/auth/magicLinkService.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAIlE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,mDAAmD;IACnD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,uBAAuB;IACvB,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,SAAS,CAAC,EAAE,oBAAoB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CAC5E;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,8CAA8C;IAC9C,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,SAAS,CAAC,EAAE,eAAe,GAAG,eAAe,GAAG,YAAY,GAAG,WAAW,CAAC;CAC5E;AAED,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,CACN,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QACR,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GACA,OAAO,CAAC,cAAc,CAAC,CAAC;IAE3B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,eAAe,GACtB,gBAAgB,CAuOlB"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * NIP-05 Handler
3
+ *
4
+ * Provides a helper for serving the /.well-known/nostr.json endpoint
5
+ * for NIP-05 identity verification.
6
+ *
7
+ * @see https://github.com/nostr-protocol/nips/blob/master/05.md
8
+ */
9
+ import type { SmrtObjectOptions } from '@happyvertical/smrt-core';
10
+ import { type Nip05Response } from '../collections/NostrIdentityCollection';
11
+ export interface Nip05HandlerConfig {
12
+ /** Database options */
13
+ db: SmrtObjectOptions['db'];
14
+ /** Optional: Additional relays to include for all users */
15
+ defaultRelays?: string[];
16
+ /** Optional: Cache TTL in seconds (default: 300 = 5 minutes) */
17
+ cacheTtlSeconds?: number;
18
+ }
19
+ export interface Nip05Request {
20
+ /** The 'name' query parameter from the request */
21
+ name?: string | null;
22
+ }
23
+ export interface Nip05HandlerResult {
24
+ /** The NIP-05 response body */
25
+ body: Nip05Response;
26
+ /** Suggested headers for the response */
27
+ headers: Record<string, string>;
28
+ /** HTTP status code */
29
+ status: number;
30
+ }
31
+ /**
32
+ * Create a NIP-05 handler
33
+ *
34
+ * @example
35
+ * // SvelteKit
36
+ * import { createNip05Handler } from '@happyvertical/smrt-profiles';
37
+ *
38
+ * const handler = createNip05Handler({ db: { type: 'postgres', url: DATABASE_URL } });
39
+ *
40
+ * export async function GET({ url }) {
41
+ * const result = await handler({ name: url.searchParams.get('name') });
42
+ * return new Response(JSON.stringify(result.body), {
43
+ * status: result.status,
44
+ * headers: result.headers,
45
+ * });
46
+ * }
47
+ *
48
+ * @example
49
+ * // Express
50
+ * import { createNip05Handler } from '@happyvertical/smrt-profiles';
51
+ *
52
+ * const handler = createNip05Handler({ db: { type: 'postgres', url: DATABASE_URL } });
53
+ *
54
+ * app.get('/.well-known/nostr.json', async (req, res) => {
55
+ * const result = await handler({ name: req.query.name });
56
+ * res.status(result.status).set(result.headers).json(result.body);
57
+ * });
58
+ */
59
+ export declare function createNip05Handler(config: Nip05HandlerConfig): (request: Nip05Request) => Promise<Nip05HandlerResult>;
60
+ /**
61
+ * Validate a NIP-05 identifier format
62
+ * @param identifier - The identifier to validate (e.g., "alice@example.com")
63
+ */
64
+ export declare function isValidNip05Identifier(identifier: string): boolean;
65
+ /**
66
+ * Parse a NIP-05 identifier into its parts
67
+ * @param identifier - The identifier to parse (e.g., "alice@example.com")
68
+ */
69
+ export declare function parseNip05Identifier(identifier: string): {
70
+ localPart: string;
71
+ domain: string;
72
+ } | null;
73
+ //# sourceMappingURL=nip05Handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nip05Handler.d.ts","sourceRoot":"","sources":["../../src/auth/nip05Handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACL,KAAK,aAAa,EAEnB,MAAM,wCAAwC,CAAC;AAEhD,MAAM,WAAW,kBAAkB;IACjC,uBAAuB;IACvB,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC5B,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,gEAAgE;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,IAIzD,SAAS,YAAY,KACpB,OAAO,CAAC,kBAAkB,CAAC,CAqC/B;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAoBlE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAOP"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Canonicalize an email used as an external identity key.
3
+ *
4
+ * Keep this in application code: SQL `trim()` and `lower()` have
5
+ * adapter-specific whitespace and Unicode behavior.
6
+ */
7
+ export declare function normalizeIdentityEmail(email: string): string;
8
+ //# sourceMappingURL=normalizeIdentityEmail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeIdentityEmail.d.ts","sourceRoot":"","sources":["../../src/auth/normalizeIdentityEmail.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM5D"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Nostr cryptographic utilities
3
+ *
4
+ * Handles keypair generation, encryption/decryption of private keys,
5
+ * signature verification, and bech32 encoding for Nostr authentication.
6
+ */
7
+ export interface NostrKeypair {
8
+ /** Hex-encoded public key (64 characters) */
9
+ pubkey: string;
10
+ /** Hex-encoded private key (64 characters) */
11
+ privkey: string;
12
+ }
13
+ export interface EncryptedKey {
14
+ /** Base64-encoded ciphertext */
15
+ ciphertext: string;
16
+ /** Base64-encoded initialization vector */
17
+ iv: string;
18
+ /** Base64-encoded authentication tag */
19
+ tag: string;
20
+ }
21
+ export interface NostrEvent {
22
+ id?: string;
23
+ pubkey: string;
24
+ created_at: number;
25
+ kind: number;
26
+ tags: string[][];
27
+ content: string;
28
+ sig?: string;
29
+ }
30
+ /**
31
+ * Generate a new Nostr keypair (secp256k1)
32
+ */
33
+ export declare function generateNostrKeypair(): NostrKeypair;
34
+ /**
35
+ * Derive an encryption key from the master secret using HKDF
36
+ * @param masterSecret - Server master secret
37
+ */
38
+ export declare function deriveEncryptionKey(masterSecret: string): Buffer;
39
+ /**
40
+ * Encrypt a private key using AES-256-GCM
41
+ * @param privkey - Hex-encoded private key
42
+ * @param masterSecret - Server master secret (from env)
43
+ */
44
+ export declare function encryptPrivkey(privkey: string, masterSecret: string): EncryptedKey;
45
+ /**
46
+ * Decrypt a private key using AES-256-GCM
47
+ * @param encrypted - Encrypted key data
48
+ * @param masterSecret - Server master secret (from env)
49
+ */
50
+ export declare function decryptPrivkey(encrypted: EncryptedKey, masterSecret: string): string;
51
+ /**
52
+ * Compute the event ID (SHA-256 hash of serialized event)
53
+ */
54
+ export declare function computeEventId(event: NostrEvent): string;
55
+ /**
56
+ * Sign a Nostr event using Schnorr signatures (BIP-340)
57
+ * @param event - Event to sign (without id and sig)
58
+ * @param privkey - Hex-encoded private key
59
+ */
60
+ export declare function signEvent(event: Omit<NostrEvent, 'id' | 'sig'>, privkey: string): NostrEvent;
61
+ /**
62
+ * Verify a Nostr event Schnorr signature (BIP-340)
63
+ * @param event - Nostr event object with sig field
64
+ */
65
+ export declare function verifyNostrSignature(event: NostrEvent): boolean;
66
+ /**
67
+ * Create a Nostr event for authentication (NIP-42 style)
68
+ * @param privkey - Private key to sign with
69
+ * @param challenge - Server challenge string
70
+ * @param relay - Relay URL (optional)
71
+ */
72
+ export declare function createAuthEvent(privkey: string, challenge: string, relay?: string): NostrEvent;
73
+ /**
74
+ * Verify an authentication event
75
+ * @param event - Auth event to verify
76
+ * @param expectedChallenge - Expected challenge string
77
+ * @param maxAgeSeconds - Maximum age of the event in seconds (default: 300 = 5 minutes)
78
+ */
79
+ export declare function verifyAuthEvent(event: NostrEvent, expectedChallenge: string, maxAgeSeconds?: number): {
80
+ valid: boolean;
81
+ error?: string;
82
+ };
83
+ /**
84
+ * Convert hex public key to npub (bech32)
85
+ */
86
+ export declare function pubkeyToNpub(pubkey: string): string;
87
+ /**
88
+ * Convert npub (bech32) to hex public key
89
+ */
90
+ export declare function npubToPubkey(npub: string): string;
91
+ /**
92
+ * Convert hex private key to nsec (bech32)
93
+ */
94
+ export declare function privkeyToNsec(privkey: string): string;
95
+ /**
96
+ * Convert nsec (bech32) to hex private key
97
+ */
98
+ export declare function nsecToPrivkey(nsec: string): string;
99
+ /**
100
+ * Get public key from private key
101
+ */
102
+ export declare function getPublicKey(privkey: string): string;
103
+ /**
104
+ * Validate a hex-encoded public key
105
+ */
106
+ export declare function isValidPubkey(pubkey: string): boolean;
107
+ /**
108
+ * Validate a hex-encoded private key
109
+ */
110
+ export declare function isValidPrivkey(privkey: string): boolean;
111
+ //# sourceMappingURL=nostrCrypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nostrCrypto.d.ts","sourceRoot":"","sources":["../../src/auth/nostrCrypto.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,YAAY,CAWnD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,YAAY,CAgBd;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,MAAM,GACnB,MAAM,CAeR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAWxD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,EACrC,OAAO,EAAE,MAAM,GACd,UAAU,CAcZ;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAqB/D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,GACb,UAAU,CAmBZ;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,iBAAiB,EAAE,MAAM,EACzB,aAAa,GAAE,MAAY,GAC1B;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA0BpC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAYrD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYvD"}
@@ -0,0 +1,58 @@
1
+ import type { getDatabase } from '@happyvertical/sql';
2
+ type DatabaseInterface = Awaited<ReturnType<typeof getDatabase>>;
3
+ /** Shared transaction and concurrency policy for OIDC provisioning. */
4
+ export interface OidcProvisioningCoordinatorOptions<T> {
5
+ /** Root or transaction-bound database used for every provisioning write. */
6
+ db: DatabaseInterface;
7
+ /**
8
+ * Stable keys used for local serialization. Supply both the exact
9
+ * issuer/subject key and normalized email when available.
10
+ */
11
+ lockKeys: readonly string[];
12
+ /** Package-specific durable race-arbiter classifier. */
13
+ isRaceConflict: (error: unknown) => boolean;
14
+ /** Package-specific transaction failure mapping. */
15
+ createTransactionError: (message: string, cause?: unknown) => Error;
16
+ /** Package-specific terminal concurrency failure mapping. */
17
+ createConcurrencyError: (cause?: unknown) => Error;
18
+ /** Provision atomically using the supplied transaction-bound handle. */
19
+ provision: (tx: DatabaseInterface) => Promise<T>;
20
+ /**
21
+ * Rehydrate root-owned results after commit so models do not retain a
22
+ * released transaction client. Omit for non-model results.
23
+ */
24
+ rebindRootResult?: (result: T, rootDb: DatabaseInterface) => Promise<T>;
25
+ }
26
+ /**
27
+ * Coordinate one OIDC provisioning operation across adapters.
28
+ *
29
+ * Root adapters must expose `beginTransaction`. Already-bound adapters must
30
+ * support savepoints. An adapter that exposes only `transaction()` is
31
+ * intentionally ambiguous and fails closed instead of risking a nested
32
+ * transaction that could roll back its caller's work.
33
+ */
34
+ export declare function coordinateOidcProvisioning<T>(options: OidcProvisioningCoordinatorOptions<T>): Promise<T>;
35
+ /**
36
+ * Detect an adapter error caused by an aborted transaction.
37
+ *
38
+ * Reduced to the framework contract in #2366. The heuristic this replaced
39
+ * matched a bare `/transaction.*aborted/` against every message in the chain,
40
+ * which would misclassify a genuine foreign-key or check violation whose text
41
+ * happened to mention a transaction. Core now recognizes PostgreSQL's
42
+ * `25P02 in_failed_sql_transaction` from the driver's own SQLSTATE, whichever
43
+ * layer wrapped it.
44
+ *
45
+ * Kept as a named export because it is part of this package's provisioning
46
+ * API surface; the body is now a single delegation.
47
+ */
48
+ export declare function isOidcAbortedTransactionError(error: unknown): boolean;
49
+ export interface OidcProvisioningRaceClassifierOptions {
50
+ /** Package-specific database constraint messages. */
51
+ messagePatterns?: readonly RegExp[];
52
+ }
53
+ /** Classify only the durable constraints used to converge OIDC retries. */
54
+ export declare function isOidcProvisioningRaceConflict(error: unknown, options?: OidcProvisioningRaceClassifierOptions): boolean;
55
+ /** Wrap a known OIDC arbiter write so only its unique failure is retryable. */
56
+ export declare function saveOidcRaceArbiter<T>(operation: () => Promise<T>): Promise<T>;
57
+ export {};
58
+ //# sourceMappingURL=oidcProvisioningCoordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidcProvisioningCoordinator.d.ts","sourceRoot":"","sources":["../../src/auth/oidcProvisioningCoordinator.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,KAAK,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC;AA0CjE,uEAAuE;AACvE,MAAM,WAAW,kCAAkC,CAAC,CAAC;IACnD,4EAA4E;IAC5E,EAAE,EAAE,iBAAiB,CAAC;IACtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,wDAAwD;IACxD,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IAC5C,oDAAoD;IACpD,sBAAsB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,KAAK,CAAC;IACpE,6DAA6D;IAC7D,sBAAsB,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,KAAK,CAAC;IACnD,wEAAwE;IACxE,SAAS,EAAE,CAAC,EAAE,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACzE;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAAC,CAAC,EAChD,OAAO,EAAE,kCAAkC,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,CAAC,CAoCZ;AAyBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErE;AAED,MAAM,WAAW,qCAAqC;IACpD,qDAAqD;IACrD,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAaD,2EAA2E;AAC3E,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,qCAA0C,GAClD,OAAO,CAkDT;AAED,+EAA+E;AAC/E,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAaZ"}
@@ -0,0 +1,23 @@
1
+ import type { getDatabase } from '@happyvertical/sql';
2
+ import { OidcIdentity } from '../models/OidcIdentity';
3
+ import type { Profile } from '../models/Profile';
4
+ type DatabaseInterface = Awaited<ReturnType<typeof getDatabase>>;
5
+ export interface OidcProvisioningPersonInput {
6
+ email?: string;
7
+ name?: string;
8
+ preferredUsername?: string;
9
+ subject: string;
10
+ }
11
+ export interface OidcProvisioningIdentityInput {
12
+ email?: string;
13
+ issuer: string;
14
+ profileId: string;
15
+ provider: string;
16
+ subject: string;
17
+ }
18
+ /** Create and reserve a fresh global Person inside the caller's transaction. */
19
+ export declare function createOidcProvisioningPerson(db: DatabaseInterface, input: OidcProvisioningPersonInput): Promise<Profile>;
20
+ /** Insert the identity after the caller proves Profile ownership. */
21
+ export declare function insertOidcProvisioningIdentity(db: DatabaseInterface, input: OidcProvisioningIdentityInput): Promise<OidcIdentity>;
22
+ export {};
23
+ //# sourceMappingURL=oidcProvisioningPrimitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidcProvisioningPrimitives.d.ts","sourceRoot":"","sources":["../../src/auth/oidcProvisioningPrimitives.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIjD,KAAK,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC;AAEjE,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,gFAAgF;AAChF,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,OAAO,CAAC,CA4BlB;AAED,qEAAqE;AACrE,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,YAAY,CAAC,CAYvB"}