@revealui/core 0.5.6 → 0.6.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.
Files changed (40) hide show
  1. package/dist/api/compression.d.ts +3 -4
  2. package/dist/api/compression.d.ts.map +1 -1
  3. package/dist/api/compression.js +1 -2
  4. package/dist/api/rate-limit.d.ts +10 -11
  5. package/dist/api/rate-limit.d.ts.map +1 -1
  6. package/dist/api/rate-limit.js +2 -3
  7. package/dist/api/response-cache.d.ts +8 -9
  8. package/dist/api/response-cache.d.ts.map +1 -1
  9. package/dist/api/response-cache.js +2 -3
  10. package/dist/client/admin/layout.d.ts.map +1 -1
  11. package/dist/client/admin/layout.js +1 -3
  12. package/dist/generated/types/admin.d.ts +2 -2
  13. package/dist/generated/types/admin.d.ts.map +1 -1
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +6 -2
  17. package/dist/license-encryption.d.ts +11 -2
  18. package/dist/license-encryption.d.ts.map +1 -1
  19. package/dist/license-encryption.js +77 -22
  20. package/dist/license.d.ts +68 -5
  21. package/dist/license.d.ts.map +1 -1
  22. package/dist/license.js +157 -15
  23. package/dist/nextjs/index.d.ts +0 -1
  24. package/dist/nextjs/index.d.ts.map +1 -1
  25. package/dist/nextjs/index.js +7 -2
  26. package/dist/nextjs/withRevealUI.d.ts +29 -1
  27. package/dist/nextjs/withRevealUI.d.ts.map +1 -1
  28. package/dist/observability/logger.d.ts +0 -4
  29. package/dist/observability/logger.d.ts.map +1 -1
  30. package/dist/observability/logger.js +2 -29
  31. package/dist/revealui.d.ts +0 -5
  32. package/dist/revealui.d.ts.map +1 -1
  33. package/dist/revealui.js +0 -10
  34. package/dist/richtext/exports/server/rsc.d.ts +2 -17
  35. package/dist/richtext/exports/server/rsc.d.ts.map +1 -1
  36. package/dist/richtext/exports/server/rsc.js +9 -54
  37. package/dist/utils/api-wrapper.d.ts +4 -6
  38. package/dist/utils/api-wrapper.d.ts.map +1 -1
  39. package/dist/utils/api-wrapper.js +6 -9
  40. package/package.json +56 -17
@@ -3,50 +3,91 @@
3
3
  *
4
4
  * Format: enc:<iv-hex>:<ciphertext-hex>:<auth-tag-hex>
5
5
  * Falls back to plaintext when REVEALUI_LICENSE_ENCRYPTION_KEY is not set.
6
+ *
7
+ * Edge-compatible: uses the Web Crypto API (`crypto.subtle`) exclusively.
8
+ * Safe to import from any runtime (Node, Edge, browser, Workers).
9
+ *
10
+ * Note: AES-GCM via Web Crypto bundles the auth tag onto the ciphertext
11
+ * (last 16 bytes). The on-wire format is kept identical to the previous
12
+ * node:crypto implementation for backward compatibility, so decrypt still
13
+ * accepts `enc:iv:ciphertext:tag` and recombines ciphertext||tag before
14
+ * passing to `crypto.subtle.decrypt`.
6
15
  */
7
- import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
8
16
  const ENC_PREFIX = 'enc:';
9
- const ALGORITHM = 'aes-256-gcm';
10
17
  const IV_BYTES = 12;
18
+ const TAG_BYTES = 16;
19
+ /** Hex-encode a Uint8Array. */
20
+ function toHex(bytes) {
21
+ let out = '';
22
+ for (const b of bytes) {
23
+ out += b.toString(16).padStart(2, '0');
24
+ }
25
+ return out;
26
+ }
27
+ /** Hex-decode to Uint8Array. Throws on invalid input length. */
28
+ function fromHex(hex) {
29
+ if (hex.length % 2 !== 0) {
30
+ throw new Error('Invalid hex string: odd length');
31
+ }
32
+ const out = new Uint8Array(hex.length / 2);
33
+ for (let i = 0; i < out.length; i++) {
34
+ const byte = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
35
+ if (Number.isNaN(byte)) {
36
+ throw new Error('Invalid hex string');
37
+ }
38
+ out[i] = byte;
39
+ }
40
+ return out;
41
+ }
11
42
  /**
12
43
  * Derives a 32-byte key from the env var value.
13
44
  * Accepts either a 64-char hex string or an arbitrary passphrase (hashed to 32 bytes).
14
45
  */
