@c15t/backend 2.0.0-rc.5 → 2.0.0-rc.6
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/302.js +473 -0
- package/dist/364.js +1140 -0
- package/dist/583.js +540 -0
- package/dist/cache.cjs +1 -1
- package/dist/cache.js +4 -415
- package/dist/core.cjs +21 -24
- package/dist/core.js +18 -2420
- package/dist/db/adapters/drizzle.cjs +1 -1
- package/dist/db/adapters/drizzle.js +1 -2
- package/dist/db/adapters/kysely.cjs +1 -1
- package/dist/db/adapters/kysely.js +1 -2
- package/dist/db/adapters/mongo.cjs +1 -1
- package/dist/db/adapters/mongo.js +1 -2
- package/dist/db/adapters/prisma.cjs +1 -1
- package/dist/db/adapters/prisma.js +1 -2
- package/dist/db/adapters/typeorm.cjs +1 -1
- package/dist/db/adapters/typeorm.js +1 -2
- package/dist/db/adapters.cjs +1 -1
- package/dist/db/migrator.cjs +1 -1
- package/dist/db/schema.cjs +1 -1
- package/dist/db/schema.js +1 -1
- package/dist/define-config.cjs +1 -1
- package/dist/edge.cjs +1 -1
- package/dist/edge.js +3 -882
- package/dist/router.cjs +17 -18
- package/dist/router.js +1 -2058
- package/dist/types/index.cjs +1 -1
- package/dist-types/cache/gvl-resolver.d.ts +1 -1
- package/dist-types/db/registry/runtime-policy-decision.d.ts +1 -1
- package/dist-types/db/schema/1.0.0/consent.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/audit-log.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/consent-policy.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/consent-purpose.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/consent.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/domain.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +1 -1
- package/dist-types/db/schema/2.0.0/subject.d.ts +1 -1
- package/dist-types/handlers/init/index.d.ts +1 -1
- package/dist-types/handlers/init/policy.d.ts +1 -1
- package/dist-types/handlers/init/resolve-init.d.ts +1 -1
- package/dist-types/handlers/policy/snapshot.d.ts +1 -1
- package/dist-types/policies/defaults.d.ts +1 -1
- package/dist-types/policies/matchers.d.ts +2 -2
- package/dist-types/types/index.d.ts +2 -2
- package/dist-types/version.d.ts +1 -1
- package/docs/guides/policy-packs.md +1 -1
- package/package.json +15 -15
package/dist/583.js
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
import { inspectPolicies, resolvePolicyDecision, resolvePolicySync, validatePolicyI18nConfig } from "@c15t/schema/types";
|
|
2
|
+
import { deepMergeTranslations, selectLanguage } from "@c15t/translations";
|
|
3
|
+
import { baseTranslations } from "@c15t/translations/all";
|
|
4
|
+
import { SignJWT, errors, jwtVerify } from "jose";
|
|
5
|
+
import { createGVLResolver, getMetrics } from "./302.js";
|
|
6
|
+
const DEFAULT_PROFILE = 'default';
|
|
7
|
+
const warnedKeys = new Set();
|
|
8
|
+
function isSupportedBaseLanguage(lang) {
|
|
9
|
+
return lang in baseTranslations;
|
|
10
|
+
}
|
|
11
|
+
function warnOnce(logger, key, message, metadata) {
|
|
12
|
+
if (!logger || warnedKeys.has(key)) return;
|
|
13
|
+
warnedKeys.add(key);
|
|
14
|
+
logger.warn(message, metadata);
|
|
15
|
+
}
|
|
16
|
+
function normalizeLanguage(value) {
|
|
17
|
+
if (!value) return;
|
|
18
|
+
const normalized = value.split(',')[0]?.split(';')[0]?.trim().toLowerCase();
|
|
19
|
+
if (!normalized) return;
|
|
20
|
+
return normalized.split('-')[0] ?? void 0;
|
|
21
|
+
}
|
|
22
|
+
function normalizeProfiles(params) {
|
|
23
|
+
const profiles = params.i18n?.messages;
|
|
24
|
+
const legacy = params.customTranslations;
|
|
25
|
+
if (profiles && Object.keys(profiles).length > 0) {
|
|
26
|
+
if (legacy && Object.keys(legacy).length > 0) warnOnce(params.logger, 'i18n.customTranslations.ignored', '`customTranslations` is deprecated and ignored when `i18n.messages` is configured.');
|
|
27
|
+
return profiles;
|
|
28
|
+
}
|
|
29
|
+
if (legacy && Object.keys(legacy).length > 0) {
|
|
30
|
+
warnOnce(params.logger, 'i18n.customTranslations.deprecated', '`customTranslations` is deprecated. Use `i18n.messages` instead.');
|
|
31
|
+
return {
|
|
32
|
+
[DEFAULT_PROFILE]: {
|
|
33
|
+
translations: legacy
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
function buildCandidates(input) {
|
|
40
|
+
const raw = [
|
|
41
|
+
{
|
|
42
|
+
language: input.language,
|
|
43
|
+
reason: 'profile_language'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
language: input.fallbackLanguage,
|
|
47
|
+
reason: 'profile_fallback'
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
const dedupe = new Set();
|
|
51
|
+
return raw.filter((candidate)=>{
|
|
52
|
+
const key = candidate.language;
|
|
53
|
+
if (dedupe.has(key)) return false;
|
|
54
|
+
dedupe.add(key);
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function getProfileLanguages(profiles, profile) {
|
|
59
|
+
return Object.keys(profiles[profile]?.translations ?? {}).sort();
|
|
60
|
+
}
|
|
61
|
+
function getSelectableLanguages(input) {
|
|
62
|
+
return getProfileLanguages(input.profiles, input.profile);
|
|
63
|
+
}
|
|
64
|
+
function resolveFallbackLanguage(input) {
|
|
65
|
+
const configuredFallbackLanguage = normalizeLanguage(input.profile?.fallbackLanguage) ?? 'en';
|
|
66
|
+
const profileLanguages = Object.keys(input.profile?.translations ?? {}).sort();
|
|
67
|
+
if (profileLanguages.includes(configuredFallbackLanguage)) return configuredFallbackLanguage;
|
|
68
|
+
if (profileLanguages.includes('en')) return 'en';
|
|
69
|
+
return profileLanguages[0] ?? configuredFallbackLanguage;
|
|
70
|
+
}
|
|
71
|
+
function resolveActiveProfile(input) {
|
|
72
|
+
const requestedProfile = input.policyProfile ?? input.defaultProfile;
|
|
73
|
+
if (input.profiles[requestedProfile]) return requestedProfile;
|
|
74
|
+
if (input.policyProfile) warnOnce(input.logger, `i18n.profile.missing:${requestedProfile}`, `Policy i18n profile '${requestedProfile}' does not exist. Falling back to default profile '${input.defaultProfile}'.`);
|
|
75
|
+
return input.defaultProfile;
|
|
76
|
+
}
|
|
77
|
+
function validateMessages(options) {
|
|
78
|
+
return validatePolicyI18nConfig({
|
|
79
|
+
customTranslations: options.customTranslations,
|
|
80
|
+
i18n: options.i18n,
|
|
81
|
+
policies: options.policies
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function getTranslationsData(acceptLanguage, customTranslations, options) {
|
|
85
|
+
const profiles = normalizeProfiles({
|
|
86
|
+
customTranslations,
|
|
87
|
+
i18n: options?.i18n,
|
|
88
|
+
logger: options?.logger
|
|
89
|
+
});
|
|
90
|
+
const defaultProfile = options?.i18n?.defaultProfile ?? DEFAULT_PROFILE;
|
|
91
|
+
const profile = resolveActiveProfile({
|
|
92
|
+
profiles,
|
|
93
|
+
defaultProfile,
|
|
94
|
+
policyProfile: options?.policyI18n?.messageProfile,
|
|
95
|
+
logger: options?.logger
|
|
96
|
+
});
|
|
97
|
+
const configuredLanguages = Object.keys(profiles).length > 0 ? getSelectableLanguages({
|
|
98
|
+
profiles,
|
|
99
|
+
profile
|
|
100
|
+
}) : Object.keys(baseTranslations);
|
|
101
|
+
const fallbackLanguage = Object.keys(profiles).length > 0 ? resolveFallbackLanguage({
|
|
102
|
+
profile: profiles[profile]
|
|
103
|
+
}) : 'en';
|
|
104
|
+
const policyLanguage = normalizeLanguage(options?.policyI18n?.language);
|
|
105
|
+
const requestedLanguage = policyLanguage ?? selectLanguage(configuredLanguages, {
|
|
106
|
+
header: acceptLanguage,
|
|
107
|
+
fallback: fallbackLanguage
|
|
108
|
+
});
|
|
109
|
+
const candidates = buildCandidates({
|
|
110
|
+
language: requestedLanguage,
|
|
111
|
+
fallbackLanguage
|
|
112
|
+
});
|
|
113
|
+
const selectedCandidate = candidates.find((candidate)=>!!profiles[profile]?.translations[candidate.language]);
|
|
114
|
+
if (selectedCandidate && 'profile_language' !== selectedCandidate.reason) warnOnce(options?.logger, `i18n.fallback:${profile}:${requestedLanguage}:${selectedCandidate.language}`, `Policy translation fallback used (${selectedCandidate.reason}).`, {
|
|
115
|
+
requestedProfile: profile,
|
|
116
|
+
requestedLanguage,
|
|
117
|
+
resolvedProfile: profile,
|
|
118
|
+
resolvedLanguage: selectedCandidate.language
|
|
119
|
+
});
|
|
120
|
+
let language = selectedCandidate?.language ?? requestedLanguage;
|
|
121
|
+
if (!selectedCandidate && !isSupportedBaseLanguage(language)) {
|
|
122
|
+
warnOnce(options?.logger, `i18n.base-fallback:${language}`, `No translation found for '${language}'. Falling back to base English translations.`);
|
|
123
|
+
language = 'en';
|
|
124
|
+
}
|
|
125
|
+
const base = isSupportedBaseLanguage(language) ? baseTranslations[language] : baseTranslations.en;
|
|
126
|
+
const custom = selectedCandidate ? profiles[profile]?.translations[selectedCandidate.language] : void 0;
|
|
127
|
+
const translations = custom ? deepMergeTranslations(base, custom) : base;
|
|
128
|
+
return {
|
|
129
|
+
translations: translations,
|
|
130
|
+
language
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function policy_inspectPolicies(policies, options) {
|
|
134
|
+
return inspectPolicies(policies, options);
|
|
135
|
+
}
|
|
136
|
+
async function policy_resolvePolicyDecision(params) {
|
|
137
|
+
return resolvePolicyDecision({
|
|
138
|
+
policies: params.policies,
|
|
139
|
+
countryCode: params.countryCode,
|
|
140
|
+
regionCode: params.regionCode,
|
|
141
|
+
jurisdiction: params.jurisdiction,
|
|
142
|
+
iabEnabled: params.iabEnabled
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function policy_resolvePolicySync(params) {
|
|
146
|
+
return resolvePolicySync({
|
|
147
|
+
policies: params.policies,
|
|
148
|
+
countryCode: params.countryCode,
|
|
149
|
+
regionCode: params.regionCode,
|
|
150
|
+
jurisdiction: params.jurisdiction,
|
|
151
|
+
iabEnabled: params.iabEnabled
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
const POLICY_SNAPSHOT_JWT_HEADER = {
|
|
155
|
+
alg: 'HS256',
|
|
156
|
+
typ: 'JWT'
|
|
157
|
+
};
|
|
158
|
+
const DEFAULT_POLICY_SNAPSHOT_ISSUER = 'c15t';
|
|
159
|
+
const DEFAULT_POLICY_SNAPSHOT_AUDIENCE = 'c15t-policy-snapshot';
|
|
160
|
+
function resolveSnapshotIssuer(options) {
|
|
161
|
+
return options?.issuer?.trim() || DEFAULT_POLICY_SNAPSHOT_ISSUER;
|
|
162
|
+
}
|
|
163
|
+
function resolveSnapshotAudience(params) {
|
|
164
|
+
const configuredAudience = params.options?.audience?.trim();
|
|
165
|
+
if (configuredAudience) return configuredAudience;
|
|
166
|
+
return params.tenantId ? `${DEFAULT_POLICY_SNAPSHOT_AUDIENCE}:${params.tenantId}` : DEFAULT_POLICY_SNAPSHOT_AUDIENCE;
|
|
167
|
+
}
|
|
168
|
+
function getSigningKey(secret) {
|
|
169
|
+
return new TextEncoder().encode(secret);
|
|
170
|
+
}
|
|
171
|
+
function isPolicySnapshotPayload(payload) {
|
|
172
|
+
return 'string' == typeof payload.policyId && 'string' == typeof payload.fingerprint && 'string' == typeof payload.matchedBy && 'string' == typeof payload.jurisdiction && 'string' == typeof payload.model && 'string' == typeof payload.iss && 'string' == typeof payload.aud && 'string' == typeof payload.sub && 'number' == typeof payload.iat && 'number' == typeof payload.exp;
|
|
173
|
+
}
|
|
174
|
+
async function createPolicySnapshotToken(params) {
|
|
175
|
+
const { options } = params;
|
|
176
|
+
if (!options?.signingKey) return;
|
|
177
|
+
const iat = Math.floor(Date.now() / 1000);
|
|
178
|
+
const ttlSeconds = options.ttlSeconds ?? 1800;
|
|
179
|
+
const exp = iat + ttlSeconds;
|
|
180
|
+
const iss = resolveSnapshotIssuer(options);
|
|
181
|
+
const aud = resolveSnapshotAudience({
|
|
182
|
+
options,
|
|
183
|
+
tenantId: params.tenantId
|
|
184
|
+
});
|
|
185
|
+
const payload = {
|
|
186
|
+
iss,
|
|
187
|
+
aud,
|
|
188
|
+
sub: params.policyId,
|
|
189
|
+
tenantId: params.tenantId,
|
|
190
|
+
policyId: params.policyId,
|
|
191
|
+
fingerprint: params.fingerprint,
|
|
192
|
+
matchedBy: params.matchedBy,
|
|
193
|
+
country: params.country,
|
|
194
|
+
region: params.region,
|
|
195
|
+
jurisdiction: params.jurisdiction,
|
|
196
|
+
language: params.language,
|
|
197
|
+
model: params.model,
|
|
198
|
+
policyI18n: params.policyI18n,
|
|
199
|
+
expiryDays: params.expiryDays,
|
|
200
|
+
scopeMode: params.scopeMode,
|
|
201
|
+
uiMode: params.uiMode,
|
|
202
|
+
bannerUi: params.bannerUi,
|
|
203
|
+
dialogUi: params.dialogUi,
|
|
204
|
+
categories: params.categories,
|
|
205
|
+
preselectedCategories: params.preselectedCategories,
|
|
206
|
+
gpc: params.gpc,
|
|
207
|
+
proofConfig: params.proofConfig,
|
|
208
|
+
iat,
|
|
209
|
+
exp
|
|
210
|
+
};
|
|
211
|
+
const token = await new SignJWT(payload).setProtectedHeader(POLICY_SNAPSHOT_JWT_HEADER).setIssuedAt(iat).setExpirationTime(exp).sign(getSigningKey(options.signingKey));
|
|
212
|
+
return {
|
|
213
|
+
token,
|
|
214
|
+
payload
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
async function verifyPolicySnapshotToken(params) {
|
|
218
|
+
const { token, options, tenantId } = params;
|
|
219
|
+
if (!options?.signingKey) return {
|
|
220
|
+
valid: false,
|
|
221
|
+
reason: 'missing'
|
|
222
|
+
};
|
|
223
|
+
if (!token) return {
|
|
224
|
+
valid: false,
|
|
225
|
+
reason: 'missing'
|
|
226
|
+
};
|
|
227
|
+
if (3 !== token.split('.').length) return {
|
|
228
|
+
valid: false,
|
|
229
|
+
reason: 'malformed'
|
|
230
|
+
};
|
|
231
|
+
try {
|
|
232
|
+
const { payload, protectedHeader } = await jwtVerify(token, getSigningKey(options.signingKey), {
|
|
233
|
+
issuer: resolveSnapshotIssuer(options),
|
|
234
|
+
audience: resolveSnapshotAudience({
|
|
235
|
+
options,
|
|
236
|
+
tenantId
|
|
237
|
+
})
|
|
238
|
+
});
|
|
239
|
+
const header = protectedHeader;
|
|
240
|
+
if ('HS256' !== header.alg || 'JWT' !== header.typ) return {
|
|
241
|
+
valid: false,
|
|
242
|
+
reason: 'invalid'
|
|
243
|
+
};
|
|
244
|
+
if (!isPolicySnapshotPayload(payload)) return {
|
|
245
|
+
valid: false,
|
|
246
|
+
reason: 'invalid'
|
|
247
|
+
};
|
|
248
|
+
if (payload.sub !== payload.policyId) return {
|
|
249
|
+
valid: false,
|
|
250
|
+
reason: 'invalid'
|
|
251
|
+
};
|
|
252
|
+
if ((tenantId ?? void 0) !== (payload.tenantId ?? void 0)) return {
|
|
253
|
+
valid: false,
|
|
254
|
+
reason: 'invalid'
|
|
255
|
+
};
|
|
256
|
+
return {
|
|
257
|
+
valid: true,
|
|
258
|
+
payload
|
|
259
|
+
};
|
|
260
|
+
} catch (error) {
|
|
261
|
+
if (error instanceof errors.JWTExpired) return {
|
|
262
|
+
valid: false,
|
|
263
|
+
reason: 'expired'
|
|
264
|
+
};
|
|
265
|
+
return {
|
|
266
|
+
valid: false,
|
|
267
|
+
reason: 'invalid'
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function normalizeHeader(value) {
|
|
272
|
+
if (!value) return null;
|
|
273
|
+
return Array.isArray(value) ? value[0] ?? null : value;
|
|
274
|
+
}
|
|
275
|
+
function getGeoHeaders(headers) {
|
|
276
|
+
const countryCode = normalizeHeader(headers.get('x-c15t-country')) ?? normalizeHeader(headers.get('cf-ipcountry')) ?? normalizeHeader(headers.get('x-vercel-ip-country')) ?? normalizeHeader(headers.get('x-amz-cf-ipcountry')) ?? normalizeHeader(headers.get('x-country-code'));
|
|
277
|
+
const regionCode = normalizeHeader(headers.get('x-c15t-region')) ?? normalizeHeader(headers.get('x-vercel-ip-country-region')) ?? normalizeHeader(headers.get('x-region-code'));
|
|
278
|
+
return {
|
|
279
|
+
countryCode,
|
|
280
|
+
regionCode
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function checkJurisdiction(countryCode, regionCode) {
|
|
284
|
+
const jurisdictions = {
|
|
285
|
+
EU: new Set([
|
|
286
|
+
'AT',
|
|
287
|
+
'BE',
|
|
288
|
+
'BG',
|
|
289
|
+
'HR',
|
|
290
|
+
'CY',
|
|
291
|
+
'CZ',
|
|
292
|
+
'DK',
|
|
293
|
+
'EE',
|
|
294
|
+
'FI',
|
|
295
|
+
'FR',
|
|
296
|
+
'DE',
|
|
297
|
+
'GR',
|
|
298
|
+
'HU',
|
|
299
|
+
'IE',
|
|
300
|
+
'IT',
|
|
301
|
+
'LV',
|
|
302
|
+
'LT',
|
|
303
|
+
'LU',
|
|
304
|
+
'MT',
|
|
305
|
+
'NL',
|
|
306
|
+
'PL',
|
|
307
|
+
'PT',
|
|
308
|
+
'RO',
|
|
309
|
+
'SK',
|
|
310
|
+
'SI',
|
|
311
|
+
'ES',
|
|
312
|
+
'SE'
|
|
313
|
+
]),
|
|
314
|
+
EEA: new Set([
|
|
315
|
+
'IS',
|
|
316
|
+
'NO',
|
|
317
|
+
'LI'
|
|
318
|
+
]),
|
|
319
|
+
UK: new Set([
|
|
320
|
+
'GB'
|
|
321
|
+
]),
|
|
322
|
+
CH: new Set([
|
|
323
|
+
'CH'
|
|
324
|
+
]),
|
|
325
|
+
BR: new Set([
|
|
326
|
+
'BR'
|
|
327
|
+
]),
|
|
328
|
+
CA: new Set([
|
|
329
|
+
'CA'
|
|
330
|
+
]),
|
|
331
|
+
AU: new Set([
|
|
332
|
+
'AU'
|
|
333
|
+
]),
|
|
334
|
+
JP: new Set([
|
|
335
|
+
'JP'
|
|
336
|
+
]),
|
|
337
|
+
KR: new Set([
|
|
338
|
+
'KR'
|
|
339
|
+
]),
|
|
340
|
+
US_CCPA_REGIONS: new Set([
|
|
341
|
+
'CA'
|
|
342
|
+
]),
|
|
343
|
+
CA_QC_REGIONS: new Set([
|
|
344
|
+
'QC'
|
|
345
|
+
])
|
|
346
|
+
};
|
|
347
|
+
let jurisdiction = 'NONE';
|
|
348
|
+
if (countryCode) {
|
|
349
|
+
const normalizedCountryCode = countryCode.toUpperCase();
|
|
350
|
+
const normalizedRegionCode = regionCode && 'string' == typeof regionCode ? (regionCode.includes('-') ? regionCode.split('-').pop() : regionCode).toUpperCase() : null;
|
|
351
|
+
if ('US' === normalizedCountryCode && normalizedRegionCode && jurisdictions.US_CCPA_REGIONS.has(normalizedRegionCode)) return 'CCPA';
|
|
352
|
+
if ('CA' === normalizedCountryCode && normalizedRegionCode && jurisdictions.CA_QC_REGIONS.has(normalizedRegionCode)) return 'QC_LAW25';
|
|
353
|
+
const jurisdictionMap = [
|
|
354
|
+
{
|
|
355
|
+
sets: [
|
|
356
|
+
jurisdictions.UK
|
|
357
|
+
],
|
|
358
|
+
code: 'UK_GDPR'
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
sets: [
|
|
362
|
+
jurisdictions.EU,
|
|
363
|
+
jurisdictions.EEA
|
|
364
|
+
],
|
|
365
|
+
code: 'GDPR'
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
sets: [
|
|
369
|
+
jurisdictions.CH
|
|
370
|
+
],
|
|
371
|
+
code: 'CH'
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
sets: [
|
|
375
|
+
jurisdictions.BR
|
|
376
|
+
],
|
|
377
|
+
code: 'BR'
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
sets: [
|
|
381
|
+
jurisdictions.CA
|
|
382
|
+
],
|
|
383
|
+
code: 'PIPEDA'
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
sets: [
|
|
387
|
+
jurisdictions.AU
|
|
388
|
+
],
|
|
389
|
+
code: 'AU'
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
sets: [
|
|
393
|
+
jurisdictions.JP
|
|
394
|
+
],
|
|
395
|
+
code: 'APPI'
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
sets: [
|
|
399
|
+
jurisdictions.KR
|
|
400
|
+
],
|
|
401
|
+
code: 'PIPA'
|
|
402
|
+
}
|
|
403
|
+
];
|
|
404
|
+
for (const { sets, code } of jurisdictionMap)if (sets.some((set)=>set.has(normalizedCountryCode))) {
|
|
405
|
+
jurisdiction = code;
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return jurisdiction;
|
|
410
|
+
}
|
|
411
|
+
async function getLocation(request, options) {
|
|
412
|
+
if (options.disableGeoLocation) return {
|
|
413
|
+
countryCode: null,
|
|
414
|
+
regionCode: null
|
|
415
|
+
};
|
|
416
|
+
const { countryCode, regionCode } = getGeoHeaders(request.headers);
|
|
417
|
+
return {
|
|
418
|
+
countryCode,
|
|
419
|
+
regionCode
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
function getJurisdiction(location, options) {
|
|
423
|
+
if (options.disableGeoLocation) return 'GDPR';
|
|
424
|
+
return checkJurisdiction(location.countryCode, location.regionCode);
|
|
425
|
+
}
|
|
426
|
+
function stripIabTranslations(translations) {
|
|
427
|
+
const { iab: _iab, ...rest } = translations;
|
|
428
|
+
return rest;
|
|
429
|
+
}
|
|
430
|
+
function resolveNoPolicyFallback() {
|
|
431
|
+
return {
|
|
432
|
+
id: 'no_banner',
|
|
433
|
+
model: 'none',
|
|
434
|
+
ui: {
|
|
435
|
+
mode: 'none'
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
async function resolveInitPayload(request, options, logger) {
|
|
440
|
+
const acceptLanguage = request.headers.get('accept-language') || 'en';
|
|
441
|
+
const location = await getLocation(request, options);
|
|
442
|
+
const jurisdiction = getJurisdiction(location, options);
|
|
443
|
+
const hasExplicitPolicyPack = void 0 !== options.policyPacks;
|
|
444
|
+
const isExplicitEmptyPolicyPack = hasExplicitPolicyPack && (options.policyPacks?.length ?? 0) === 0;
|
|
445
|
+
const policyDecision = isExplicitEmptyPolicyPack ? void 0 : await policy_resolvePolicyDecision({
|
|
446
|
+
policies: options.policyPacks,
|
|
447
|
+
countryCode: location.countryCode,
|
|
448
|
+
regionCode: location.regionCode,
|
|
449
|
+
jurisdiction,
|
|
450
|
+
iabEnabled: options.iab?.enabled === true
|
|
451
|
+
});
|
|
452
|
+
if (hasExplicitPolicyPack && !isExplicitEmptyPolicyPack && !policyDecision) logger?.warn('Policy packs configured but no policy matched', {
|
|
453
|
+
country: location.countryCode,
|
|
454
|
+
region: location.regionCode
|
|
455
|
+
});
|
|
456
|
+
const resolvedPolicy = hasExplicitPolicyPack ? policyDecision?.policy ?? resolveNoPolicyFallback() : void 0;
|
|
457
|
+
const iabOptions = options.iab;
|
|
458
|
+
const shouldIncludeIabPayload = iabOptions?.enabled === true && (!hasExplicitPolicyPack || resolvedPolicy?.model === 'iab');
|
|
459
|
+
const translationsResult = getTranslationsData(acceptLanguage, options.customTranslations, {
|
|
460
|
+
i18n: options.i18n,
|
|
461
|
+
policyI18n: resolvedPolicy?.i18n,
|
|
462
|
+
logger
|
|
463
|
+
});
|
|
464
|
+
const responseTranslations = shouldIncludeIabPayload ? translationsResult : {
|
|
465
|
+
...translationsResult,
|
|
466
|
+
translations: stripIabTranslations(translationsResult.translations)
|
|
467
|
+
};
|
|
468
|
+
let gvl = null;
|
|
469
|
+
if (shouldIncludeIabPayload && iabOptions) {
|
|
470
|
+
const language = translationsResult.language.split('-')[0] || 'en';
|
|
471
|
+
const gvlResolver = createGVLResolver({
|
|
472
|
+
appName: options.appName || 'c15t',
|
|
473
|
+
bundled: iabOptions.bundled,
|
|
474
|
+
cacheAdapter: options.cache?.adapter,
|
|
475
|
+
vendorIds: iabOptions.vendorIds,
|
|
476
|
+
endpoint: iabOptions.endpoint
|
|
477
|
+
});
|
|
478
|
+
gvl = await gvlResolver.get(language);
|
|
479
|
+
}
|
|
480
|
+
const customVendors = shouldIncludeIabPayload ? iabOptions?.customVendors : void 0;
|
|
481
|
+
const snapshot = policyDecision ? await createPolicySnapshotToken({
|
|
482
|
+
options: options.policySnapshot,
|
|
483
|
+
tenantId: options.tenantId,
|
|
484
|
+
policyId: policyDecision.policy.id,
|
|
485
|
+
fingerprint: policyDecision.fingerprint,
|
|
486
|
+
matchedBy: policyDecision.matchedBy,
|
|
487
|
+
country: location?.countryCode ?? null,
|
|
488
|
+
region: location?.regionCode ?? null,
|
|
489
|
+
jurisdiction,
|
|
490
|
+
language: translationsResult.language,
|
|
491
|
+
model: policyDecision.policy.model,
|
|
492
|
+
policyI18n: policyDecision.policy.i18n,
|
|
493
|
+
expiryDays: policyDecision.policy.consent?.expiryDays,
|
|
494
|
+
scopeMode: policyDecision.policy.consent?.scopeMode,
|
|
495
|
+
uiMode: policyDecision.policy.ui?.mode,
|
|
496
|
+
bannerUi: policyDecision.policy.ui?.banner,
|
|
497
|
+
dialogUi: policyDecision.policy.ui?.dialog,
|
|
498
|
+
categories: policyDecision.policy.consent?.categories,
|
|
499
|
+
preselectedCategories: policyDecision.policy.consent?.preselectedCategories,
|
|
500
|
+
gpc: policyDecision.policy.consent?.gpc,
|
|
501
|
+
proofConfig: policyDecision.policy.proof
|
|
502
|
+
}) : void 0;
|
|
503
|
+
const gpc = '1' === request.headers.get('sec-gpc');
|
|
504
|
+
getMetrics()?.recordInit({
|
|
505
|
+
jurisdiction,
|
|
506
|
+
country: location?.countryCode ?? void 0,
|
|
507
|
+
region: location?.regionCode ?? void 0,
|
|
508
|
+
gpc
|
|
509
|
+
});
|
|
510
|
+
return {
|
|
511
|
+
jurisdiction,
|
|
512
|
+
location,
|
|
513
|
+
translations: responseTranslations,
|
|
514
|
+
branding: options.branding || 'c15t',
|
|
515
|
+
...shouldIncludeIabPayload && {
|
|
516
|
+
gvl,
|
|
517
|
+
customVendors
|
|
518
|
+
},
|
|
519
|
+
...resolvedPolicy && {
|
|
520
|
+
policy: resolvedPolicy
|
|
521
|
+
},
|
|
522
|
+
...policyDecision && {
|
|
523
|
+
policyDecision: {
|
|
524
|
+
policyId: policyDecision.policy.id,
|
|
525
|
+
fingerprint: policyDecision.fingerprint,
|
|
526
|
+
matchedBy: policyDecision.matchedBy,
|
|
527
|
+
country: location.countryCode,
|
|
528
|
+
region: location.regionCode,
|
|
529
|
+
jurisdiction
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
...snapshot?.token && {
|
|
533
|
+
policySnapshotToken: snapshot.token
|
|
534
|
+
},
|
|
535
|
+
...shouldIncludeIabPayload && iabOptions?.cmpId != null && {
|
|
536
|
+
cmpId: iabOptions.cmpId
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
export { checkJurisdiction, getJurisdiction, getLocation, policy_inspectPolicies as inspectPolicies, policy_resolvePolicyDecision, policy_resolvePolicySync, resolveInitPayload, validateMessages, verifyPolicySnapshotToken };
|
package/dist/cache.cjs
CHANGED
|
@@ -13,7 +13,7 @@ var __webpack_require__ = {};
|
|
|
13
13
|
})();
|
|
14
14
|
(()=>{
|
|
15
15
|
__webpack_require__.r = (exports1)=>{
|
|
16
|
-
if (
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
17
|
value: 'Module'
|
|
18
18
|
});
|
|
19
19
|
Object.defineProperty(exports1, '__esModule', {
|