@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.
- package/dist/api/compression.d.ts +3 -4
- package/dist/api/compression.d.ts.map +1 -1
- package/dist/api/compression.js +1 -2
- package/dist/api/rate-limit.d.ts +10 -11
- package/dist/api/rate-limit.d.ts.map +1 -1
- package/dist/api/rate-limit.js +2 -3
- package/dist/api/response-cache.d.ts +8 -9
- package/dist/api/response-cache.d.ts.map +1 -1
- package/dist/api/response-cache.js +2 -3
- package/dist/client/admin/layout.d.ts.map +1 -1
- package/dist/client/admin/layout.js +1 -3
- package/dist/generated/types/admin.d.ts +2 -2
- package/dist/generated/types/admin.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/license-encryption.d.ts +11 -2
- package/dist/license-encryption.d.ts.map +1 -1
- package/dist/license-encryption.js +77 -22
- package/dist/license.d.ts +68 -5
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +157 -15
- package/dist/nextjs/index.d.ts +0 -1
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/index.js +7 -2
- package/dist/nextjs/withRevealUI.d.ts +29 -1
- package/dist/nextjs/withRevealUI.d.ts.map +1 -1
- package/dist/observability/logger.d.ts +0 -4
- package/dist/observability/logger.d.ts.map +1 -1
- package/dist/observability/logger.js +2 -29
- package/dist/revealui.d.ts +0 -5
- package/dist/revealui.d.ts.map +1 -1
- package/dist/revealui.js +0 -10
- package/dist/richtext/exports/server/rsc.d.ts +2 -17
- package/dist/richtext/exports/server/rsc.d.ts.map +1 -1
- package/dist/richtext/exports/server/rsc.js +9 -54
- package/dist/utils/api-wrapper.d.ts +4 -6
- package/dist/utils/api-wrapper.d.ts.map +1 -1
- package/dist/utils/api-wrapper.js +6 -9
- 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
|
|
46
|
+
async function deriveKeyBytes(raw) {
|
|
16
47
|
if (/^[0-9a-f]{64}$/i.test(raw)) {
|
|
17
|
-
return
|
|
48
|
+
return fromHex(raw);
|
|
18
49
|
}
|
|
19
|
-
|
|
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
|
|
54
|
+
async function getCryptoKey(usage) {
|
|
22
55
|
const raw = process.env.REVEALUI_LICENSE_ENCRYPTION_KEY;
|
|
23
56
|
if (!raw)
|
|
24
57
|
return null;
|
|
25
|
-
|
|
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 =
|
|
69
|
+
export async function encryptLicenseKey(plaintext) {
|
|
70
|
+
const key = await getCryptoKey('encrypt');
|
|
33
71
|
if (!key)
|
|
34
72
|
return plaintext;
|
|
35
|
-
const iv =
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
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 =
|
|
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 =
|
|
60
|
-
const ciphertext =
|
|
61
|
-
const tag =
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
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:
|
|
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
|
-
*
|
|
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)
|
package/dist/license.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"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"}
|
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
|
|
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
|
-
|
|
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'
|
|
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 = {
|
|
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
|
-
|
|
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
|
-
*
|
|
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 })
|
|
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
|
}
|
package/dist/nextjs/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/nextjs/index.js
CHANGED
|
@@ -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
|
-
|
|
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":"
|
|
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
|
|
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"}
|