15
- function deriveKey(raw) {
46
+ async function deriveKeyBytes(raw) {
16
47
  if (/^[0-9a-f]{64}$/i.test(raw)) {
17
- return Buffer.from(raw, 'hex');
48
+ return fromHex(raw);
18
49
  }
19
- return createHash('sha256').update(raw).digest();
50
+ const encoded = new TextEncoder().encode(raw);
51
+ const digest = await crypto.subtle.digest('SHA-256', encoded);
52
+ return new Uint8Array(digest);
20
53
  }
21
- function getEncryptionKey() {
54
+ async function getCryptoKey(usage) {
22
55
  const raw = process.env.REVEALUI_LICENSE_ENCRYPTION_KEY;
23
56
  if (!raw)
24
57
  return null;
25
- return deriveKey(raw);
58
+ const keyBytes = await deriveKeyBytes(raw);
59
+ // Cast through BufferSource: TS 5.7+ narrows Uint8Array to ArrayBufferLike on
60
+ // some construction paths, but Web Crypto accepts any ArrayBufferView.
61
+ return crypto.subtle.importKey('raw', keyBytes, { name: 'AES-GCM' }, false, [
62
+ usage,
63
+ ]);
26
64
  }
27
65
  /**
28
66
  * Encrypt a plaintext license key.
29
67
  * Returns `enc:<iv>:<ciphertext>:<tag>` or the original plaintext if no key is configured.
30
68
  */
31
- export function encryptLicenseKey(plaintext) {
32
- const key = getEncryptionKey();
69
+ export async function encryptLicenseKey(plaintext) {
70
+ const key = await getCryptoKey('encrypt');
33
71
  if (!key)
34
72
  return plaintext;
35
- const iv = randomBytes(IV_BYTES);
36
- const cipher = createCipheriv(ALGORITHM, key, iv);
37
- const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
38
- const tag = cipher.getAuthTag();
39
- return `${ENC_PREFIX}${iv.toString('hex')}:${encrypted.toString('hex')}:${tag.toString('hex')}`;
73
+ const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES));
74
+ const plaintextBytes = new TextEncoder().encode(plaintext);
75
+ const combined = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintextBytes));
76
+ // Web Crypto appends the 16-byte auth tag to the ciphertext. Split it back
77
+ // out to preserve the original on-wire format.
78
+ const ciphertext = combined.slice(0, combined.length - TAG_BYTES);
79
+ const tag = combined.slice(combined.length - TAG_BYTES);
80
+ return `${ENC_PREFIX}${toHex(iv)}:${toHex(ciphertext)}:${toHex(tag)}`;
40
81
  }
41
82
  /**
42
83
  * Decrypt a license key.
43
84
  * If the value doesn't start with `enc:`, returns it as-is (plaintext fallback).
44
85
  */
45
- export function decryptLicenseKey(stored) {
86
+ export async function decryptLicenseKey(stored) {
46
87
  if (!stored.startsWith(ENC_PREFIX)) {
47
88
  return stored; // plaintext - backward compatible
48
89
  }
49
- const key = getEncryptionKey();
90
+ const key = await getCryptoKey('decrypt');
50
91
  if (!key) {
51
92
  throw new Error('Encrypted license key found but REVEALUI_LICENSE_ENCRYPTION_KEY is not set. ' +
52
93
  'Cannot decrypt without the encryption key.');
@@ -56,15 +97,29 @@ export function decryptLicenseKey(stored) {
56
97
  throw new Error('Malformed encrypted license key - expected enc:<iv>:<ciphertext>:<tag>');
57
98
  }
58
99
  const [ivHex, ciphertextHex, tagHex] = parts;
59
- const iv = Buffer.from(ivHex, 'hex');
60
- const ciphertext = Buffer.from(ciphertextHex, 'hex');
61
- const tag = Buffer.from(tagHex, 'hex');
100
+ const iv = fromHex(ivHex);
101
+ const ciphertext = fromHex(ciphertextHex);
102
+ const tag = fromHex(tagHex);
62
103
  if (iv.length !== IV_BYTES) {
63
104
  throw new Error(`Invalid IV length: expected ${IV_BYTES} bytes, got ${iv.length}`);
64
105
  }
65
- const decipher = createDecipheriv(ALGORITHM, key, iv);
66
- decipher.setAuthTag(tag);
67
- return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('utf8');
106
+ if (tag.length !== TAG_BYTES) {
107
+ throw new Error(`Invalid auth tag length: expected ${TAG_BYTES} bytes, got ${tag.length}`);
108
+ }
109
+ // Recombine ciphertext||tag for Web Crypto's decrypt API.
110
+ const combined = new Uint8Array(ciphertext.length + tag.length);
111
+ combined.set(ciphertext, 0);
112
+ combined.set(tag, ciphertext.length);
113
+ let plaintextBuffer;
114
+ try {
115
+ plaintextBuffer = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: iv }, key, combined);
116
+ }
117
+ catch {
118
+ // Web Crypto throws an opaque OperationError on tag mismatch / wrong key.
119
+ // Normalize to a descriptive error matching the old node:crypto behavior.
120
+ throw new Error('Unsupported state or unable to authenticate data');
121
+ }
122
+ return new TextDecoder().decode(plaintextBuffer);
68
123
  }
