@happyvertical/smrt-profiles 0.35.2 → 0.35.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/utils.d.ts CHANGED
@@ -1,11 +1,151 @@
1
- /**
2
- * Utility functions for profile operations
3
- *
4
- * Provides standalone helper functions for metadata management,
5
- * relationship operations, and validation.
6
- *
7
- * @packageDocumentation
8
- */
1
+ import { Asset } from '@happyvertical/smrt-assets';
2
+ import { SmrtObject } from '@happyvertical/smrt-core';
3
+ import { SmrtObjectOptions } from '@happyvertical/smrt-core';
4
+
5
+ declare class ApiKey extends SmrtObject {
6
+ /**
7
+ * Link to the Profile (Person, Organization, Bot)
8
+ */
9
+ profileId?: string;
10
+ /**
11
+ * SHA-256 hash of the API key
12
+ */
13
+ keyHash: string;
14
+ /**
15
+ * First 8 characters of the key for identification (e.g., "sk_live_a1b2...")
16
+ */
17
+ keyPrefix: string;
18
+ /**
19
+ * Human-readable name for the key (e.g., "CI Bot", "Local CLI")
20
+ */
21
+ name: string;
22
+ /**
23
+ * Scopes/permissions for this key
24
+ */
25
+ scopes: string[];
26
+ /**
27
+ * Last time this key was used
28
+ */
29
+ lastUsedAt: Date | null;
30
+ /**
31
+ * When this key expires (null = never)
32
+ */
33
+ expiresAt: Date | null;
34
+ /**
35
+ * When this key was revoked (null = active)
36
+ */
37
+ revokedAt: Date | null;
38
+ constructor(options?: ApiKeyOptions);
39
+ /**
40
+ * Get the linked Profile
41
+ */
42
+ getProfile(): Promise<Profile | null>;
43
+ /**
44
+ * Check if this key is valid (not expired, not revoked)
45
+ */
46
+ isValid(): boolean;
47
+ /**
48
+ * Check if this key has a specific scope
49
+ */
50
+ hasScope(scope: string): boolean;
51
+ /**
52
+ * Revoke this key
53
+ */
54
+ revoke(): Promise<void>;
55
+ /**
56
+ * Record usage of this key
57
+ */
58
+ recordUsage(): Promise<void>;
59
+ /**
60
+ * Hash an API key
61
+ */
62
+ static hashKey(key: string): string;
63
+ /**
64
+ * Generate a new API key for a profile
65
+ */
66
+ static generate(profile: Profile, options: {
67
+ name: string;
68
+ scopes?: string[];
69
+ expiresAt?: Date | null;
70
+ db?: SmrtObjectOptions['db'];
71
+ }): Promise<GenerateKeyResult>;
72
+ /**
73
+ * Verify an API key and return the ApiKey record if valid
74
+ */
75
+ static verify(key: string, options?: SmrtObjectOptions): Promise<ApiKey | null>;
76
+ }
77
+
78
+ declare interface ApiKeyOptions extends SmrtObjectOptions {
79
+ profileId?: string;
80
+ name?: string;
81
+ scopes?: string[];
82
+ expiresAt?: Date | null;
83
+ }
84
+
85
+ declare class AuditLog extends SmrtObject {
86
+ tenantId: string | null;
87
+ /**
88
+ * The profile who performed the action
89
+ */
90
+ profileId?: string;
91
+ /**
92
+ * Action performed (e.g., 'issue.update', 'feedback.incorporate')
93
+ */
94
+ action: string;
95
+ /**
96
+ * Type of resource affected (e.g., 'Issue', 'Repository')
97
+ */
98
+ resourceType: string;
99
+ /**
100
+ * ID of the affected resource
101
+ */
102
+ resourceId: string;
103
+ /**
104
+ * Source of the action
105
+ */
106
+ source: AuditSource;
107
+ /**
108
+ * Additional context (CI run ID, request ID, etc.)
109
+ */
110
+ metadata: Record<string, unknown>;
111
+ /**
112
+ * For pass-through identity in CI - the actual person who triggered
113
+ */
114
+ onBehalfOfId?: string | null;
115
+ constructor(options?: AuditLogOptions);
116
+ /**
117
+ * Get the profile who performed the action
118
+ */
119
+ getProfile(): Promise<Profile | null>;
120
+ /**
121
+ * Get the profile on whose behalf the action was performed (if any)
122
+ */
123
+ getOnBehalfOf(): Promise<Profile | null>;
124
+ /**
125
+ * Get the effective actor (onBehalfOf if set, otherwise profile)
126
+ */
127
+ getEffectiveActor(): Promise<Profile | null>;
128
+ /**
129
+ * Create an audit log entry
130
+ */
131
+ static record(options: AuditLogOptions & {
132
+ profile: Profile;
133
+ onBehalfOf?: Profile | null;
134
+ }): Promise<AuditLog>;
135
+ }
136
+
137
+ declare interface AuditLogOptions extends SmrtObjectOptions {
138
+ profileId?: string;
139
+ action?: string;
140
+ resourceType?: string;
141
+ resourceId?: string;
142
+ source?: AuditSource;
143
+ metadata?: Record<string, unknown>;
144
+ onBehalfOfId?: string | null;
145
+ tenantId?: string | null;
146
+ }
147
+
148
+ declare type AuditSource = 'web' | 'cli' | 'ci' | 'webhook' | 'mcp';
9
149
 
