@c15t/backend 2.0.0-rc.3 → 2.0.0-rc.5
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/cache.cjs +4 -4
- package/dist/cache.js +4 -4
- package/dist/core.cjs +845 -87
- package/dist/core.js +821 -87
- package/dist/db/schema.cjs +37 -0
- package/dist/db/schema.js +33 -2
- package/dist/edge.cjs +1106 -0
- package/dist/edge.js +1069 -0
- package/dist/router.cjs +621 -71
- package/dist/router.js +621 -71
- package/{dist → dist-types}/cache/adapters/cloudflare-kv.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/index.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/memory.d.ts +0 -1
- package/{dist → dist-types}/cache/adapters/upstash-redis.d.ts +0 -1
- package/{dist → dist-types}/cache/gvl-resolver.d.ts +1 -2
- package/{dist → dist-types}/cache/index.d.ts +0 -1
- package/{dist → dist-types}/cache/keys.d.ts +0 -1
- package/{dist → dist-types}/cache/types.d.ts +0 -1
- package/{dist → dist-types}/core.d.ts +8 -1
- package/{dist → dist-types}/db/migrator/index.d.ts +0 -1
- package/{dist → dist-types}/db/registry/consent-policy.d.ts +0 -1
- package/{dist → dist-types}/db/registry/consent-purpose.d.ts +0 -1
- package/{dist → dist-types}/db/registry/domain.d.ts +0 -1
- package/{dist → dist-types}/db/registry/index.d.ts +22 -2
- package/dist-types/db/registry/runtime-policy-decision.d.ts +60 -0
- package/{dist → dist-types}/db/registry/subject.d.ts +0 -1
- package/{dist → dist-types}/db/registry/types.d.ts +1 -2
- package/{dist → dist-types}/db/registry/utils/generate-id.d.ts +0 -1
- package/{dist → dist-types}/db/registry/utils.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/audit-log.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-policy.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-purpose.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent-record.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/consent.d.ts +1 -2
- package/{dist → dist-types}/db/schema/1.0.0/domain.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/index.d.ts +0 -1
- package/{dist → dist-types}/db/schema/1.0.0/subject.d.ts +0 -1
- package/{dist → dist-types}/db/schema/2.0.0/audit-log.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent-policy.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent-purpose.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/consent.d.ts +5 -2
- package/{dist → dist-types}/db/schema/2.0.0/domain.d.ts +1 -2
- package/{dist → dist-types}/db/schema/2.0.0/index.d.ts +432 -17
- package/dist-types/db/schema/2.0.0/runtime-policy-decision.d.ts +23 -0
- package/{dist → dist-types}/db/schema/2.0.0/subject.d.ts +1 -2
- package/{dist → dist-types}/db/schema/index.d.ts +862 -33
- package/{dist → dist-types}/db/tenant-scope.d.ts +0 -1
- package/dist-types/define-config.d.ts +17 -0
- package/dist-types/edge/index.d.ts +5 -0
- package/dist-types/edge/init-handler.d.ts +38 -0
- package/dist-types/edge/resolve-consent.d.ts +80 -0
- package/dist-types/edge/types.d.ts +13 -0
- package/{dist → dist-types}/handlers/consent/check.handler.d.ts +0 -1
- package/{src/handlers/consent/index.ts → dist-types/handlers/consent/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/init/geo.d.ts +2 -3
- package/{dist → dist-types}/handlers/init/index.d.ts +4 -5
- package/dist-types/handlers/init/policy.d.ts +26 -0
- package/dist-types/handlers/init/resolve-init.d.ts +44 -0
- package/dist-types/handlers/init/translations.d.ts +48 -0
- package/dist-types/handlers/policy/snapshot.d.ts +99 -0
- package/{src/handlers/status/index.ts → dist-types/handlers/status/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/status/status.handler.d.ts +0 -1
- package/{dist → dist-types}/handlers/subject/get.handler.d.ts +0 -1
- package/{src/handlers/subject/index.ts → dist-types/handlers/subject/index.d.ts} +0 -1
- package/{dist → dist-types}/handlers/subject/list.handler.d.ts +0 -1
- package/{dist → dist-types}/handlers/subject/patch.handler.d.ts +0 -1
- package/{dist → dist-types}/handlers/subject/post.handler.d.ts +12 -1
- package/{dist → dist-types}/handlers/utils/consent-enrichment.d.ts +0 -1
- package/{dist → dist-types}/init.d.ts +4 -7
- package/{dist → dist-types}/middleware/auth/index.d.ts +0 -1
- package/{dist → dist-types}/middleware/auth/validate-api-key.d.ts +0 -1
- package/{dist → dist-types}/middleware/cors/cors.d.ts +0 -1
- package/{src/middleware/cors/index.ts → dist-types/middleware/cors/index.d.ts} +0 -1
- package/{dist → dist-types}/middleware/cors/is-origin-trusted.d.ts +1 -2
- package/{dist → dist-types}/middleware/cors/process-cors.d.ts +0 -1
- package/{dist → dist-types}/middleware/openapi/config.d.ts +0 -1
- package/{dist → dist-types}/middleware/openapi/handlers.d.ts +0 -1
- package/{src/middleware/openapi/index.ts → dist-types/middleware/openapi/index.d.ts} +0 -1
- package/{dist → dist-types}/middleware/process-ip/index.d.ts +0 -1
- package/dist-types/policies/builder.d.ts +127 -0
- package/dist-types/policies/defaults.d.ts +2 -0
- package/dist-types/policies/matchers.d.ts +3 -0
- package/{dist → dist-types}/router.d.ts +0 -1
- package/{dist → dist-types}/routes/consent.d.ts +0 -1
- package/{src/routes/index.ts → dist-types/routes/index.d.ts} +0 -1
- package/{dist → dist-types}/routes/init.d.ts +0 -1
- package/{dist → dist-types}/routes/status.d.ts +0 -1
- package/{dist → dist-types}/routes/subject.d.ts +0 -1
- package/{dist → dist-types}/types/api.d.ts +0 -1
- package/dist-types/types/index.d.ts +443 -0
- package/dist-types/utils/background.d.ts +6 -0
- package/{dist → dist-types}/utils/create-telemetry-options.d.ts +1 -2
- package/{dist → dist-types}/utils/env.d.ts +0 -1
- package/{dist → dist-types}/utils/extract-error-message.d.ts +0 -1
- package/{dist → dist-types}/utils/instrumentation.d.ts +0 -1
- package/{dist → dist-types}/utils/logger.d.ts +1 -2
- package/{dist → dist-types}/utils/metrics.d.ts +0 -1
- package/dist-types/version.d.ts +1 -0
- package/docs/README.md +49 -0
- package/docs/api/configuration.md +197 -0
- package/docs/api/endpoints.md +211 -0
- package/docs/guides/caching.md +85 -0
- package/docs/guides/database-setup.md +128 -0
- package/docs/guides/edge-deployment.md +248 -0
- package/docs/guides/framework-integration.md +142 -0
- package/docs/guides/iab-tcf.md +89 -0
- package/docs/guides/observability.md +96 -0
- package/docs/guides/policy-packs.md +396 -0
- package/docs/quickstart.md +129 -0
- package/package.json +37 -23
- package/.turbo/turbo-build.log +0 -49
- package/CHANGELOG.md +0 -115
- package/dist/cache/adapters/cloudflare-kv.d.ts.map +0 -1
- package/dist/cache/adapters/index.d.ts.map +0 -1
- package/dist/cache/adapters/memory.d.ts.map +0 -1
- package/dist/cache/adapters/upstash-redis.d.ts.map +0 -1
- package/dist/cache/gvl-resolver.d.ts.map +0 -1
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/keys.d.ts.map +0 -1
- package/dist/cache/types.d.ts.map +0 -1
- package/dist/core.d.ts.map +0 -1
- package/dist/db/adapters/drizzle.d.ts +0 -2
- package/dist/db/adapters/drizzle.d.ts.map +0 -1
- package/dist/db/adapters/index.d.ts +0 -2
- package/dist/db/adapters/index.d.ts.map +0 -1
- package/dist/db/adapters/kysely.d.ts +0 -2
- package/dist/db/adapters/kysely.d.ts.map +0 -1
- package/dist/db/adapters/mongo.d.ts +0 -2
- package/dist/db/adapters/mongo.d.ts.map +0 -1
- package/dist/db/adapters/prisma.d.ts +0 -2
- package/dist/db/adapters/prisma.d.ts.map +0 -1
- package/dist/db/adapters/typeorm.d.ts +0 -2
- package/dist/db/adapters/typeorm.d.ts.map +0 -1
- package/dist/db/migrator/index.d.ts.map +0 -1
- package/dist/db/registry/consent-policy.d.ts.map +0 -1
- package/dist/db/registry/consent-purpose.d.ts.map +0 -1
- package/dist/db/registry/domain.d.ts.map +0 -1
- package/dist/db/registry/index.d.ts.map +0 -1
- package/dist/db/registry/subject.d.ts.map +0 -1
- package/dist/db/registry/types.d.ts.map +0 -1
- package/dist/db/registry/utils/generate-id.d.ts.map +0 -1
- package/dist/db/registry/utils.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/audit-log.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-policy.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-purpose.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent-record.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/consent.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/domain.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/index.d.ts.map +0 -1
- package/dist/db/schema/1.0.0/subject.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/audit-log.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent-policy.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent-purpose.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/consent.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/domain.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/index.d.ts.map +0 -1
- package/dist/db/schema/2.0.0/subject.d.ts.map +0 -1
- package/dist/db/schema/index.d.ts.map +0 -1
- package/dist/db/tenant-scope.d.ts.map +0 -1
- package/dist/define-config.d.ts +0 -5
- package/dist/define-config.d.ts.map +0 -1
- package/dist/handlers/consent/check.handler.d.ts.map +0 -1
- package/dist/handlers/consent/index.d.ts +0 -12
- package/dist/handlers/consent/index.d.ts.map +0 -1
- package/dist/handlers/init/geo.d.ts.map +0 -1
- package/dist/handlers/init/index.d.ts.map +0 -1
- package/dist/handlers/init/translations.d.ts +0 -28
- package/dist/handlers/init/translations.d.ts.map +0 -1
- package/dist/handlers/status/index.d.ts +0 -7
- package/dist/handlers/status/index.d.ts.map +0 -1
- package/dist/handlers/status/status.handler.d.ts.map +0 -1
- package/dist/handlers/subject/get.handler.d.ts.map +0 -1
- package/dist/handlers/subject/index.d.ts +0 -10
- package/dist/handlers/subject/index.d.ts.map +0 -1
- package/dist/handlers/subject/list.handler.d.ts.map +0 -1
- package/dist/handlers/subject/patch.handler.d.ts.map +0 -1
- package/dist/handlers/subject/post.handler.d.ts.map +0 -1
- package/dist/handlers/utils/consent-enrichment.d.ts.map +0 -1
- package/dist/init.d.ts.map +0 -1
- package/dist/middleware/auth/index.d.ts.map +0 -1
- package/dist/middleware/auth/validate-api-key.d.ts.map +0 -1
- package/dist/middleware/cors/cors.d.ts.map +0 -1
- package/dist/middleware/cors/index.d.ts +0 -30
- package/dist/middleware/cors/index.d.ts.map +0 -1
- package/dist/middleware/cors/is-origin-trusted.d.ts.map +0 -1
- package/dist/middleware/cors/process-cors.d.ts.map +0 -1
- package/dist/middleware/openapi/config.d.ts.map +0 -1
- package/dist/middleware/openapi/handlers.d.ts.map +0 -1
- package/dist/middleware/openapi/index.d.ts +0 -12
- package/dist/middleware/openapi/index.d.ts.map +0 -1
- package/dist/middleware/process-ip/index.d.ts.map +0 -1
- package/dist/router.d.ts.map +0 -1
- package/dist/routes/consent.d.ts.map +0 -1
- package/dist/routes/index.d.ts +0 -10
- package/dist/routes/index.d.ts.map +0 -1
- package/dist/routes/init.d.ts.map +0 -1
- package/dist/routes/status.d.ts.map +0 -1
- package/dist/routes/subject.d.ts.map +0 -1
- package/dist/types/api.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -263
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/create-telemetry-options.d.ts.map +0 -1
- package/dist/utils/env.d.ts.map +0 -1
- package/dist/utils/extract-error-message.d.ts.map +0 -1
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/instrumentation.d.ts.map +0 -1
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/metrics.d.ts.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.d.ts.map +0 -1
- package/knip.json +0 -31
- package/rslib.config.ts +0 -93
- package/src/cache/adapters/cloudflare-kv.ts +0 -71
- package/src/cache/adapters/index.ts +0 -22
- package/src/cache/adapters/memory.ts +0 -111
- package/src/cache/adapters/upstash-redis.ts +0 -113
- package/src/cache/gvl-resolver.ts +0 -289
- package/src/cache/index.ts +0 -34
- package/src/cache/keys.ts +0 -68
- package/src/cache/types.ts +0 -66
- package/src/core.ts +0 -369
- package/src/db/migrator/index.ts +0 -80
- package/src/db/registry/consent-policy.test.ts +0 -451
- package/src/db/registry/consent-policy.ts +0 -82
- package/src/db/registry/consent-purpose.test.ts +0 -428
- package/src/db/registry/consent-purpose.ts +0 -61
- package/src/db/registry/domain.test.ts +0 -445
- package/src/db/registry/domain.ts +0 -91
- package/src/db/registry/index.ts +0 -14
- package/src/db/registry/subject.test.ts +0 -371
- package/src/db/registry/subject.ts +0 -126
- package/src/db/registry/types.ts +0 -10
- package/src/db/registry/utils/generate-id.test.ts +0 -216
- package/src/db/registry/utils/generate-id.ts +0 -133
- package/src/db/registry/utils.ts +0 -133
- package/src/db/schema/1.0.0/audit-log.ts +0 -15
- package/src/db/schema/1.0.0/consent-policy.ts +0 -14
- package/src/db/schema/1.0.0/consent-purpose.ts +0 -14
- package/src/db/schema/1.0.0/consent-record.ts +0 -10
- package/src/db/schema/1.0.0/consent.ts +0 -20
- package/src/db/schema/1.0.0/domain.ts +0 -12
- package/src/db/schema/1.0.0/index.ts +0 -48
- package/src/db/schema/1.0.0/subject.ts +0 -11
- package/src/db/schema/2.0.0/audit-log.ts +0 -18
- package/src/db/schema/2.0.0/consent-policy.ts +0 -28
- package/src/db/schema/2.0.0/consent-purpose.ts +0 -12
- package/src/db/schema/2.0.0/consent.ts +0 -28
- package/src/db/schema/2.0.0/domain.ts +0 -12
- package/src/db/schema/2.0.0/index.ts +0 -47
- package/src/db/schema/2.0.0/subject.ts +0 -13
- package/src/db/schema/index.ts +0 -15
- package/src/db/tenant-scope.test.ts +0 -747
- package/src/db/tenant-scope.ts +0 -103
- package/src/define-config.ts +0 -5
- package/src/handlers/consent/check.handler.ts +0 -126
- package/src/handlers/init/geo.test.ts +0 -317
- package/src/handlers/init/geo.ts +0 -195
- package/src/handlers/init/index.test.ts +0 -205
- package/src/handlers/init/index.ts +0 -114
- package/src/handlers/init/translations.test.ts +0 -121
- package/src/handlers/init/translations.ts +0 -72
- package/src/handlers/status/status.handler.test.ts +0 -155
- package/src/handlers/status/status.handler.ts +0 -51
- package/src/handlers/subject/get.handler.ts +0 -92
- package/src/handlers/subject/list.handler.ts +0 -92
- package/src/handlers/subject/patch.handler.ts +0 -119
- package/src/handlers/subject/post.handler.test.ts +0 -294
- package/src/handlers/subject/post.handler.ts +0 -268
- package/src/handlers/utils/consent-enrichment.test.ts +0 -380
- package/src/handlers/utils/consent-enrichment.ts +0 -218
- package/src/init.test.ts +0 -126
- package/src/init.ts +0 -87
- package/src/middleware/auth/index.ts +0 -11
- package/src/middleware/auth/validate-api-key.test.ts +0 -86
- package/src/middleware/auth/validate-api-key.ts +0 -107
- package/src/middleware/cors/cors.test.ts +0 -135
- package/src/middleware/cors/cors.ts +0 -186
- package/src/middleware/cors/is-origin-trusted.test.ts +0 -164
- package/src/middleware/cors/is-origin-trusted.ts +0 -130
- package/src/middleware/cors/process-cors.ts +0 -91
- package/src/middleware/openapi/config.ts +0 -29
- package/src/middleware/openapi/handlers.ts +0 -34
- package/src/middleware/process-ip/index.test.ts +0 -195
- package/src/middleware/process-ip/index.ts +0 -199
- package/src/router.ts +0 -15
- package/src/routes/consent.ts +0 -52
- package/src/routes/init.ts +0 -105
- package/src/routes/status.ts +0 -46
- package/src/routes/subject.ts +0 -152
- package/src/types/api.ts +0 -48
- package/src/types/index.ts +0 -297
- package/src/utils/create-telemetry-options.test.ts +0 -302
- package/src/utils/create-telemetry-options.ts +0 -229
- package/src/utils/env.ts +0 -84
- package/src/utils/extract-error-message.ts +0 -21
- package/src/utils/instrumentation.test.ts +0 -185
- package/src/utils/instrumentation.ts +0 -196
- package/src/utils/logger.ts +0 -41
- package/src/utils/metrics.test.ts +0 -323
- package/src/utils/metrics.ts +0 -402
- package/src/utils/telemetry-pii.test.ts +0 -325
- package/src/version.ts +0 -2
- package/tsconfig.json +0 -11
- package/vitest.config.ts +0 -28
- /package/dist/{types.cjs → types/index.cjs} +0 -0
- /package/dist/{types.js → types/index.js} +0 -0
- /package/{src/db/adapters/drizzle.ts → dist-types/db/adapters/drizzle.d.ts} +0 -0
- /package/{src/db/adapters/index.ts → dist-types/db/adapters/index.d.ts} +0 -0
- /package/{src/db/adapters/kysely.ts → dist-types/db/adapters/kysely.d.ts} +0 -0
- /package/{src/db/adapters/mongo.ts → dist-types/db/adapters/mongo.d.ts} +0 -0
- /package/{src/db/adapters/prisma.ts → dist-types/db/adapters/prisma.d.ts} +0 -0
- /package/{src/db/adapters/typeorm.ts → dist-types/db/adapters/typeorm.d.ts} +0 -0
- /package/{src/utils/index.ts → dist-types/utils/index.d.ts} +0 -0
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E test: every span attribute key must be in the allowlist,
|
|
3
|
-
* and no attribute value may match PII patterns.
|
|
4
|
-
*
|
|
5
|
-
* Uses a real BasicTracerProvider + InMemorySpanExporter (no mocks).
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
BasicTracerProvider,
|
|
10
|
-
InMemorySpanExporter,
|
|
11
|
-
SimpleSpanProcessor,
|
|
12
|
-
} from '@opentelemetry/sdk-trace-base';
|
|
13
|
-
import { afterEach, beforeAll, describe, expect, it } from 'vitest';
|
|
14
|
-
import type { C15TOptions } from '../types';
|
|
15
|
-
import {
|
|
16
|
-
createRequestSpan,
|
|
17
|
-
createTelemetryOptions,
|
|
18
|
-
resetTelemetryConfig,
|
|
19
|
-
withRequestSpan,
|
|
20
|
-
} from './create-telemetry-options';
|
|
21
|
-
import {
|
|
22
|
-
withCacheSpan,
|
|
23
|
-
withDatabaseSpan,
|
|
24
|
-
withExternalSpan,
|
|
25
|
-
} from './instrumentation';
|
|
26
|
-
|
|
27
|
-
// ── Allowlist ───────────────────────────────────────────────────────────
|
|
28
|
-
const ALLOWED_KEYS = new Set([
|
|
29
|
-
'http.method',
|
|
30
|
-
'http.route',
|
|
31
|
-
'http.host',
|
|
32
|
-
'http.path',
|
|
33
|
-
'http.url',
|
|
34
|
-
'error.type',
|
|
35
|
-
'db.system',
|
|
36
|
-
'db.operation',
|
|
37
|
-
'db.entity',
|
|
38
|
-
'cache.operation',
|
|
39
|
-
'cache.layer',
|
|
40
|
-
'service.name',
|
|
41
|
-
'service.version',
|
|
42
|
-
'tenant.id',
|
|
43
|
-
]);
|
|
44
|
-
|
|
45
|
-
const BLOCKED_KEYS = new Set(['error.stack', 'error.message']);
|
|
46
|
-
|
|
47
|
-
const PII_PATTERNS = [
|
|
48
|
-
/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/, // IPv4
|
|
49
|
-
/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/, // email
|
|
50
|
-
/at .+\(.+:\d+:\d+\)/, // stack trace line
|
|
51
|
-
/\?[^=]+=/, // query string
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
// ── Provider setup ──────────────────────────────────────────────────────
|
|
55
|
-
const exporter = new InMemorySpanExporter();
|
|
56
|
-
const provider = new BasicTracerProvider();
|
|
57
|
-
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
|
|
58
|
-
provider.register();
|
|
59
|
-
|
|
60
|
-
const tracer = provider.getTracer('pii-test');
|
|
61
|
-
|
|
62
|
-
function telemetryOptions(): C15TOptions {
|
|
63
|
-
return {
|
|
64
|
-
trustedOrigins: [],
|
|
65
|
-
adapter: {} as C15TOptions['adapter'],
|
|
66
|
-
advanced: {
|
|
67
|
-
telemetry: {
|
|
68
|
-
enabled: true,
|
|
69
|
-
tracer,
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
76
|
-
function drainSpans() {
|
|
77
|
-
const spans = exporter.getFinishedSpans();
|
|
78
|
-
const copy = [...spans];
|
|
79
|
-
exporter.reset();
|
|
80
|
-
return copy;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function assertAllowlist(spans: ReturnType<typeof drainSpans>) {
|
|
84
|
-
for (const span of spans) {
|
|
85
|
-
const attrs = span.attributes;
|
|
86
|
-
for (const key of Object.keys(attrs)) {
|
|
87
|
-
expect(ALLOWED_KEYS.has(key)).toBe(true);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function assertNoBlockedKeys(spans: ReturnType<typeof drainSpans>) {
|
|
93
|
-
for (const span of spans) {
|
|
94
|
-
const attrs = span.attributes;
|
|
95
|
-
for (const key of Object.keys(attrs)) {
|
|
96
|
-
expect(BLOCKED_KEYS.has(key)).toBe(false);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function assertNoPiiValues(spans: ReturnType<typeof drainSpans>) {
|
|
102
|
-
for (const span of spans) {
|
|
103
|
-
const attrs = span.attributes;
|
|
104
|
-
for (const [key, value] of Object.entries(attrs)) {
|
|
105
|
-
if (typeof value === 'string') {
|
|
106
|
-
for (const pattern of PII_PATTERNS) {
|
|
107
|
-
expect(
|
|
108
|
-
pattern.test(value),
|
|
109
|
-
`Attribute "${key}" value "${value}" matches PII pattern ${pattern}`
|
|
110
|
-
).toBe(false);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ── Tests ───────────────────────────────────────────────────────────────
|
|
118
|
-
beforeAll(() => {
|
|
119
|
-
createTelemetryOptions('pii-test', { enabled: true, tracer });
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
afterEach(() => {
|
|
123
|
-
exporter.reset();
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
describe('telemetry PII safeguards', () => {
|
|
127
|
-
// 1. withDatabaseSpan success
|
|
128
|
-
it('withDatabaseSpan attributes pass allowlist', async () => {
|
|
129
|
-
await withDatabaseSpan(
|
|
130
|
-
{ operation: 'find', entity: 'subject' },
|
|
131
|
-
async () => 'ok',
|
|
132
|
-
telemetryOptions()
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const spans = drainSpans();
|
|
136
|
-
expect(spans.length).toBe(1);
|
|
137
|
-
assertAllowlist(spans);
|
|
138
|
-
assertNoPiiValues(spans);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
// 2. withExternalSpan success — span name = hostname only
|
|
142
|
-
it('withExternalSpan span name is HTTP METHOD hostname only', async () => {
|
|
143
|
-
await withExternalSpan(
|
|
144
|
-
{ url: 'https://api.example.com/v1/charges', method: 'GET' },
|
|
145
|
-
async () => 'ok',
|
|
146
|
-
telemetryOptions()
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
const spans = drainSpans();
|
|
150
|
-
expect(spans.length).toBe(1);
|
|
151
|
-
expect(spans[0].name).toBe('HTTP GET api.example.com');
|
|
152
|
-
assertAllowlist(spans);
|
|
153
|
-
assertNoPiiValues(spans);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// 3. withExternalSpan strips query params from http.url
|
|
157
|
-
it('withExternalSpan strips query params from http.url', async () => {
|
|
158
|
-
await withExternalSpan(
|
|
159
|
-
{
|
|
160
|
-
url: 'https://api.example.com/v1/data?key=secret&email=user@ex.com',
|
|
161
|
-
method: 'POST',
|
|
162
|
-
},
|
|
163
|
-
async () => 'ok',
|
|
164
|
-
telemetryOptions()
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
const spans = drainSpans();
|
|
168
|
-
expect(spans.length).toBe(1);
|
|
169
|
-
const url = spans[0].attributes['http.url'] as string;
|
|
170
|
-
expect(url).toBe('https://api.example.com/v1/data');
|
|
171
|
-
expect(url).not.toContain('?');
|
|
172
|
-
assertAllowlist(spans);
|
|
173
|
-
assertNoPiiValues(spans);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
// 4. withCacheSpan success
|
|
177
|
-
it('withCacheSpan has no unexpected attributes', async () => {
|
|
178
|
-
await withCacheSpan('get', 'memory', async () => 'ok', telemetryOptions());
|
|
179
|
-
|
|
180
|
-
const spans = drainSpans();
|
|
181
|
-
expect(spans.length).toBe(1);
|
|
182
|
-
assertAllowlist(spans);
|
|
183
|
-
assertNoPiiValues(spans);
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// 5. withRequestSpan success — no http.path
|
|
187
|
-
it('withRequestSpan has no http.path attribute', async () => {
|
|
188
|
-
await withRequestSpan(
|
|
189
|
-
'GET',
|
|
190
|
-
'/subjects/abc123',
|
|
191
|
-
async () => 'ok',
|
|
192
|
-
telemetryOptions()
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
const spans = drainSpans();
|
|
196
|
-
expect(spans.length).toBe(1);
|
|
197
|
-
expect(spans[0].attributes['http.path']).toBeUndefined();
|
|
198
|
-
assertAllowlist(spans);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
// 6. createRequestSpan direct — no http.path
|
|
202
|
-
it('createRequestSpan has no http.path attribute', () => {
|
|
203
|
-
const span = createRequestSpan(
|
|
204
|
-
'POST',
|
|
205
|
-
'/subjects/xyz789',
|
|
206
|
-
telemetryOptions()
|
|
207
|
-
);
|
|
208
|
-
|
|
209
|
-
expect(span).toBeDefined();
|
|
210
|
-
span!.end();
|
|
211
|
-
|
|
212
|
-
const spans = drainSpans();
|
|
213
|
-
expect(spans.length).toBe(1);
|
|
214
|
-
expect(spans[0].attributes['http.path']).toBeUndefined();
|
|
215
|
-
assertAllowlist(spans);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// 7. withDatabaseSpan error — PII in message
|
|
219
|
-
it('withDatabaseSpan error does not leak error.message or error.stack', async () => {
|
|
220
|
-
await expect(
|
|
221
|
-
withDatabaseSpan(
|
|
222
|
-
{ operation: 'find', entity: 'subject' },
|
|
223
|
-
async () => {
|
|
224
|
-
throw new Error('User user@example.com not found at 192.168.1.1');
|
|
225
|
-
},
|
|
226
|
-
telemetryOptions()
|
|
227
|
-
)
|
|
228
|
-
).rejects.toThrow();
|
|
229
|
-
|
|
230
|
-
const spans = drainSpans();
|
|
231
|
-
expect(spans.length).toBe(1);
|
|
232
|
-
assertNoBlockedKeys(spans);
|
|
233
|
-
assertNoPiiValues(spans);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// 8. withExternalSpan error — IP in message
|
|
237
|
-
it('withExternalSpan error does not leak error.message or error.stack', async () => {
|
|
238
|
-
await expect(
|
|
239
|
-
withExternalSpan(
|
|
240
|
-
{ url: 'https://api.example.com/v1/data', method: 'GET' },
|
|
241
|
-
async () => {
|
|
242
|
-
throw new Error('Connection refused at 10.0.0.1:5432');
|
|
243
|
-
},
|
|
244
|
-
telemetryOptions()
|
|
245
|
-
)
|
|
246
|
-
).rejects.toThrow();
|
|
247
|
-
|
|
248
|
-
const spans = drainSpans();
|
|
249
|
-
expect(spans.length).toBe(1);
|
|
250
|
-
assertNoBlockedKeys(spans);
|
|
251
|
-
assertNoPiiValues(spans);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// 9. withCacheSpan error
|
|
255
|
-
it('withCacheSpan error does not leak error.message or error.stack', async () => {
|
|
256
|
-
await expect(
|
|
257
|
-
withCacheSpan(
|
|
258
|
-
'get',
|
|
259
|
-
'external',
|
|
260
|
-
async () => {
|
|
261
|
-
throw new Error('Redis timeout at 172.16.0.1');
|
|
262
|
-
},
|
|
263
|
-
telemetryOptions()
|
|
264
|
-
)
|
|
265
|
-
).rejects.toThrow();
|
|
266
|
-
|
|
267
|
-
const spans = drainSpans();
|
|
268
|
-
expect(spans.length).toBe(1);
|
|
269
|
-
assertNoBlockedKeys(spans);
|
|
270
|
-
assertNoPiiValues(spans);
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// 10. withRequestSpan error
|
|
274
|
-
it('withRequestSpan error does not leak error.message or error.stack', async () => {
|
|
275
|
-
await expect(
|
|
276
|
-
withRequestSpan(
|
|
277
|
-
'GET',
|
|
278
|
-
'/subjects/abc123',
|
|
279
|
-
async () => {
|
|
280
|
-
throw new Error('Subject user@corp.io failed auth');
|
|
281
|
-
},
|
|
282
|
-
telemetryOptions()
|
|
283
|
-
)
|
|
284
|
-
).rejects.toThrow();
|
|
285
|
-
|
|
286
|
-
const spans = drainSpans();
|
|
287
|
-
expect(spans.length).toBe(1);
|
|
288
|
-
assertNoBlockedKeys(spans);
|
|
289
|
-
assertNoPiiValues(spans);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// 11. All 4 span types combined — every key in allowlist
|
|
293
|
-
it('all span types combined: every attribute key is in allowlist', async () => {
|
|
294
|
-
// database
|
|
295
|
-
await withDatabaseSpan(
|
|
296
|
-
{ operation: 'create', entity: 'consent' },
|
|
297
|
-
async () => 'ok',
|
|
298
|
-
telemetryOptions()
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
// external
|
|
302
|
-
await withExternalSpan(
|
|
303
|
-
{ url: 'https://vendor.example.com/api', method: 'POST' },
|
|
304
|
-
async () => 'ok',
|
|
305
|
-
telemetryOptions()
|
|
306
|
-
);
|
|
307
|
-
|
|
308
|
-
// cache
|
|
309
|
-
await withCacheSpan('set', 'bundled', async () => 'ok', telemetryOptions());
|
|
310
|
-
|
|
311
|
-
// request
|
|
312
|
-
await withRequestSpan(
|
|
313
|
-
'DELETE',
|
|
314
|
-
'/consents/123',
|
|
315
|
-
async () => 'ok',
|
|
316
|
-
telemetryOptions()
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
const spans = drainSpans();
|
|
320
|
-
expect(spans.length).toBe(4);
|
|
321
|
-
assertAllowlist(spans);
|
|
322
|
-
assertNoBlockedKeys(spans);
|
|
323
|
-
assertNoPiiValues(spans);
|
|
324
|
-
});
|
|
325
|
-
});
|
package/src/version.ts
DELETED
package/tsconfig.json
DELETED
package/vitest.config.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
|
-
import { baseConfig } from '@c15t/vitest-config/base';
|
|
4
|
-
import { defineConfig, mergeConfig } from 'vitest/config';
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
|
|
9
|
-
export default mergeConfig(
|
|
10
|
-
baseConfig,
|
|
11
|
-
defineConfig({
|
|
12
|
-
resolve: {
|
|
13
|
-
alias: {
|
|
14
|
-
'~': path.resolve(__dirname, './src'),
|
|
15
|
-
// Workaround: fumadb imports without extension, but Node ESM needs .js
|
|
16
|
-
'semver/functions/compare': 'semver/functions/compare.js',
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
test: {
|
|
20
|
-
environment: 'node',
|
|
21
|
-
server: {
|
|
22
|
-
deps: {
|
|
23
|
-
inline: ['fumadb'],
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
})
|
|
28
|
-
);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|