69
124
  /**
70
125
  * Check whether a stored license key value is encrypted.
package/dist/license.d.ts CHANGED
@@ -1,18 +1,62 @@
1
1
  /**
2
2
  * License validation for RevealUI Pro/Enterprise tiers.
3
3
  *
4
+ * Edge-compatible: uses the Web Crypto API (`crypto.subtle`) and `jose`
5
+ * exclusively. Safe to import from any runtime (Node, Edge, browser,
6
+ * Workers). No `node:crypto` or filesystem dependencies.
7
+ *
4
8
  * @dependencies
5
- * - jose - JWT token verification (Web Crypto API)
9
+ * - jose - JWT signing/verification (Web Crypto API)
6
10
  * - zod - Schema validation for license payloads
7
11
  */
8
12
  import { z } from 'zod';
9
13
  /** Available license tiers */
10
14
  export type LicenseTier = 'free' | 'pro' | 'max' | 'enterprise';
15
+ /**
16
+ * License operating mode — determines how the system behaves when license
17
+ * checks encounter various failure conditions.
18
+ *
19
+ * - active: License is valid and current
20
+ * - grace: License has an issue but is within a grace period (still allowed)
21
+ * - read-only: Perpetual support lapsed past grace — reads allowed, writes blocked
22
+ * - expired: Grace period exhausted — degraded to free tier
23
+ * - invalid: Signature invalid or tampered — hard fail
24
+ * - missing: No license configured — free tier
25
+ */
26
+ export type LicenseMode = 'active' | 'grace' | 'read-only' | 'expired' | 'invalid' | 'missing';
27
+ /** Detailed result from license status check */
28
+ export interface LicenseCheckResult {
29
+ /** Whether the requested action is allowed */
30
+ allowed: boolean;
31
+ /** Current effective tier */
32
+ tier: LicenseTier;
33
+ /** Operating mode */
34
+ mode: LicenseMode;
35
+ /** Human-readable reason for the current mode */
36
+ reason?: string;
37
+ /** Milliseconds remaining in grace period (undefined if not in grace) */
38
+ graceRemainingMs?: number;
39
+ /** Whether writes should be blocked (read-only mode for lapsed perpetual) */
40
+ readOnly: boolean;
41
+ }
42
+ /** Grace period configuration (in days). Overridable via env for testing. */
43
+ export interface GracePeriodConfig {
44
+ /** Days after subscription expiry before degrading to free (default: 3) */
45
+ subscriptionDays: number;
46
+ /** Days after perpetual support lapse before read-only mode (default: 30) */
47
+ perpetualDays: number;
48
+ /** Days of cached-license grace when infra is unreachable (default: 7) */
49
+ infraDays: number;
50
+ }
51
+ /**
52
+ * Configure grace period durations. Useful for testing.
53
+ */
54
+ export declare function configureGracePeriods(overrides: Partial<GracePeriodConfig>): void;
11
55
  /** Decoded license payload schema */