10
150
  /**
11
151
  * Create a reciprocal relationship between two profiles
@@ -18,7 +158,7 @@
18
158
  * @param relationshipSlug - The type of relationship
19
159
  * @param contextProfile - Optional context profile for tertiary relationships
20
160
  */
21
- export declare function createReciprocalRelationship(fromProfile: any, toProfile: any, relationshipSlug: string, contextProfile?: any): Promise<void>;
161
+ export declare function createReciprocalRelationship(fromProfile: Profile, toProfile: Profile, relationshipSlug: string, contextProfile?: Profile): Promise<void>;
22
162
 
23
163
  /**
24
164
  * Find profiles with a specific metadata key-value pair
@@ -28,7 +168,12 @@ export declare function createReciprocalRelationship(fromProfile: any, toProfile
28
168
  * @param options - Database and configuration options
29
169
  * @returns Array of matching profile IDs
30
170
  */
31
- export declare function findProfilesByMeta(metafieldSlug: string, value: any, options?: any): Promise<string[]>;
171
+ export declare function findProfilesByMeta(metafieldSlug: string, value: unknown, options?: SmrtObjectOptions): Promise<string[]>;
172
+
173
+ declare interface GenerateKeyResult {
174
+ key: string;
175
+ apiKey: ApiKey;
176
+ }
32
177
 
33
178
  /**
34
179
  * Retrieve all metadata for a profile as a key-value object
@@ -37,7 +182,540 @@ export declare function findProfilesByMeta(metafieldSlug: string, value: any, op
37
182
  * @param options - Database and configuration options
38
183
  * @returns Object with metafield slugs as keys and values as values
39
184
  */
