@consenti/api 0.1.0 → 0.2.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.
package/dist/index.d.ts CHANGED
@@ -1,200 +1,27 @@
1
1
  import { EventEmitter } from 'node:events';
2
2
  import { IncomingMessage, ServerResponse } from 'node:http';
3
3
 
4
- type ConsentStatus = 'granted' | 'denied' | 'objected';
5
- type ConsentValue = Record<string, ConsentStatus>;
6
- interface Cookie {
7
- id: string;
8
- type?: 'consent' | 'legitimate_interest';
9
- mandatory?: boolean;
10
- listenGpc?: boolean;
11
- expiry?: number;
12
- tcfVendorId?: number;
13
- tcfPurposes?: number[];
14
- cpraCategory?: 'sale' | 'sharing' | 'sensitive';
15
- }
16
- type ButtonStyle = 'primary' | 'secondary' | 'text' | 'accent';
17
- type ButtonAction = 'submit' | 'manage' | 'close' | 'custom' | 'link';
18
- interface Button {
19
- text: string;
20
- style: ButtonStyle;
21
- action: ButtonAction;
22
- cookies?: string[] | '*' | '!';
23
- url?: string;
24
- }
25
- interface MainBanner {
26
- position: 'top' | 'bottom' | 'middle' | 'left-bottom' | 'right-bottom';
27
- overlayOpacity?: number;
28
- showClose?: boolean;
29
- showLocaleSwitcher?: boolean;
30
- heading?: string;
31
- headingTag?: string;
32
- htmlText: string;
33
- buttons: Button[];
34
- }
35
- type GpcBanner = MainBanner;
36
- interface Category {
37
- id: string;
38
- heading: string;
39
- headingTag?: string;
40
- htmlText: string;
41
- mandatory?: boolean;
42
- type?: 'consent' | 'legitimate_interest';
43
- legitimateInterest?: {
44
- enabled?: boolean;
45
- description?: string;
46
- };
47
- cookies: string[];
48
- }
49
- interface PreferenceModal {
50
- position?: 'left' | 'right' | 'center';
51
- overlayOpacity?: number;
52
- showClose?: boolean;
53
- showLocaleSwitcher?: boolean;
54
- heading?: string;
55
- headingTag?: string;
56
- subheading?: string;
57
- htmlText?: string;
58
- buttons: Button[];
59
- categories: Category[];
60
- persistent?: boolean;
61
- }
62
- interface LocaleTranslations {
63
- mainBanner: MainBanner;
64
- gpcBanner?: GpcBanner;
65
- preferenceModal: PreferenceModal;
66
- }
67
- interface ProfileTranslations {
68
- [locale: string]: LocaleTranslations;
69
- }
70
- interface DpdpaConfig {
71
- dataFiduciary: string;
72
- grievanceEmail: string;
73
- purposeDescription?: string;
74
- }
75
- interface LocaleTextContent {
76
- mainBanner: {
77
- heading: string;
78
- htmlText: string;
79
- buttonLabels: string[];
80
- };
81
- gpcBanner: {
82
- heading: string;
83
- htmlText: string;
84
- buttonLabels: string[];
85
- };
86
- preferenceModal: {
87
- heading: string;
88
- subheading?: string;
89
- htmlText?: string;
90
- buttonLabels: string[];
91
- categories: Array<{
92
- id: string;
93
- heading: string;
94
- htmlText: string;
95
- }>;
96
- };
97
- }
98
- interface ProfileConfig {
99
- cookies?: Cookie[];
100
- defaultLocale: string;
101
- translations?: ProfileTranslations;
102
- gpcBanner?: boolean;
103
- darkMode?: boolean;
104
- allowedOrigins?: string[];
105
- dpdpa?: DpdpaConfig;
106
- regulation?: 'gdpr' | 'ccpa' | 'cpra' | 'dpdpa' | 'uk-gdpr' | 'lgpd' | 'pipeda' | 'popia' | 'pdpa-th' | 'appi' | 'kvkk';
107
- regulations?: string[];
108
- cookieTemplateId?: string;
109
- uiTemplateId?: string;
110
- localeContents?: Record<string, LocaleTextContent>;
111
- }
112
- interface UITemplateButton {
113
- text: string;
114
- type: string;
115
- action: 'submit' | 'custom' | 'manage' | 'close' | 'link';
116
- cookies?: string | string[];
117
- url?: string;
118
- }
119
- interface UITemplateBanner {
120
- position: string;
121
- overlayOpacity: number;
122
- showClose: boolean;
123
- showLocaleSwitcher?: boolean;
124
- headingTag: string;
125
- buttons: UITemplateButton[];
126
- }
127
- interface UITemplateCategory {
128
- id: string;
129
- headingTag: string;
130
- mandatory: boolean;
131
- type: 'consent' | 'legitimate_interest';
132
- liEnabled: boolean;
133
- cookies: string[];
134
- }
135
- interface UITemplateModal extends UITemplateBanner {
136
- hasSubheading: boolean;
137
- persistent: boolean;
138
- showLocaleSwitcher?: boolean;
139
- categories: UITemplateCategory[];
140
- }
141
- interface ServerUITemplate {
142
- id: string;
143
- tenantId: string;
144
- name: string;
145
- mainBanner: UITemplateBanner;
146
- gpcBanner: UITemplateBanner;
147
- preferenceModal: UITemplateModal;
148
- createdAt: string;
149
- updatedAt: string;
150
- }
151
- interface ServerCookieTemplate {
152
- id: string;
153
- tenantId: string;
154
- name: string;
155
- cookies: Cookie[];
156
- createdAt: string;
157
- updatedAt: string;
158
- }
159
- interface CreateCookieTemplateInput {
160
- tenantId: string;
161
- name: string;
162
- cookies: Cookie[];
163
- }
164
- interface UpdateCookieTemplateInput {
165
- name?: string;
166
- cookies?: Cookie[];
167
- }
168
- interface CreateUITemplateInput {
169
- tenantId: string;
170
- name: string;
171
- mainBanner: UITemplateBanner;
172
- gpcBanner: UITemplateBanner;
173
- preferenceModal: UITemplateModal;
174
- }
175
- interface UpdateUITemplateInput {
176
- name?: string;
177
- mainBanner?: UITemplateBanner;
178
- gpcBanner?: UITemplateBanner;
179
- preferenceModal?: UITemplateModal;
180
- }
181
- interface PublicProfileResponse {
182
- id: string;
183
- version: number;
184
- defaultLocale: string;
185
- currentLocale: string;
186
- locales: string[];
187
- cookies: Cookie[];
188
- mainBanner: MainBanner;
189
- gpcBanner?: GpcBanner;
190
- preferenceModal: PreferenceModal;
191
- }
4
+ declare const COMPLIANCE_GROUP_IDS: readonly ["opt-in", "opt-out", "opt-out-strict", "opt-in-dpdpa", "opt-in-china", "opt-in-brazil", "general-privacy-consent", "notice-only"];
5
+
6
+ /**
7
+ * Compliance-related literal types, derived from the regulation/group ID data
8
+ * that lives in @consenti/utils (packages/utils/src/compliance.ts).
9
+ *
10
+ * This import is type-only and fully erased at compile time — @consenti/types
11
+ * has no runtime dependency on @consenti/utils. The actual data (COMPLIANCE_GROUPS,
12
+ * EMBEDDED_COMPLIANCE_MAP, COMPLIANCE_VALIDATION_RULES, GPC_OPTIONS, etc.) lives in
13
+ * @consenti/utils; import it from there.
14
+ *
15
+ * HOW TO ADD A NEW REGULATION OR COMPLIANCE GROUP: see the header comment in
16
+ * packages/utils/src/compliance.ts — these types auto-update from that data.
17
+ */
18
+
19
+ type ComplianceGroupId = typeof COMPLIANCE_GROUP_IDS[number];
192
20
 