12
56
  declare const licensePayloadSchema: z.ZodObject<{
13
57
  tier: z.ZodEnum<{
14
- max: "max";
15
58
  pro: "pro";
59
+ max: "max";
16
60
  enterprise: "enterprise";
17
61
  }>;
18
62
  customerId: z.ZodString;
@@ -26,7 +70,7 @@ declare const licensePayloadSchema: z.ZodObject<{
26
70
  export type LicensePayload = z.infer<typeof licensePayloadSchema>;
27
71
  /** License cache TTL configuration */
28
72
  export interface LicenseCacheConfig {
29
- /** Cache TTL in milliseconds (default: 24 hours) */
73
+ /** Cache TTL in milliseconds (default: 15 seconds) */
30
74
  ttlMs: number;
31
75
  }
32
76
  /**
@@ -37,8 +81,10 @@ export declare function configureLicenseCache(overrides: Partial<LicenseCacheCon
37
81
  /**
38
82
  * Computes a deterministic Key ID (kid) from a public key PEM string.
39
83
  * Returns the first 8 characters of the SHA-256 hex digest of the PEM.
84
+ *
85
+ * Async because it uses `crypto.subtle.digest` for full edge compatibility.
40
86
  */
41
- export declare function computeKeyId(publicKeyPem: string): string;
87
+ export declare function computeKeyId(publicKeyPem: string): Promise<string>;
42
88
  /**
43
89
  * Validates a license key JWT and returns the decoded payload.
44
90
  * Returns null if the key is invalid, expired, or missing.
@@ -63,8 +109,24 @@ export declare function getLicensePayload(): LicensePayload | null;
63
109
  /**
64
110
  * Checks whether the current license is at least the given tier.
65
111
  * Also validates that the license has not expired (checks JWT exp claim).
112
+ *
113
+ * Subscription grace: if the JWT has expired but is within the configured
114
+ * grace period (default 3 days), access is still allowed. Use
115
+ * `getLicenseStatus()` to check whether the license is in grace.
66
116
  */
67
117
  export declare function isLicensed(requiredTier: LicenseTier): boolean;
118
+ /**
119
+ * Returns the full license status including mode, grace state, and read-only flag.
120
+ *
121
+ * Use this for UI decisions (banners, warnings) and API response headers.
122
+ * For simple gate checks, `isLicensed()` is sufficient.
123
+ */
124
+ export declare function getLicenseStatus(requiredTier?: LicenseTier): LicenseCheckResult;
125
+ /**
126
+ * Returns the configured grace period durations.
127
+ * Useful for API response headers and customer-facing documentation.
128
+ */
129
+ export declare function getGraceConfig(): Readonly<GracePeriodConfig>;
68
130
  /**
69
131
  * Returns the maximum number of sites allowed by the current license.
70
132
  */
@@ -80,7 +142,8 @@ export declare function getMaxUsers(): number;
80
142
  export declare function getMaxAgentTasks(): number;
81
143
  /**
82
144
  * Generates a signed license key JWT.
83
- * This is a server-only function - requires the private key.
145
+ * Server-only in practice (requires the private key) but edge-compatible —
146
+ * `jose.importPKCS8` and `SignJWT` both run on Web Crypto.
84
147
  *
85
148
  * @param payload - License payload (tier, customerId, limits, perpetual flag)
86
149
  * @param privateKey - RS256 private key (PEM format)
@@ -1 +1 @@
1
- {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,YAAY,CAAC;AAEhE,qCAAqC;AACrC,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;iBAqBxB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;CACf;AAkBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAElF;AAoCD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0BhC;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,CAkC9D;AAaD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAGzD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CAqB7D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,KAAK,CAAC,EAC5C,UAAU,EAAE,MAAM,EAClB,gBAAgB,GAAE,MAAM,GAAG,IAAyB,EACpD,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAYjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
1
+ {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,YAAY,CAAC;AAEhE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE/F,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,qBAAqB;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;CACnB;AAmBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAEjF;AAED,qCAAqC;AACrC,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;iBAqBxB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;CACf;AAkBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAElF;AAuCD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASxE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA+BhC;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC,CA8C9D;AAaD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,IAAI,CAGzD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CA2B7D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,GAAE,WAAmB,GAAG,kBAAkB,CAkEtF;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAE5D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,KAAK,CAAC,EAC5C,UAAU,EAAE,MAAM,EAClB,gBAAgB,GAAE,MAAM,GAAG,IAAyB,EACpD,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC"}
package/dist/license.js CHANGED
@@ -1,15 +1,42 @@
1
1
  /**
2
2
  * License validation for RevealUI Pro/Enterprise tiers.
3
3
  *
4
+ * Edge-compatible: uses the Web Crypto API (`crypto.subtle`) and `jose`
5
+ * exclusively. Safe to import from any runtime (Node, Edge, browser,
6
+ * Workers). No `node:crypto` or filesystem dependencies.
7
+ *
4
8
  * @dependencies
5
- * - jose - JWT token verification (Web Crypto API)
9
+ * - jose - JWT signing/verification (Web Crypto API)
6
10
  * - zod - Schema validation for license payloads
7
11
  */
8
- import { createHash } from 'node:crypto';
9
12
  import { decodeProtectedHeader, importPKCS8, importSPKI, jwtVerify, SignJWT } from 'jose';
10
13
  import { z } from 'zod';
11
14
  import { decryptLicenseKey } from './license-encryption.js';
12
15
  import { logger } from './utils/logger.js';
16
+ /** JWT issuer and audience for license tokens — prevents cross-environment replay */
17
+ const LICENSE_ISSUER = process.env.REVEALUI_LICENSE_ISSUER ?? 'https://revealui.com';
18
+ const LICENSE_AUDIENCE = process.env.REVEALUI_LICENSE_AUDIENCE ?? 'revealui-license';
19
+ const DEFAULT_GRACE = {
20
+ subscriptionDays: parseEnvInt('LICENSE_GRACE_SUBSCRIPTION_DAYS', 3),
21
+ perpetualDays: parseEnvInt('LICENSE_GRACE_PERPETUAL_DAYS', 30),
22
+ infraDays: parseEnvInt('LICENSE_GRACE_INFRA_DAYS', 7),
23
+ };
24
+ function parseEnvInt(key, fallback) {
25
+ const val = process.env[key];
26
+ if (val) {
27
+ const parsed = Number.parseInt(val, 10);
28
+ if (Number.isFinite(parsed) && parsed >= 0)
29
+ return parsed;
30
+ }
31
+ return fallback;
32
+ }
33
+ let graceConfig = { ...DEFAULT_GRACE };
34
+ /**
35
+ * Configure grace period durations. Useful for testing.
36
+ */
37
+ export function configureGracePeriods(overrides) {
38
+ graceConfig = { ...DEFAULT_GRACE, ...overrides };
39
+ }
13
40
  /** Decoded license payload schema */
14
41
  const licensePayloadSchema = z.object({
15
42
  /** License tier */
@@ -58,6 +85,7 @@ let cachedState = {
58
85
  tier: 'free',
59
86
  payload: null,
60
87
  validatedAt: null,
88
+ keyPresentButInvalid: false,
61
89
  };
62
90
  /**
63
91
  * The public key used to verify license JWTs.
@@ -73,7 +101,7 @@ function getPublicKey() {
73
101
  * Reads the license key from environment.
74
102
  * Supports encrypted keys (enc:iv:ciphertext:tag format) via REVEALUI_LICENSE_ENCRYPTION_KEY.
75
103
  */
76
- function getLicenseKey() {
104
+ async function getLicenseKey() {
77
105
  const raw = process.env.REVEALUI_LICENSE_KEY ?? null;
78
106
  if (!raw)
79
107
  return null;
@@ -82,9 +110,18 @@ function getLicenseKey() {
82
110
  /**
83
111
  * Computes a deterministic Key ID (kid) from a public key PEM string.
84
112
  * Returns the first 8 characters of the SHA-256 hex digest of the PEM.
113
+ *
114
+ * Async because it uses `crypto.subtle.digest` for full edge compatibility.
85
115
  */
86
- export function computeKeyId(publicKeyPem) {
87
- return createHash('sha256').update(publicKeyPem).digest('hex').slice(0, 8);
116
+ export async function computeKeyId(publicKeyPem) {
117
+ const encoded = new TextEncoder().encode(publicKeyPem);
118
+ const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', encoded));
119
+ let hex = '';
120
+ // Only the first 4 bytes (8 hex chars) — enough to identify rotated keys.
121
+ for (const b of digest.subarray(0, 4)) {
122
+ hex += b.toString(16).padStart(2, '0');
123
+ }
124
+ return hex;
88
125
  }
89
126
  /**
90
127
  * Validates a license key JWT and returns the decoded payload.
@@ -94,14 +131,19 @@ export async function validateLicenseKey(licenseKey, publicKey) {
94
131
  try {
95
132
  // Extract kid from JWT header for forward-compatible key rotation
96
133
  const header = decodeProtectedHeader(licenseKey);
97
- const expectedKid = computeKeyId(publicKey);
134
+ const expectedKid = await computeKeyId(publicKey);
98
135
  if (header.kid && header.kid !== expectedKid) {
99
136
  logger.warn(`JWT kid mismatch: token has "${header.kid}", current key is "${expectedKid}". ` +
100
137
  'Token may have been signed with a rotated key.');
101
138
  }
102
139
  const key = await importSPKI(publicKey, 'RS256');
140
+ // Accept tokens expired within the subscription grace window so the
141
+ // payload is available for grace-period calculations in isLicensed().
103
142
  const { payload } = await jwtVerify(licenseKey, key, {
104
- algorithms: ['RS256', 'ES256'],
143
+ algorithms: ['RS256'],
144
+ clockTolerance: graceConfig.subscriptionDays * 86_400,
145
+ issuer: LICENSE_ISSUER,
146
+ audience: LICENSE_AUDIENCE,
105
147
  });
106
148
  const result = licensePayloadSchema.safeParse(payload);
107
149
  if (!result.success) {
@@ -120,16 +162,27 @@ export async function validateLicenseKey(licenseKey, publicKey) {
120
162
  * @returns The resolved license tier
121
163
  */
122
164
  export async function initializeLicense() {
123
- const licenseKey = getLicenseKey();
165
+ const licenseKey = await getLicenseKey();
124
166
  const publicKey = getPublicKey();
125
167
  if (!(licenseKey && publicKey)) {
126
- cachedState = { tier: 'free', payload: null, validatedAt: Date.now() };
168
+ cachedState = {
169
+ tier: 'free',
170
+ payload: null,
171
+ validatedAt: Date.now(),
172
+ keyPresentButInvalid: false,
173
+ };
127
174
  cachedAt = Date.now();
128
175
  return 'free';
129
176
  }
130
177
  const payload = await validateLicenseKey(licenseKey, publicKey);
131
178
  if (!payload) {
132
- cachedState = { tier: 'free', payload: null, validatedAt: Date.now() };
179
+ // Key was present but failed validation (expired beyond grace, invalid signature, etc.)
180
+ cachedState = {
181
+ tier: 'free',
182
+ payload: null,
183
+ validatedAt: Date.now(),
184
+ keyPresentButInvalid: true,
185
+ };
133
186
  cachedAt = Date.now();
134
187
  return 'free';
135
188
  }
@@ -137,6 +190,7 @@ export async function initializeLicense() {
137
190
  tier: payload.tier,
138
191
  payload,
139
192
  validatedAt: Date.now(),
193
+ keyPresentButInvalid: false,
140
194
  };
141
195
  cachedAt = Date.now();
142
196
  // Clamp cache TTL to license expiry so revoked licenses don't survive the full TTL
@@ -154,7 +208,7 @@ export async function initializeLicense() {
154
208
  */
155
209
  function evictStaleCache() {
156
210
  if (cachedAt > 0 && Date.now() - cachedAt > cacheConfig.ttlMs) {
157
- cachedState = { tier: 'free', payload: null, validatedAt: null };
211
+ cachedState = { tier: 'free', payload: null, validatedAt: null, keyPresentButInvalid: false };
158
212
  cachedAt = 0;
159
213
  }
160
214
  }
@@ -176,6 +230,10 @@ export function getLicensePayload() {
176
230
  /**
177
231
  * Checks whether the current license is at least the given tier.
178
232
  * Also validates that the license has not expired (checks JWT exp claim).
233
+ *
234
+ * Subscription grace: if the JWT has expired but is within the configured
235
+ * grace period (default 3 days), access is still allowed. Use
236
+ * `getLicenseStatus()` to check whether the license is in grace.
179
237
  */
180
238
  export function isLicensed(requiredTier) {
181
239
  evictStaleCache();
@@ -192,11 +250,90 @@ export function isLicensed(requiredTier) {
192
250
  if (!cachedState.payload?.perpetual && cachedState.payload?.exp) {
193
251
  const nowSeconds = Math.floor(Date.now() / 1000);
194
252
  if (cachedState.payload.exp < nowSeconds) {
253
+ // Expired — check subscription grace period
254
+ const graceEndSeconds = cachedState.payload.exp + graceConfig.subscriptionDays * 86_400;
255
+ if (nowSeconds < graceEndSeconds) {
256
+ // Within grace — still allowed, but callers should check getLicenseStatus()
257
+ return tierRank[cachedState.tier] >= tierRank[requiredTier];
258
+ }
195
259
  return false;
196
260
  }
197
261
  }
198
262
  return tierRank[cachedState.tier] >= tierRank[requiredTier];
199
263
  }
264
+ /**
265
+ * Returns the full license status including mode, grace state, and read-only flag.
266
+ *
267
+ * Use this for UI decisions (banners, warnings) and API response headers.
268
+ * For simple gate checks, `isLicensed()` is sufficient.
269
+ */
270
+ export function getLicenseStatus(requiredTier = 'pro') {
271
+ evictStaleCache();
272
+ const tierRank = {
273
+ free: 0,
274
+ pro: 1,
275
+ max: 2,
276
+ enterprise: 3,
277
+ };
278
+ // No license configured — or key was present but failed validation
279
+ if (!cachedState.payload) {
280
+ if (cachedState.keyPresentButInvalid) {
281
+ return {
282
+ allowed: requiredTier === 'free',
283
+ tier: 'free',
284
+ mode: 'expired',
285
+ reason: 'License key failed validation (expired beyond grace or invalid)',
286
+ readOnly: false,
287
+ };
288
+ }
289
+ return {
290
+ allowed: requiredTier === 'free',
291
+ tier: 'free',
292
+ mode: 'missing',
293
+ reason: 'No license configured',
294
+ readOnly: false,
295
+ };
296
+ }
297
+ const nowSeconds = Math.floor(Date.now() / 1000);
298
+ // Check subscription expiry + grace
299
+ if (!cachedState.payload.perpetual && cachedState.payload.exp) {
300
+ if (cachedState.payload.exp < nowSeconds) {
301
+ const graceEndSeconds = cachedState.payload.exp + graceConfig.subscriptionDays * 86_400;
302
+ if (nowSeconds < graceEndSeconds) {
303
+ const graceRemainingMs = (graceEndSeconds - nowSeconds) * 1000;
304
+ return {
305
+ allowed: tierRank[cachedState.tier] >= tierRank[requiredTier],
306
+ tier: cachedState.tier,
307
+ mode: 'grace',
308
+ reason: `Subscription expired, ${Math.ceil(graceRemainingMs / 86_400_000)}-day grace remaining`,
309
+ graceRemainingMs,
310
+ readOnly: false,
311
+ };
312
+ }
313
+ return {
314
+ allowed: requiredTier === 'free',
315
+ tier: 'free',
316
+ mode: 'expired',
317
+ reason: 'Subscription expired and grace period exhausted',
318
+ readOnly: false,
319
+ };
320
+ }
321
+ }
322
+ // Active license
323
+ return {
324
+ allowed: tierRank[cachedState.tier] >= tierRank[requiredTier],
325
+ tier: cachedState.tier,
326
+ mode: 'active',
327
+ readOnly: false,
328
+ };
329
+ }
330
+ /**
331
+ * Returns the configured grace period durations.
332
+ * Useful for API response headers and customer-facing documentation.
333
+ */
334
+ export function getGraceConfig() {
335
+ return graceConfig;
336
+ }
200
337
  /**
201
338
  * Returns the maximum number of sites allowed by the current license.
202
339
  */
@@ -239,7 +376,8 @@ export function getMaxAgentTasks() {
239
376
  }
240
377
  /**
241
378
  * Generates a signed license key JWT.
242
- * This is a server-only function - requires the private key.
379
+ * Server-only in practice (requires the private key) but edge-compatible —
380
+ * `jose.importPKCS8` and `SignJWT` both run on Web Crypto.
243
381
  *
244
382
  * @param payload - License payload (tier, customerId, limits, perpetual flag)
245
383
  * @param privateKey - RS256 private key (PEM format)
@@ -251,12 +389,16 @@ export function getMaxAgentTasks() {
251
389
  */
252
390
  export async function generateLicenseKey(payload, privateKey, expiresInSeconds = 365 * 24 * 60 * 60, publicKey) {
253
391
  const key = await importPKCS8(privateKey, 'RS256');
254
- const kid = publicKey ? computeKeyId(publicKey) : undefined;
392
+ const kid = publicKey ? await computeKeyId(publicKey) : undefined;
255
393
  const header = { alg: 'RS256' };
256
394
  if (kid) {
257
395
  header.kid = kid;
258
396
  }
259
- const builder = new SignJWT({ ...payload }).setProtectedHeader(header).setIssuedAt();
397
+ const builder = new SignJWT({ ...payload })
398
+ .setProtectedHeader(header)
399
+ .setIssuedAt()
400
+ .setIssuer(LICENSE_ISSUER)
401
+ .setAudience(LICENSE_AUDIENCE);
260
402
  if (expiresInSeconds !== null) {
261
403
  builder.setExpirationTime(`${expiresInSeconds}s`);
262
404
  }
@@ -266,6 +408,6 @@ export async function generateLicenseKey(payload, privateKey, expiresInSeconds =
266
408
  * Reset license state. Primarily for testing.
267
409
  */
268
410
  export function resetLicenseState() {
269
- cachedState = { tier: 'free', payload: null, validatedAt: null };
411
+ cachedState = { tier: 'free', payload: null, validatedAt: null, keyPresentButInvalid: false };
270
412
  cachedAt = 0;
271
413
  }
@@ -1,4 +1,3 @@
1
1
  export { getRevealUI } from './utilities.js';
2
2
  export type { WithRevealUIOptions } from './withRevealUI.js';
3
- export { withRevealUI } from './withRevealUI.js';
4
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,3 +1,8 @@
1
- // RevealUI Next.js integration
1
+ // RevealUI Next.js runtime integration.
2
+ //
3
+ // This barrel is intentionally runtime-only. `withRevealUI` is NOT re-exported
4
+ // here because it pulls in `node:fs` + `node:path` at module load, which Next's
5
+ // NFT tracer then attributes to every route that transitively imports this
6
+ // barrel (even via type-only paths). Config-time consumers should import it
7
+ // directly from `@revealui/core/nextjs/withRevealUI`.
2
8
  export { getRevealUI } from './utilities.js';
3
- export { withRevealUI } from './withRevealUI.js';
@@ -1,4 +1,31 @@
1
- import type { NextConfig } from 'next';
1
+ /**
2
+ * Subset of Next.js config shape used by withRevealUI.
3
+ * Defined locally to avoid requiring `next` as a dependency of @revealui/core.
4
+ * Consumers pass their full NextConfig through; we only access these fields.
5
+ */
6
+ interface NextConfig {
7
+ env?: Record<string, string | undefined>;
8
+ webpack?: (config: Record<string, unknown>, context: {
9
+ isServer: boolean;
10
+ dev: boolean;
11
+ dir: string;
12
+ [key: string]: unknown;
13
+ }) => Record<string, unknown>;
14
+ turbopack?: {
15
+ resolveAlias?: Record<string, string>;
16
+ };
17
+ headers?: () => Promise<Array<{
18
+ source: string;
19
+ headers: Array<{
20
+ key: string;
21
+ value: string;
22
+ }>;
23
+ }>>;
24
+ images?: {
25
+ remotePatterns?: Array<Record<string, unknown>>;
26
+ };
27
+ [key: string]: unknown;
28
+ }
2
29
  export interface WithRevealUIOptions {
3
30
  /** Path to the RevealUI config file (relative to Next.js project root) */
4
31
  configPath?: string;
@@ -17,4 +44,5 @@ export interface WithRevealUIOptions {
17
44
  * The alias works with both Webpack (Next.js < 15) and Turbopack (Next.js 16+).
18
45
  */
19
46
  export declare function withRevealUI(nextConfig?: NextConfig, options?: WithRevealUIOptions): NextConfig;
47
+ export {};
20
48
  //# sourceMappingURL=withRevealUI.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withRevealUI.d.ts","sourceRoot":"","sources":["../../src/nextjs/withRevealUI.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAOvC,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,GAAE,UAAe,EAC3B,OAAO,GAAE,mBAAwB,GAChC,UAAU,CAgMZ"}
1
+ {"version":3,"file":"withRevealUI.d.ts","sourceRoot":"","sources":["../../src/nextjs/withRevealUI.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,UAAU,UAAU;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,CACR,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAC9E,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IACtD,OAAO,CAAC,EAAE,MAAM,OAAO,CACrB,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,CAC1E,CAAC;IACF,MAAM,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,CAAC;IAC7D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAOD,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,GAAE,UAAe,EAC3B,OAAO,GAAE,mBAAwB,GAChC,UAAU,CAgMZ"}
@@ -40,8 +40,4 @@ export declare function logUserAction(action: string, userId?: string, context?:
40
40
  * System event logger
41
41
  */
42
42
  export declare function logSystemEvent(event: string, context?: Record<string, unknown>): void;
43
- /**
44
- * Sanitize sensitive data from logs
45
- */
46
- export declare function sanitizeLogData(data: Record<string, unknown>): Record<string, unknown>;
47
43
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,YAAY,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAKhC;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO,EACzE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,IAG/D,SAAS,QAAQ,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;QACrC,OAAO,CAAC,EAAE,MAAM,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KAC5C,CAAC;CACH,EACD,MAAM,MAAM,OAAO,CAAC,SAAS,CAAC,KAC7B,OAAO,CAAC,SAAS,CAAC,CA6CtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CASN;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAgBN;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,EAC5C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2BtF"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,YAAY,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,MAAM,wBAAwB,CAAC;AAKhC;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO,EACzE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,IAG/D,SAAS,QAAQ,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;QACrC,OAAO,CAAC,EAAE,MAAM,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KAC5C,CAAC;CACH,EACD,MAAM,MAAM,OAAO,CAAC,SAAS,CAAC,KAC7B,OAAO,CAAC,SAAS,CAAC,CA6CtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CASN;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAgBN;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,EAC5C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAMN;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKrF"}