40
- export declare function getProfileMetadata(profileId: string, options?: any): Promise<Record<string, any>>;
185
+ export declare function getProfileMetadata(profileId: string, options?: SmrtObjectOptions): Promise<Record<string, string>>;
186
+
187
+ declare class NostrIdentity extends SmrtObject {
188
+ /**
189
+ * Link to the Profile (Person, Organization, Bot)
190
+ */
191
+ profileId?: string;
192
+ /**
193
+ * Hex-encoded secp256k1 public key (64 characters)
194
+ */
195
+ pubkey: string;
196
+ /**
197
+ * AES-256-GCM encrypted private key (base64-encoded ciphertext)
198
+ */
199
+ encryptedPrivkey: string;
200
+ /**
201
+ * Initialization vector for AES-GCM decryption (base64)
202
+ */
203
+ encryptionIv: string;
204
+ /**
205
+ * Authentication tag from AES-GCM (base64)
206
+ */
207
+ encryptionTag: string;
208
+ /**
209
+ * Email address associated with this identity
210
+ */
211
+ email: string;
212
+ /**
213
+ * Username for NIP-05 verification (e.g., "alice" for alice@domain.com)
214
+ */
215
+ nip05Username: string;
216
+ /**
217
+ * Last time this identity was used for authentication
218
+ */
219
+ lastUsedAt: Date | null;
220
+ /**
221
+ * When this identity was verified via magic link
222
+ */
223
+ verifiedAt: Date | null;
224
+ constructor(options?: NostrIdentityOptions);
225
+ /**
226
+ * Get the linked Profile
227
+ */
228
+ getProfile(): Promise<Profile | null>;
229
+ /**
230
+ * Find identity by public key
231
+ */
232
+ static findByPubkey(pubkey: string, options?: SmrtObjectOptions): Promise<NostrIdentity | null>;
233
+ /**
234
+ * Find identity by email
235
+ */
236
+ static findByEmail(email: string, options?: SmrtObjectOptions): Promise<NostrIdentity | null>;
237
+ /**
238
+ * Find identity by NIP-05 username
239
+ */
240
+ static findByNip05(username: string, options?: SmrtObjectOptions): Promise<NostrIdentity | null>;
241
+ /**
242
+ * Decrypt the private key using the server master secret
243
+ * @param masterSecret - SERVER_MASTER_SECRET from environment
244
+ * @returns Hex-encoded private key
245
+ */
246
+ decryptPrivkey(masterSecret: string): string;
247
+ /**
248
+ * Get the full keypair (requires master secret)
249
+ * @param masterSecret - SERVER_MASTER_SECRET from environment
250
+ */
251
+ getKeypair(masterSecret: string): {
252
+ pubkey: string;
253
+ privkey: string;
254
+ npub: string;
255
+ nsec: string;
256
+ };
257
+ /**
258
+ * Record usage of this identity
259
+ */
260
+ recordUsage(): Promise<void>;
261
+ /**
262
+ * Mark this identity as verified
263
+ */
264
+ markVerified(): Promise<void>;
265
+ /**
266
+ * Check if this identity is verified
267
+ */
268
+ isVerified(): boolean;
269
+ /**
270
+ * Get the NIP-05 identifier (username@domain)
271
+ * Note: Domain must be provided by the application
272
+ */
273
+ getNip05Identifier(domain: string): string;
274
+ }
275
+
276
+ declare interface NostrIdentityOptions extends SmrtObjectOptions {
277
+ profileId?: string;
278
+ pubkey?: string;
279
+ encryptedPrivkey?: string;
280
+ encryptionIv?: string;
281
+ encryptionTag?: string;
282
+ email?: string;
283
+ nip05Username?: string;
284
+ lastUsedAt?: Date | null;
285
+ verifiedAt?: Date | null;
286
+ }
287
+
288
+ declare class OidcIdentity extends SmrtObject {
289
+ /**
290
+ * Link to the Profile (Person, Organization, Bot)
291
+ */
292
+ profileId?: string;
293
+ /**
294
+ * Provider name (e.g., 'keycloak', 'google', 'github')
295
+ */
296
+ provider: string;
297
+ /**
298
+ * OIDC issuer URL (e.g., https://keycloak.example.com/realms/bmp)
299
+ */
300
+ issuer: string;
301
+ /**
302
+ * OIDC subject claim - unique identifier from the provider
303
+ */
304
+ subject: string;
305
+ /**
306
+ * Cached email from the IdP (for display/lookup)
307
+ */
308
+ email: string;
309
+ /**
310
+ * Last time this identity was used for authentication
311
+ */
312
+ lastUsedAt: Date | null;
313
+ constructor(options?: OidcIdentityOptions);
314
+ /**
315
+ * Get the linked Profile
316
+ */
317
+ getProfile(): Promise<Profile | null>;
318
+ /**
319
+ * Find identity by issuer and subject
320
+ */
321
+ static findBySubject(issuer: string, subject: string, options?: SmrtObjectOptions): Promise<OidcIdentity | null>;
322
+ /**
323
+ * Find or create identity for a profile
324
+ */
325
+ static findOrCreate(profile: Profile, oidcData: {
326
+ provider: string;
327
+ issuer: string;
328
+ subject: string;
329
+ email?: string;
330
+ }, options?: SmrtObjectOptions): Promise<OidcIdentity>;
331
+ /**
332
+ * Record usage of this identity
333
+ */
334
+ recordUsage(): Promise<void>;
335
+ }
336
+
337
+ declare interface OidcIdentityOptions extends SmrtObjectOptions {
338
+ profileId?: string;
339
+ provider?: string;
340
+ issuer?: string;
341
+ subject?: string;
342
+ email?: string;
343
+ lastUsedAt?: Date | null;
344
+ }
345
+
346
+ declare class Profile extends SmrtObject {
347
+ tenantId: string | null;
348
+ typeId?: string;
349
+ email?: string;
350
+ name: string;
351
+ description?: string;
352
+ metadata: ProfileMetadata[];
353
+ relationshipsFrom: ProfileRelationship[];
354
+ relationshipsTo: ProfileRelationship[];
355
+ constructor(options?: ProfileOptions);
356
+ /**
357
+ * Get the profile type slug for this profile
358
+ *
359
+ * @returns The slug of the profile type
360
+ */
361
+ getTypeSlug(): Promise<string>;
362
+ /**
363
+ * Set the profile type by slug
364
+ *
365
+ * @param slug - The slug of the profile type
366
+ * @throws Error if profile type not found
367
+ */
368
+ setTypeBySlug(slug: string): Promise<void>;
369
+ /**
370
+ * Add metadata to this profile
371
+ *
372
+ * @param metafieldSlug - The slug of the metafield
373
+ * @param value - The value to set
374
+ */
375
+ addMetadata(metafieldSlug: string, value: unknown): Promise<void>;
376
+ /**
377
+ * Get all metadata for this profile as key-value object
378
+ *
379
+ * @returns Object with metafield slugs as keys
380
+ */
381
+ getMetadata(): Promise<Record<string, string>>;
382
+ /**
383
+ * Update multiple metadata values
384
+ *
385
+ * @param metadata - Object with metafield slugs as keys and values
386
+ */
387
+ updateMetadata(metadata: Record<string, unknown>): Promise<void>;
388
+ /**
389
+ * Remove metadata by metafield slug
390
+ *
391
+ * @param metafieldSlug - The slug of the metafield to remove
392
+ */
393
+ removeMetadata(metafieldSlug: string): Promise<void>;
394
+ private getProfileAssetCollection;
395
+ getAssets(relationship?: string): Promise<Asset[]>;
396
+ addAsset(asset: Asset, relationship?: string, sortOrder?: number): Promise<void>;
397
+ removeAsset(assetId: string, relationship?: string): Promise<void>;
398
+ /**
399
+ * Add a relationship to another profile
400
+ *
401
+ * @param toProfile - The target profile
402
+ * @param relationshipSlug - The type of relationship
403
+ * @param contextProfile - Optional context profile for tertiary relationships
404
+ */
405
+ addRelationship(toProfile: Profile, relationshipSlug: string, contextProfile?: Profile): Promise<void>;
406
+ /**
407
+ * Get all relationships for this profile
408
+ *
409
+ * @param options - Filter options (typeSlug, direction)
410
+ * @returns Array of ProfileRelationship instances
411
+ */
412
+ getRelationships(options?: {
413
+ typeSlug?: string;
414
+ direction?: 'from' | 'to' | 'all';
415
+ }): Promise<ProfileRelationship[]>;
416
+ /**
417
+ * Get related profiles
418
+ *
419
+ * @param relationshipSlug - Optional filter by relationship type slug
420
+ * @returns Array of related Profile instances
421
+ */
422
+ getRelatedProfiles(relationshipSlug?: string): Promise<Profile[]>;
423
+ /**
424
+ * Remove a relationship to another profile
425
+ *
426
+ * @param toProfile - The target profile
427
+ * @param relationshipSlug - The type of relationship to remove
428
+ */
429
+ removeRelationship(toProfile: Profile, relationshipSlug: string): Promise<void>;
430
+ /**
431
+ * AI-powered: Generate a professional bio for this profile
432
+ *
433
+ * Uses the `smrtProfiles.profile.generateBio` prompt registered via
434
+ * `@happyvertical/smrt-prompts`, allowing tenant- or instance-level
435
+ * overrides of the template, model, and parameters at runtime.
436
+ *
437
+ * @returns Generated bio text
438
+ */
439
+ generateBio(): Promise<string>;
440
+ /**
441
+ * AI-powered: Check if profile matches criteria
442
+ *
443
+ * @param criteria - Criteria to match against
444
+ * @returns True if matches criteria
445
+ */
446
+ matches(criteria: string): Promise<boolean>;
447
+ /**
448
+ * Find profiles by metadata key-value pair
449
+ *
450
+ * @param metafieldSlug - The metafield slug to search
451
+ * @param value - The value to match
452
+ * @returns Array of matching profiles
453
+ */
454
+ static findByMetadata(_metafieldSlug: string, _value: unknown): Promise<Profile[]>;
455
+ /**
456
+ * Find profiles by type slug
457
+ *
458
+ * @param typeSlug - The profile type slug
459
+ * @returns Array of matching profiles
460
+ */
461
+ static findByType(_typeSlug: string): Promise<Profile[]>;
462
+ /**
463
+ * Find related profiles for a given profile
464
+ *
465
+ * @param profileId - The profile UUID
466
+ * @param relationshipSlug - Optional filter by relationship type
467
+ * @returns Array of related profiles
468
+ */
469
+ static findRelated(_profileId: string, _relationshipSlug?: string): Promise<Profile[]>;
470
+ /**
471
+ * Search profiles by email
472
+ *
473
+ * @param email - The email to search for
474
+ * @returns Profile or null if not found
475
+ */
476
+ static searchByEmail(_email: string): Promise<Profile | null>;
477
+ /**
478
+ * Get all API keys for this profile
479
+ *
480
+ * @returns Array of API keys
481
+ */
482
+ getApiKeys(): Promise<ApiKey[]>;
483
+ /**
484
+ * Get active (non-revoked, non-expired) API keys for this profile
485
+ *
486
+ * @returns Array of active API keys
487
+ */
488
+ getActiveApiKeys(): Promise<ApiKey[]>;
489
+ /**
490
+ * Generate a new API key for this profile
491
+ *
492
+ * @param options - Key options (name, scopes, expiration)
493
+ * @returns The generated key (plaintext) and ApiKey record
494
+ */
495
+ generateApiKey(options: {
496
+ name: string;
497
+ scopes?: string[];
498
+ expiresAt?: Date | null;
499
+ }): Promise<GenerateKeyResult>;
500
+ /**
501
+ * Get all OIDC identities linked to this profile
502
+ *
503
+ * @returns Array of OIDC identity records
504
+ */
505
+ getOidcIdentities(): Promise<OidcIdentity[]>;
506
+ /**
507
+ * Link a new OIDC identity to this profile
508
+ *
509
+ * @param oidcData - OIDC provider data
510
+ * @returns The linked OIDC identity record
511
+ */
512
+ linkOidcIdentity(oidcData: {
513
+ provider: string;
514
+ issuer: string;
515
+ subject: string;
516
+ email?: string;
517
+ }): Promise<OidcIdentity>;
518
+ /**
519
+ * Get all Nostr identities linked to this profile
520
+ *
521
+ * @returns Array of Nostr identity records
522
+ */
523
+ getNostrIdentities(): Promise<NostrIdentity[]>;
524
+ /**
525
+ * Link a new Nostr identity to this profile
526
+ *
527
+ * @param nostrData - Nostr identity data (encrypted keypair)
528
+ * @returns The linked Nostr identity record
529
+ */
530
+ linkNostrIdentity(nostrData: {
531
+ pubkey: string;
532
+ encryptedPrivkey: string;
533
+ encryptionIv: string;
534
+ encryptionTag: string;
535
+ email: string;
536
+ nip05Username?: string;
537
+ }): Promise<NostrIdentity>;
538
+ /**
539
+ * Get audit logs for actions performed by this profile
540
+ *
541
+ * @param limit - Maximum number of logs to return
542
+ * @returns Array of audit log entries
543
+ */
544
+ getAuditLogs(limit?: number): Promise<AuditLog[]>;
545
+ /**
546
+ * Record an audit log entry for an action by this profile
547
+ *
548
+ * @param options - Audit log options
549
+ * @returns The created audit log entry
550
+ */
551
+ recordAction(options: {
552
+ action: string;
553
+ resourceType: string;
554
+ resourceId: string;
555
+ source?: 'web' | 'cli' | 'ci' | 'webhook' | 'mcp';
556
+ metadata?: Record<string, unknown>;
557
+ onBehalfOf?: Profile | null;
558
+ }): Promise<AuditLog>;
559
+ }
560
+
561
+ declare class ProfileMetadata extends SmrtObject {
562
+ tenantId: string | null;
563
+ profileId?: string;
564
+ metafieldId?: string;
565
+ value: string;
566
+ constructor(options?: ProfileMetadataOptions);
567
+ /**
568
+ * Validate this metadata value against the metafield's validation schema
569
+ *
570
+ * @returns True if valid, throws error if invalid
571
+ */
572
+ validate(): Promise<boolean>;
573
+ /**
574
+ * Get the metafield slug for this metadata
575
+ *
576
+ * @returns The slug of the metafield
577
+ */
578
+ getMetafieldSlug(): Promise<string>;
579
+ }
580
+
581
+ declare interface ProfileMetadataOptions extends SmrtObjectOptions {
582
+ profileId?: string;
583
+ metafieldId?: string;
584
+ value?: string;
585
+ tenantId?: string | null;
586
+ }
587
+
588
+ declare class ProfileMetafield extends SmrtObject {
589
+ tenantId: string | null;
590
+ name: string;
591
+ description?: string;
592
+ validation?: ValidationSchema;
593
+ constructor(options?: ProfileMetafieldOptions);
594
+ /**
595
+ * Convenience method for slug-based lookup
596
+ *
597
+ * @param slug - The slug to search for
598
+ * @returns ProfileMetafield instance or null if not found
599
+ */
600
+ static getBySlug(_slug: string): Promise<ProfileMetafield | null>;
601
+ /**
602
+ * Register a custom validator function
603
+ *
604
+ * @param name - Name of the validator (used in validation.custom field)
605
+ * @param validator - The validator function
606
+ */
607
+ static registerValidator(name: string, validator: ValidatorFunction): void;
608
+ /**
609
+ * Get a registered custom validator
610
+ *
611
+ * @param name - Name of the validator
612
+ * @returns The validator function or undefined
613
+ */
614
+ static getValidator(name: string): ValidatorFunction | undefined;
615
+ /**
616
+ * Validate a value against this metafield's validation schema
617
+ *
618
+ * @param value - The value to validate
619
+ * @returns True if valid, throws ValidationError if invalid
620
+ */
621
+ validateValue(value: unknown): Promise<boolean>;
622
+ }
623
+
624
+ declare interface ProfileMetafieldOptions extends SmrtObjectOptions {
625
+ slug?: string;
626
+ name?: string;
627
+ description?: string;
628
+ validation?: ValidationSchema;
629
+ tenantId?: string | null;
630
+ }
631
+
632
+ declare interface ProfileOptions extends SmrtObjectOptions {
633
+ typeId?: string;
634
+ email?: string;
635
+ name?: string;
636
+ description?: string;
637
+ tenantId?: string | null;
638
+ }
639
+
640
+ declare class ProfileRelationship extends SmrtObject {
641
+ tenantId: string | null;
642
+ fromProfileId?: string;
643
+ toProfileId?: string;
644
+ typeId?: string;
645
+ contextProfileId?: string;
646
+ terms: ProfileRelationshipTerm[];
647
+ constructor(options?: ProfileRelationshipOptions);
648
+ /**
649
+ * Get the relationship type slug
650
+ *
651
+ * @returns The slug of the relationship type
652
+ */
653
+ getTypeSlug(): Promise<string>;
654
+ /**
655
+ * Add a term (time period) to this relationship
656
+ *
657
+ * @param startedAt - Start date of the term
658
+ * @param endedAt - Optional end date of the term
659
+ */
660
+ addTerm(startedAt: Date, endedAt?: Date): Promise<void>;
661
+ /**
662
+ * End the current active term
663
+ *
664
+ * @param endedAt - End date for the term
665
+ */
666
+ endCurrentTerm(endedAt: Date): Promise<void>;
667
+ /**
668
+ * Get all terms for this relationship
669
+ *
670
+ * @returns Array of ProfileRelationshipTerm instances
671
+ */
672
+ getTerms(): Promise<ProfileRelationshipTerm[]>;
673
+ /**
674
+ * Get the active term (no end date)
675
+ *
676
+ * @returns Current term or null if none active
677
+ */
678
+ getActiveTerm(): Promise<ProfileRelationshipTerm | null>;
679
+ }
680
+
681
+ declare interface ProfileRelationshipOptions extends SmrtObjectOptions {
682
+ fromProfileId?: string;
683
+ toProfileId?: string;
684
+ typeId?: string;
685
+ contextProfileId?: string;
686
+ tenantId?: string | null;
687
+ }
688
+
689
+ declare class ProfileRelationshipTerm extends SmrtObject {
690
+ relationshipId?: string;
691
+ startedAt: Date;
692
+ endedAt?: Date;
693
+ constructor(options?: ProfileRelationshipTermOptions);
694
+ /**
695
+ * Check if this term is currently active
696
+ *
697
+ * @returns True if active (no end date or end date in future)
698
+ */
699
+ isActive(): boolean;
700
+ /**
701
+ * End this term
702
+ *
703
+ * @param endedAt - End date for the term (defaults to now)
704
+ */
705
+ end(endedAt?: Date): Promise<void>;
706
+ /**
707
+ * Get the duration of this term in days
708
+ *
709
+ * @returns Duration in days
710
+ */
711
+ getDurationDays(): number;
712
+ }
713
+
714
+ declare interface ProfileRelationshipTermOptions extends SmrtObjectOptions {
715
+ relationshipId?: string;
716
+ startedAt?: Date;
717
+ endedAt?: Date;
718
+ }
41
719
 