193
21
  interface StorageConfig {
194
22
  driver: 'sqlite' | 'better-sqlite3' | 'node-sqlite3-wasm' | 'node:sqlite' | 'mongodb' | 'mysql' | 'postgresql' | 'json';
195
23
  path?: string;
196
24
  uri?: string;
197
- dbName?: string;
198
25
  database?: string;
199
26
  host?: string;
200
27
  port?: number;
@@ -231,10 +58,97 @@ interface RateLimitConfig {
231
58
  windowMs?: number;
232
59
  maxRequests?: number;
233
60
  }
61
+ type GeoResult = {
62
+ country: string | null;
63
+ region: string | null;
64
+ locale: string | null;
65
+ };
66
+ type CountryResolverFn = (ctx: {
67
+ ip: string;
68
+ language: string;
69
+ timezone: string;
70
+ }) => Promise<GeoResult>;
71
+ interface S3ApiConfig {
72
+ enabled: boolean;
73
+ region: string;
74
+ bucketName: string;
75
+ accessKeyId: string;
76
+ secretAccessKey: string;
77
+ sessionToken?: string;
78
+ }
79
+ interface ProfileSummary {
80
+ id: string;
81
+ name: string;
82
+ defaultLocale: string;
83
+ complianceGroup: ComplianceGroupId | null;
84
+ version: number;
85
+ isActive: boolean;
86
+ cookieTemplateName: string | null;
87
+ uiTemplateName: string | null;
88
+ createdAt: string;
89
+ updatedAt: string;
90
+ }
91
+ interface ProfileVersionEntry {
92
+ version: number;
93
+ createdAt: string;
94
+ locales: string[];
95
+ }
96
+ interface OptInFilters {
97
+ profileId?: string;
98
+ complianceGroup?: string;
99
+ from?: string;
100
+ to?: string;
101
+ locale?: string;
102
+ }
103
+ interface OptInByLocale {
104
+ total: number;
105
+ granted: number;
106
+ denied: number;
107
+ managed: number;
108
+ }
109
+ interface OptInByDate {
110
+ date: string;
111
+ total: number;
112
+ granted: number;
113
+ denied: number;
114
+ managed: number;
115
+ }
116
+ interface OptInStats {
117
+ total: number;
118
+ granted: number;
119
+ denied: number;
120
+ managed: number;
121
+ grantedPct: number;
122
+ deniedPct: number;
123
+ managedPct: number;
124
+ byLocale: Record<string, OptInByLocale>;
125
+ byDate: OptInByDate[];
126
+ }
127
+ type ComplianceMapOverride = 'default' | ComplianceMapData | 'auto';
128
+ interface ComplianceMapData {
129
+ version: string;
130
+ countries: Record<string, CountryComplianceEntry>;
131
+ }
132
+ interface CountryComplianceEntry {
133
+ complianceGroup: ComplianceGroupId;
134
+ default: ComplianceGroupId;
135
+ description: string;
136
+ overriddenRegions?: Record<string, {
137
+ complianceGroup: ComplianceGroupId;
138
+ description: string;
139
+ }>;
140
+ }
234
141
  interface ComplianceConfig {
142
+ /** @deprecated use type */
235
143
  gdpr?: boolean;
144
+ /** @deprecated use type */
236
145
  ccpa?: boolean;
237
- gpc?: boolean;
146
+ gpc?: boolean | 'strict';
147
+ type?: ComplianceGroupId | 'auto';
148
+ /** @deprecated use 'default' instead of 'language' or 'timezone'; 'geoip' and 'hosted-geoip-lite' removed */
149
+ geoDataProvider?: 'default' | 'maxmind' | 'language' | 'timezone' | 'geoip' | 'hosted-geoip-lite' | CountryResolverFn;
150
+ autoComplianceMap?: ComplianceMapOverride;
151
+ complianceMapUrl?: string;
238
152
  }
239
153
  interface DashboardConfig {
240
154
  enabled?: boolean;
@@ -256,6 +170,18 @@ interface TcfConfig {
256
170
  interface DataRetentionConfig {
257
171
  purgeAfterDays: number;
258
172
  }
173
+ interface BrandingConfig {
174
+ /** Display name shown in the dashboard (login page, header, browser tab). Default: 'Consenti'. */
175
+ appName?: string;
176
+ /**
177
+ * Logo to display in the dashboard. Accepts a public URL (https://…) or a local
178
+ * filesystem path — when a path is given, the file is copied into the dashboard
179
+ * dist and served as a static asset automatically.
180
+ */
181
+ appLogoPath?: string;
182
+ /** When true, hides the "Powered by Consenti" badge in the dashboard. Default: false. */
183
+ hidePoweredBy?: boolean;
184
+ }
259
185
  interface ConsentiServerConfig {
260
186
  basePath?: string;
261
187
  dashboard?: boolean | DashboardConfig;
@@ -270,6 +196,10 @@ interface ConsentiServerConfig {
270
196
  dataRetention?: DataRetentionConfig;
271
197
  maxBodySize?: number;
272
198
  trustedProxies?: string[];
199
+ branding?: BrandingConfig;
200
+ s3Api?: S3ApiConfig;
201
+ /** Called after every profile activate/deactivate/delete. isPurge=true means invalidate; false means warm. */
202
+ handleCache?: (paths: string[], currentVersion: number, isPurge: boolean) => void;
273
203
  }
274
204
  interface Tenant {
275
205
  id: string;
@@ -343,6 +273,8 @@ interface AdminUser {
343
273
  isActive: boolean;
344
274
  totpEnabled?: boolean;
345
275
  totpSecret?: string;
276
+ /** Empty array = access to all tenants. Non-empty = restricted to listed tenant IDs. */
277
+ allowedTenants?: string[];
346
278
  createdAt: string;
347
279
  updatedAt: string;
348
280
  }
@@ -417,6 +349,7 @@ interface CreateUserInput {
417
349
  name: string;
418
350
  email: string;
419
351
  passwordHash: string;
352
+ allowedTenants?: string[];
420
353
  }
421
354
  interface UpdateUserInput {
422
355
  name?: string;
@@ -425,6 +358,7 @@ interface UpdateUserInput {
425
358
  isActive?: boolean;
426
359
  totpSecret?: string | null;
427
360
  totpEnabled?: boolean;
361
+ allowedTenants?: string[];
428
362
  }
429
363
  interface CreateAuditLogInput {
430
364
  tenantId: string;
@@ -522,6 +456,12 @@ interface StorageAdapter {
522
456
  deleteProfile(id: string): Promise<void>;
523
457
  getProfile(id: string): Promise<Profile | null>;
524
458
  getProfiles(tenantId: string): Promise<Profile[]>;
459
+ findActiveProfileByComplianceGroup(tenantId: string, complianceGroup: string): Promise<Profile | null>;
460
+ /** Lightweight list — no profile_json blob; single JOIN for template names. */
461
+ listProfilesSummary(tenantId: string): Promise<ProfileSummary[]>;
462
+ findProfilesUsingCookieTemplate(templateId: string): Promise<ProfileSummary[]>;
463
+ findProfilesUsingUITemplate(templateId: string): Promise<ProfileSummary[]>;
464
+ getOptInStats(tenantId: string, filters: OptInFilters): Promise<OptInStats>;
525
465
  createConsent(data: CreateConsentInput): Promise<ConsentDbRecord>;
526
466
  updateConsent(visitorId: string, data: UpdateConsentInput): Promise<ConsentDbRecord>;
527
467
  deleteConsent(visitorId: string): Promise<void>;
@@ -600,6 +540,188 @@ declare abstract class ConsentiServerPlugin {
600
540
  afterUserCreate?(user: AdminUser): Promise<void>;
601
541
  }
602
542
 
543
+ type ConsentStatus = 'granted' | 'denied' | 'objected';
544
+ type ConsentValue = Record<string, ConsentStatus>;
545
+ interface Cookie {
546
+ id: string;
547
+ legalBasis?: 'mandatory' | 'consent' | 'legitimate_interest';
548
+ /** @deprecated use legalBasis: 'mandatory' */
549
+ mandatory?: boolean;
550
+ /** @deprecated use legalBasis */
551
+ type?: 'consent' | 'legitimate_interest';
552
+ listenGpc?: boolean;
553
+ expiry?: number;
554
+ tcfVendorId?: number;
555
+ tcfPurposes?: number[];
556
+ tcfSpecialFeatures?: number[];
557
+ cpraCategory?: 'sale' | 'sharing' | 'sensitive';
558
+ }
559
+ type ButtonStyle = 'primary' | 'secondary' | 'text' | 'accent';
560
+ type ButtonAction = 'submit' | 'manage' | 'close' | 'custom' | 'link';
561
+ interface Button {
562
+ text: string;
563
+ style: ButtonStyle;
564
+ action: ButtonAction;
565
+ cookies?: string[] | '*' | '!';
566
+ url?: string;
567
+ type?: string;
568
+ }
569
+ interface MainBanner {
570
+ position: 'top' | 'bottom' | 'middle' | 'left-bottom' | 'right-bottom';
571
+ overlayOpacity?: number;
572
+ showClose?: boolean;
573
+ showLocaleSwitcher?: boolean;
574
+ heading?: string;
575
+ headingTag?: string;
576
+ htmlText: string;
577
+ buttons: Button[];
578
+ }
579
+ type GpcBanner = MainBanner;
580
+ interface Category {
581
+ id: string;
582
+ heading: string;
583
+ headingTag?: string;
584
+ htmlText: string;
585
+ mandatory?: boolean;
586
+ type?: 'consent' | 'legitimate_interest';
587
+ legitimateInterest?: {
588
+ enabled?: boolean;
589
+ description?: string;
590
+ };
591
+ cookies: string[];
592
+ }
593
+ interface PreferenceModal extends Omit<MainBanner, "position"> {
594
+ position?: 'left' | 'right' | 'center';
595
+ subheading?: string;
596
+ categories: Category[];
597
+ persistent?: boolean;
598
+ /** Screen width in px below which the modal expands to full screen. Default: 576. Set to 0 to disable. */
599
+ mobileFullScreenBreakpoint?: number;
600
+ }
601
+ interface LocaleTranslations {
602
+ mainBanner: MainBanner;
603
+ gpcBanner?: GpcBanner;
604
+ preferenceModal: PreferenceModal;
605
+ }
606
+ interface ProfileTranslations {
607
+ [locale: string]: LocaleTranslations;
608
+ }
609
+ interface DpdpaConfig {
610
+ dataFiduciary: string;
611
+ grievanceEmail: string;
612
+ purposeDescription?: string;
613
+ }
614
+ interface LocaleTextContent {
615
+ mainBanner: {
616
+ heading?: string;
617
+ htmlText: string;
618
+ buttonLabels?: string[];
619
+ };
620
+ gpcBanner: {
621
+ heading?: string;
622
+ htmlText: string;
623
+ buttonLabels?: string[];
624
+ };
625
+ preferenceModal: {
626
+ heading: string;
627
+ subheading?: string;
628
+ htmlText?: string;
629
+ buttonLabels?: string[];
630
+ categories: {
631
+ id: string;
632
+ heading: string;
633
+ htmlText: string;
634
+ }[];
635
+ };
636
+ }
637
+ interface ProfileConfig {
638
+ cookies?: Cookie[];
639
+ defaultLocale: string;
640
+ translations?: ProfileTranslations;
641
+ gpcBanner?: boolean;
642
+ darkMode?: boolean;
643
+ allowedOrigins?: string[];
644
+ dpdpa?: DpdpaConfig;
645
+ regulation?: 'gdpr' | 'ccpa' | 'cpra' | 'dpdpa' | 'uk-gdpr' | 'lgpd' | 'pipeda' | 'popia' | 'pdpa-th' | 'appi' | 'kvkk';
646
+ regulations?: string[];
647
+ cookieTemplateId?: string;
648
+ uiTemplateId?: string;
649
+ localeContents?: Record<string, LocaleTextContent>;
650
+ complianceGroup?: string;
651
+ /** @deprecated use gpcMode */
652
+ gpcCompliance?: 'strict' | 'honor' | 'ignore';
653
+ gpcMode?: 'ignore' | 'honor' | 'strict';
654
+ isActive?: boolean;
655
+ hidePoweredBy?: boolean;
656
+ allowReceipt?: boolean;
657
+ /** Per-compliance extra config (e.g. DPDPA data fiduciary name). */
658
+ complianceConfig?: Record<string, string>;
659
+ }
660
+ interface ServerUITemplate {
661
+ id: string;
662
+ tenantId: string;
663
+ name: string;
664
+ mainBanner: MainBanner;
665
+ gpcBanner: GpcBanner;
666
+ preferenceModal: PreferenceModal;
667
+ createdAt: string;
668
+ updatedAt: string;
669
+ }
670
+ interface ServerCookieTemplate {
671
+ id: string;
672
+ tenantId: string;
673
+ name: string;
674
+ cookies: Cookie[];
675
+ createdAt: string;
676
+ updatedAt: string;
677
+ }
678
+ interface CreateCookieTemplateInput {
679
+ tenantId: string;
680
+ name: string;
681
+ cookies: Cookie[];
682
+ }
683
+ interface UpdateCookieTemplateInput {
684
+ name?: string;
685
+ cookies?: Cookie[];
686
+ }
687
+ interface CreateUITemplateInput {
688
+ tenantId: string;
689
+ name: string;
690
+ mainBanner: MainBanner;
691
+ gpcBanner: MainBanner;
692
+ preferenceModal: PreferenceModal;
693
+ }
694
+ interface UpdateUITemplateInput {
695
+ name?: string;
696
+ mainBanner?: MainBanner;
697
+ gpcBanner?: MainBanner;
698
+ preferenceModal?: PreferenceModal;
699
+ }
700
+ interface PublicProfileResponse {
701
+ id: string;
702
+ name?: string;
703
+ tenantId?: string;
704
+ version: number;
705
+ defaultLocale: string;
706
+ currentLocale: string;
707
+ locales: string[];
708
+ cookies: Cookie[];
709
+ mainBanner: MainBanner;
710
+ gpcBanner?: GpcBanner;
711
+ preferenceModal: PreferenceModal;
712
+ resolvedComplianceGroup?: string;
713
+ complianceGroup?: string;
714
+ compliances?: string[];
715
+ complianceConfig?: Record<string, string>;
716
+ allowedOrigins?: string[];
717
+ gpcMode?: boolean | 'ignore' | 'honor' | 'strict';
718
+ hidePoweredBy?: boolean;
719
+ allowReceipt?: boolean;
720
+ darkMode?: boolean;
721
+ createdAt?: string;
722
+ updatedAt?: string;
723
+ }
724
+
603
725
  declare class ProfileRepo {
604
726
  private adapter;
605
727
  constructor(adapter: StorageAdapter);
@@ -608,6 +730,7 @@ declare class ProfileRepo {
608
730
  delete(id: string): Promise<void>;
609
731
  get(id: string): Promise<Profile | null>;
610
732
  list(tenantId: string): Promise<Profile[]>;
733
+ findActiveByComplianceGroup(tenantId: string, complianceGroup: string): Promise<Profile | null>;
611
734
  }
612
735
 
613
736
  declare class AuditRepo {
@@ -617,18 +740,43 @@ declare class AuditRepo {
617
740
  list(filters: AuditFilters): Promise<AuditLog[]>;
618
741
  }
619
742
 
743
+ declare class LocaleJsonCacheService {
744
+ private readonly dir;
745
+ constructor(dir: string);
746
+ read(profileId: string, locale: string): PublicProfileResponse | null;
747
+ write(profileId: string, locale: string, response: PublicProfileResponse): void;
748
+ rebuild(profileId: string, responses: Map<string, PublicProfileResponse>): void;
749
+ invalidate(profileId: string): void;
750
+ private path;
751
+ }
752
+
620
753
  declare class ProfileService {
621
754
  private profiles;
622
755
  private audit;
623
756
  private tenantId;
624
757
  private storage?;
625
- constructor(profiles: ProfileRepo, audit: AuditRepo, tenantId?: string, storage?: StorageAdapter | undefined);
758
+ private eventBus?;
759
+ private localeCache?;
760
+ private profilesDir?;
761
+ private handleCache?;
762
+ private s3Config?;
763
+ constructor(profiles: ProfileRepo, audit: AuditRepo, tenantId?: string, storage?: StorageAdapter | undefined, eventBus?: EventEmitter | undefined, localeCache?: LocaleJsonCacheService | undefined, profilesDir?: string | undefined, handleCache?: ((paths: string[], version: number, isPurge: boolean) => void) | undefined, s3Config?: S3ApiConfig | undefined);
764
+ private profileDir;
765
+ private complianceGroupDir;
766
+ private profileFilePaths;
626
767
  create(input: Omit<CreateProfileInput, 'tenantId'>): Promise<Profile>;
627
768
  update(id: string, input: UpdateProfileInput): Promise<Profile>;
628
769
  delete(id: string): Promise<void>;
770
+ activate(id: string): Promise<Profile>;
771
+ deactivate(id: string): Promise<Profile>;
772
+ private runWrite;
629
773
  get(id: string, locale?: string): Promise<Profile | null>;
630
774
  getResolved(id: string, locale?: string): Promise<PublicProfileResponse | null>;
775
+ findActiveByComplianceGroup(complianceGroup: string): Promise<Profile | null>;
631
776
  list(): Promise<Profile[]>;
777
+ listSummary(): Promise<ProfileSummary[]>;
778
+ listVersions(profileId: string): ProfileVersionEntry[];
779
+ getVersionFile(profileId: string, version: number, locale: string): string | null;
632
780
  }
633
781
 
634
782
  declare class ConsentRepo {
@@ -685,7 +833,8 @@ declare class ConsentService {
685
833
  declare class VisitorService {
686
834
  private visitors;
687
835
  private tenantId;
688
- constructor(visitors: VisitorRepo, tenantId?: string);
836
+ private eventBus?;
837
+ constructor(visitors: VisitorRepo, tenantId?: string, eventBus?: EventEmitter | undefined);
689
838
  upsert(data: {
690
839
  visitorId: string;
691
840
  ip?: string;
@@ -721,12 +870,14 @@ declare class UserService {
721
870
  email: string;
722
871
  password: string;
723
872
  roleId?: string;
873
+ allowedTenants?: string[];
724
874
  }, actorId?: string): Promise<SafeAdminUser>;
725
875
  update(id: string, input: {
726
876
  name?: string;
727
877
  email?: string;
728
878
  isActive?: boolean;
729
879
  password?: string;
880
+ allowedTenants?: string[];
730
881
  }, actorId?: string): Promise<SafeAdminUser>;
731
882
  delete(id: string, actorId?: string): Promise<void>;
732
883
  get(id: string): Promise<SafeAdminUser | null>;
@@ -751,6 +902,7 @@ declare class BetterSqlite3Adapter implements StorageAdapter {
751
902
  deleteProfile(id: string): Promise<void>;
752
903
  getProfile(id: string): Promise<Profile | null>;
753
904
  getProfiles(tenantId: string): Promise<Profile[]>;
905
+ findActiveProfileByComplianceGroup(tenantId: string, complianceGroup: string): Promise<Profile | null>;
754
906
  private mapConsent;
755
907
  createConsent(data: CreateConsentInput): Promise<ConsentDbRecord>;
756
908
  updateConsent(visitorId: string, data: UpdateConsentInput): Promise<ConsentDbRecord>;
@@ -817,6 +969,12 @@ declare class BetterSqlite3Adapter implements StorageAdapter {
817
969
  getUITemplate(id: string): Promise<ServerUITemplate | null>;
818
970
  getUITemplates(tenantId: string): Promise<ServerUITemplate[]>;
819
971
  copyUITemplate(id: string, newName: string): Promise<ServerUITemplate>;
972
+ private mapProfileSummary;
973
+ private readonly PROFILE_SUMMARY_SQL;
974
+ listProfilesSummary(tenantId: string): Promise<ProfileSummary[]>;
975
+ findProfilesUsingCookieTemplate(templateId: string): Promise<ProfileSummary[]>;
976
+ findProfilesUsingUITemplate(templateId: string): Promise<ProfileSummary[]>;
977
+ getOptInStats(tenantId: string, filters: OptInFilters): Promise<OptInStats>;
820
978
  }
821
979
 
822
980
  declare class MongoDBAdapter implements StorageAdapter {
@@ -835,6 +993,7 @@ declare class MongoDBAdapter implements StorageAdapter {
835
993
  deleteProfile(id: string): Promise<void>;
836
994
  getProfile(id: string): Promise<Profile | null>;
837
995
  getProfiles(tenantId: string): Promise<Profile[]>;
996
+ findActiveProfileByComplianceGroup(tenantId: string, complianceGroup: string): Promise<Profile | null>;
838
997
  createConsent(data: CreateConsentInput): Promise<ConsentDbRecord>;
839
998
  updateConsent(visitorId: string, data: UpdateConsentInput): Promise<ConsentDbRecord>;
840
999
  deleteConsent(visitorId: string): Promise<void>;
@@ -897,6 +1056,10 @@ declare class MongoDBAdapter implements StorageAdapter {
897
1056
  getUITemplate(): Promise<never>;
898
1057
  getUITemplates(): Promise<never>;
899
1058
  copyUITemplate(): Promise<never>;
1059
+ listProfilesSummary(): Promise<never[]>;
1060
+ findProfilesUsingCookieTemplate(): Promise<never[]>;
1061
+ findProfilesUsingUITemplate(): Promise<never[]>;
1062
+ getOptInStats(): Promise<never>;
900
1063
  }
901
1064
 
902
1065
  declare class MySQLAdapter implements StorageAdapter {
@@ -914,6 +1077,7 @@ declare class MySQLAdapter implements StorageAdapter {
914
1077
  deleteProfile(id: string): Promise<void>;
915
1078
  getProfile(id: string): Promise<Profile | null>;
916
1079
  getProfiles(tenantId: string): Promise<Profile[]>;
1080
+ findActiveProfileByComplianceGroup(tenantId: string, complianceGroup: string): Promise<Profile | null>;
917
1081
  createConsent(data: CreateConsentInput): Promise<ConsentDbRecord>;
918
1082
  updateConsent(visitorId: string, data: UpdateConsentInput): Promise<ConsentDbRecord>;
919
1083
  deleteConsent(visitorId: string): Promise<void>;
@@ -976,6 +1140,10 @@ declare class MySQLAdapter implements StorageAdapter {
976
1140
  getUITemplate(): Promise<never>;
977
1141
  getUITemplates(): Promise<never>;
978
1142
  copyUITemplate(): Promise<never>;
1143
+ listProfilesSummary(): Promise<never[]>;
1144
+ findProfilesUsingCookieTemplate(): Promise<never[]>;
1145
+ findProfilesUsingUITemplate(): Promise<never[]>;
1146
+ getOptInStats(): Promise<never>;
979
1147
  }
980
1148
 
981
1149
  declare class PostgreSQLAdapter implements StorageAdapter {
@@ -992,6 +1160,7 @@ declare class PostgreSQLAdapter implements StorageAdapter {
992
1160
  deleteProfile(id: string): Promise<void>;
993
1161
  getProfile(id: string): Promise<Profile | null>;
994
1162
  getProfiles(tenantId: string): Promise<Profile[]>;
1163
+ findActiveProfileByComplianceGroup(tenantId: string, complianceGroup: string): Promise<Profile | null>;
995
1164
  createConsent(data: CreateConsentInput): Promise<ConsentDbRecord>;
996
1165
  updateConsent(visitorId: string, data: UpdateConsentInput): Promise<ConsentDbRecord>;
997
1166
  deleteConsent(visitorId: string): Promise<void>;
@@ -1054,13 +1223,17 @@ declare class PostgreSQLAdapter implements StorageAdapter {
1054
1223
  getUITemplate(): Promise<never>;
1055
1224
  getUITemplates(): Promise<never>;
1056
1225
  copyUITemplate(): Promise<never>;
1226
+ listProfilesSummary(): Promise<never[]>;
1227
+ findProfilesUsingCookieTemplate(): Promise<never[]>;
1228
+ findProfilesUsingUITemplate(): Promise<never[]>;
1229
+ getOptInStats(): Promise<never>;
1057
1230
  }
1058
1231
 
1059
1232
  declare const dashboardDir: string;
1060
1233
  declare function createConsenti(userConfig: ConsentiServerConfig): {
1061
1234
  router: (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void;
1062
1235
  handler: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
1063
- fastifyPlugin: (fastify: {
1236
+ fastifyHandler: (fastify: {
1064
1237
  all: (path: string, handler: (req: {
1065
1238
  raw: IncomingMessage;
1066
1239
  }, reply: {
@@ -1078,8 +1251,9 @@ declare function createConsenti(userConfig: ConsentiServerConfig): {
1078
1251
  user: UserService;
1079
1252
  };
1080
1253
  storage: StorageAdapter;
1081
- eventBus: EventEmitter<[never]>;
1254
+ eventBus: EventEmitter<any>;
1255
+ ready: Promise<void>;
1082
1256
  destroy: () => Promise<void>;
1083
1257
  };
1084
1258
 
1085
- export { type AdminUser, type AuditLog, type ConsentDbRecord, type ConsentVerifyResult, type ConsentiServerConfig, MongoDBAdapter, MySQLAdapter, type Permission, PostgreSQLAdapter, type Profile, type Role, BetterSqlite3Adapter as SQLiteAdapter, type SafeAdminUser, type StorageAdapter, type Visitor, createConsenti, dashboardDir };
1259
+ export { type AdminUser, type AuditLog, type BrandingConfig, type ConsentDbRecord, type ConsentVerifyResult, type ConsentiServerConfig, MongoDBAdapter, MySQLAdapter, type Permission, PostgreSQLAdapter, type Profile, type Role, BetterSqlite3Adapter as SQLiteAdapter, type SafeAdminUser, type StorageAdapter, type Visitor, createConsenti, dashboardDir };