42
720
  /**
43
721
  * Set a single metadata value for a profile
@@ -47,7 +725,7 @@ export declare function getProfileMetadata(profileId: string, options?: any): Pr
47
725
  * @param value - The value to set
48
726
  * @param options - Database and configuration options
49
727
  */
50
- export declare function setProfileMetadata(profileId: string, metafieldSlug: string, value: any, options?: any): Promise<void>;
728
+ export declare function setProfileMetadata(profileId: string, metafieldSlug: string, value: unknown, options?: SmrtObjectOptions): Promise<void>;
51
729
 
52
730
  /**
53
731
  * Validate a metadata value against a metafield's validation schema
@@ -56,6 +734,33 @@ export declare function setProfileMetadata(profileId: string, metafieldSlug: str
56
734
  * @param value - The value to validate
57
735
  * @returns True if valid, throws error if invalid
58
736
  */
59
- export declare function validateMetadataValue(metafield: any, value: any): Promise<boolean>;
737
+ export declare function validateMetadataValue(metafield: ProfileMetafield, value: unknown): Promise<boolean>;
738
+
739
+ /**
740
+ * Validation schema structure for profile metadata fields
741
+ */
742
+ declare interface ValidationSchema {
743
+ /** Type constraint */
744
+ type?: 'string' | 'number' | 'boolean' | 'date' | 'json';
745
+ /** Regex pattern for string validation */
746
+ pattern?: string;
747
+ /** Minimum string length */
748
+ minLength?: number;
749
+ /** Maximum string length */
750
+ maxLength?: number;
751
+ /** Minimum numeric value */
752
+ min?: number;
753
+ /** Maximum numeric value */
754
+ max?: number;
755
+ /** Custom validator function name */
756
+ custom?: string;
757
+ /** Custom validation error message */
758
+ message?: string;
759
+ }
760
+
761
+ /**
762
+ * Custom validator function type
763
+ */
764
+ declare type ValidatorFunction = (value: unknown) => boolean | Promise<boolean>;
60
765
 
61
766
  export { }