@revealui/core 0.15.0 → 0.15.4
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/rest.d.ts.map +1 -1
- package/dist/api/rest.js +5 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/license.d.ts +40 -3
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +232 -18
- package/dist/sentry-environment.d.ts +37 -0
- package/dist/sentry-environment.d.ts.map +1 -0
- package/dist/sentry-environment.js +129 -0
- package/package.json +9 -4
package/dist/api/rest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/api/rest.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EAGZ,cAAc,EAGd,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,cAAc;IAC7C,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACX,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/api/rest.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EAGZ,cAAc,EAGd,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,cAAc;IAC7C,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACX,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAuaD,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,QAAQ,CAAC,CAiGnB;AAGD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,gBAAgB,GACzB;IACD,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACrE,CAaA"}
|
package/dist/api/rest.js
CHANGED
|
@@ -153,8 +153,10 @@ function getCorsOriginsFromConfig(config) {
|
|
|
153
153
|
return [];
|
|
154
154
|
}
|
|
155
155
|
/**
|
|
156
|
-
* Get allowed CORS origin for a request
|
|
157
|
-
*
|
|
156
|
+
* Get allowed CORS origin for a request.
|
|
157
|
+
* The allowlist comes from config, then REVEALUI_CORS_ORIGINS.
|
|
158
|
+
* A request origin on that list is returned. A missing list, an empty list,
|
|
159
|
+
* or a non-matching origin returns an empty allow-origin so nothing is granted.
|
|
158
160
|
*/
|
|
159
161
|
function getAllowedOrigin(request, config) {
|
|
160
162
|
let allowedOrigins = getCorsOriginsFromConfig(config);
|
|
@@ -163,18 +165,10 @@ function getAllowedOrigin(request, config) {
|
|
|
163
165
|
allowedOrigins = process.env.REVEALUI_CORS_ORIGINS.split(',').map((s) => s.trim());
|
|
164
166
|
}
|
|
165
167
|
const origin = request.headers.get('origin');
|
|
166
|
-
// If config has specific origins and request origin matches, use it
|
|
167
168
|
if (allowedOrigins.length > 0 && origin && allowedOrigins.includes(origin)) {
|
|
168
169
|
return origin;
|
|
169
170
|
}
|
|
170
|
-
|
|
171
|
-
// In production, this should never be reached if CORS is properly configured
|
|
172
|
-
if (process.env.NODE_ENV === 'development') {
|
|
173
|
-
return '*';
|
|
174
|
-
}
|
|
175
|
-
// In production, if no allowed origins configured, deny all (secure default)
|
|
176
|
-
// This prevents accidental exposure in production
|
|
177
|
-
return origin || '';
|
|
171
|
+
return '';
|
|
178
172
|
}
|
|
179
173
|
/**
|
|
180
174
|
* Get standard CORS headers for a response
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type { UniversalPostgresAdapterConfig } from './database/universal-postgr
|
|
|
20
20
|
export { universalPostgresAdapter } from './database/universal-postgres.js';
|
|
21
21
|
export { createRevealUI, createRevealUIAccessRule, createRevealUIBlock, createRevealUICollection, createRevealUIField, } from './factories/index.js';
|
|
22
22
|
export { type FeatureFlags, getFeatures, getFeaturesForTier, getRequiredTier, isFeatureEnabled, } from './features.js';
|
|
23
|
-
export { computeKeyId, configureGracePeriods, configureLicenseCache, type GracePeriodConfig, generateLicenseKey, getCurrentTier, getGraceConfig, getLicensePayload, getLicenseStatus, getMaxSites, getMaxUsers, initializeLicense, isLicensed, type LicenseCacheConfig, type LicenseCheckResult, type LicenseMode, type LicensePayload, type LicenseTier, readLicenseExp, readLicenseJti, resetLicenseState, validateLicenseKey, } from './license.js';
|
|
23
|
+
export { computeKeyId, configureGracePeriods, configureLicenseCache, type GracePeriodConfig, generateLicenseKey, getCurrentTier, getGraceConfig, getLicensePayload, getLicensePublicKeyTrustManifest, getLicenseStatus, getMaxSites, getMaxUsers, initializeLicense, isLicensed, type LicenseCacheConfig, type LicenseCheckResult, type LicenseMode, type LicensePayload, type LicensePublicKeyTrustManifest, type LicenseTier, readLicenseExp, readLicenseJti, resetLicenseState, validateLicenseKey, } from './license.js';
|
|
24
24
|
export { getRevealUI as getRevealUINext } from './nextjs/index.js';
|
|
25
25
|
export { formBuilderPlugin } from './plugins/form-builder.js';
|
|
26
26
|
export { nestedDocsPlugin } from './plugins/nested-docs.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ export { universalPostgresAdapter } from './database/universal-postgres.js';
|
|
|
36
36
|
export { createRevealUI, createRevealUIAccessRule, createRevealUIBlock, createRevealUICollection, createRevealUIField, } from './factories/index.js';
|
|
37
37
|
export { getFeatures, getFeaturesForTier, getRequiredTier, isFeatureEnabled, } from './features.js';
|
|
38
38
|
// License and feature flags
|
|
39
|
-
export { computeKeyId, configureGracePeriods, configureLicenseCache, generateLicenseKey, getCurrentTier, getGraceConfig, getLicensePayload, getLicenseStatus, getMaxSites, getMaxUsers, initializeLicense, isLicensed, readLicenseExp, readLicenseJti, resetLicenseState, validateLicenseKey, } from './license.js';
|
|
39
|
+
export { computeKeyId, configureGracePeriods, configureLicenseCache, generateLicenseKey, getCurrentTier, getGraceConfig, getLicensePayload, getLicensePublicKeyTrustManifest, getLicenseStatus, getMaxSites, getMaxUsers, initializeLicense, isLicensed, readLicenseExp, readLicenseJti, resetLicenseState, validateLicenseKey, } from './license.js';
|
|
40
40
|
// Next.js integration
|
|
41
41
|
// Note: `withRevealUI` is intentionally NOT re-exported here — it pulls in
|
|
42
42
|
// `node:fs` at module load, which causes Next's NFT tracer to pull the whole
|
package/dist/license.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type LicenseTier = 'free' | 'pro' | 'max' | 'enterprise';
|
|
|
18
18
|
*
|
|
19
19
|
* - active: License is valid and current
|
|
20
20
|
* - grace: License has an issue but is within a grace period (still allowed)
|
|
21
|
-
* - read-only:
|
|
21
|
+
* - read-only: Reserved compatibility state; support lapse does not block perpetual writes
|
|
22
22
|
* - expired: Grace period exhausted — degraded to free tier
|
|
23
23
|
* - invalid: Signature invalid or tampered — hard fail
|
|
24
24
|
* - missing: No license configured — free tier
|
|
@@ -36,14 +36,14 @@ export interface LicenseCheckResult {
|
|
|
36
36
|
reason?: string;
|
|
37
37
|
/** Milliseconds remaining in grace period (undefined if not in grace) */
|
|
38
38
|
graceRemainingMs?: number;
|
|
39
|
-
/** Whether writes should be blocked
|
|
39
|
+
/** Whether writes should be blocked; perpetual support lapse does not set this flag */
|
|
40
40
|
readOnly: boolean;
|
|
41
41
|
}
|
|
42
42
|
/** Grace period configuration (in days). Overridable via env for testing. */
|
|
43
43
|
export interface GracePeriodConfig {
|
|
44
44
|
/** Days after subscription expiry before degrading to free (default: 3) */
|
|
45
45
|
subscriptionDays: number;
|
|
46
|
-
/**
|
|
46
|
+
/** Deprecated compatibility setting; does not limit acquired perpetual runtime access */
|
|
47
47
|
perpetualDays: number;
|
|
48
48
|
/** Days of cached-license grace when infra is unreachable (default: 7) */
|
|
49
49
|
infraDays: number;
|
|
@@ -140,6 +140,35 @@ export declare function readPemEnv(name: string, env?: Record<string, string | u
|
|
|
140
140
|
* live request.
|
|
141
141
|
*/
|
|
142
142
|
export declare function getPublicKeys(): string[];
|
|
143
|
+
type LicensePublicKeyRole = 'current' | 'next';
|
|
144
|
+
declare const LICENSE_TRUST_ISSUER = "https://revealui.com";
|
|
145
|
+
declare const LICENSE_TRUST_AUDIENCE = "revealui-license";
|
|
146
|
+
export type LicensePublicKeyTrustManifest = {
|
|
147
|
+
version: 1;
|
|
148
|
+
issuer: typeof LICENSE_TRUST_ISSUER;
|
|
149
|
+
audience: typeof LICENSE_TRUST_AUDIENCE;
|
|
150
|
+
keys: Array<{
|
|
151
|
+
role: LicensePublicKeyRole;
|
|
152
|
+
algorithm: 'EdDSA';
|
|
153
|
+
publicKey: string;
|
|
154
|
+
jwtKid: string;
|
|
155
|
+
keyId: string;
|
|
156
|
+
}>;
|
|
157
|
+
digest: string;
|
|
158
|
+
/** Compatibility field for clients of the original current-key response. */
|
|
159
|
+
publicKey: string;
|
|
160
|
+
};
|
|
161
|
+
export type LicenseTrustVerification = {
|
|
162
|
+
payload: LicensePayload;
|
|
163
|
+
verifiedKeyId: string;
|
|
164
|
+
trustSetDigest: string;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* Build the public, versioned trust manifest from the same ordered key snapshot
|
|
168
|
+
* consumed by license verification. Any malformed configured key makes the
|
|
169
|
+
* endpoint fail closed; a malformed NEXT entry is never silently discarded.
|
|
170
|
+
*/
|
|
171
|
+
export declare function getLicensePublicKeyTrustManifest(): Promise<LicensePublicKeyTrustManifest>;
|
|
143
172
|
/**
|
|
144
173
|
* Computes a deterministic Key ID (kid) from a public key PEM string.
|
|
145
174
|
* Returns the first 8 characters of the SHA-256 hex digest of the PEM.
|
|
@@ -173,6 +202,12 @@ export declare function computeKeyId(publicKeyPem: string): Promise<string>;
|
|
|
173
202
|
* options below. Signature is enforced via the public key.
|
|
174
203
|
*/
|
|
175
204
|
export declare function validateLicenseKey(licenseKey: string, publicKey: string | readonly string[], expectedCustomerId?: string): Promise<LicensePayload | null>;
|
|
205
|
+
/**
|
|
206
|
+
* Verify against one already-built trust manifest and identify the exact
|
|
207
|
+
* configured key that accepted the token. The returned digest and key ID let
|
|
208
|
+
* a strict online verifier bind its result to the same set the caller fetched.
|
|
209
|
+
*/
|
|
210
|
+
export declare function validateLicenseKeyAgainstTrustManifest(licenseKey: string, manifest: LicensePublicKeyTrustManifest, expectedCustomerId?: string): Promise<LicenseTrustVerification | null>;
|
|
176
211
|
/**
|
|
177
212
|
* How far past `exp` a license JWT is still accepted by the refresh endpoint
|
|
178
213
|
* (GAP-287 PR-1). Ratified by the owner 2026-07-18 at 30 days.
|
|
@@ -201,6 +236,8 @@ export declare const REFRESH_ACCEPT_DAYS = 30;
|
|
|
201
236
|
* the bind succeeds. It never mints and never grants entitlement on its own.
|
|
202
237
|
*/
|
|
203
238
|
export declare function validateLicenseKeyForRefresh(licenseKey: string, publicKey: string | readonly string[], expectedCustomerId: string, refreshAcceptDays?: number): Promise<LicensePayload | null>;
|
|
239
|
+
/** Authenticated operator containment: validates issuer/signature/customer, not entitlement expiry. */
|
|
240
|
+
export declare function validateLicenseKeyForOperator(licenseKey: string, publicKey: string | readonly string[], expectedCustomerId: string): Promise<LicensePayload | null>;
|
|
204
241
|
/**
|
|
205
242
|
* Outcome of a signing-keypair self-test. See {@link selfVerifyLicenseKeypair}.
|
|
206
243
|
*/
|
package/dist/license.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,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,
|
|
1
|
+
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"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"}
|
package/dist/license.js
CHANGED
|
@@ -162,10 +162,10 @@ export function readPemEnv(name, env = process.env) {
|
|
|
162
162
|
const raw = env[name];
|
|
163
163
|
if (raw === undefined)
|
|
164
164
|
return undefined;
|
|
165
|
-
const trimmed = raw.trim();
|
|
165
|
+
const trimmed = normalizePem(raw).trim();
|
|
166
166
|
if (trimmed.length === 0)
|
|
167
167
|
return undefined;
|
|
168
|
-
return
|
|
168
|
+
return trimmed;
|
|
169
169
|
}
|
|
170
170
|
/**
|
|
171
171
|
* The ordered public-key candidates used to verify license JWTs.
|
|
@@ -183,14 +183,133 @@ export function readPemEnv(name, env = process.env) {
|
|
|
183
183
|
* live request.
|
|
184
184
|
*/
|
|
185
185
|
export function getPublicKeys() {
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
return getPublicKeySnapshot().map(({ publicKey }) => publicKey);
|
|
187
|
+
}
|
|
188
|
+
const LICENSE_TRUST_ISSUER = 'https://revealui.com';
|
|
189
|
+
const LICENSE_TRUST_AUDIENCE = 'revealui-license';
|
|
190
|
+
const LICENSE_TRUST_MANIFEST_MAX_BYTES = 16 * 1024;
|
|
191
|
+
const LICENSE_TRUST_PEM_MAX_BYTES = 2 * 1024;
|
|
192
|
+
const LICENSE_TRUST_SPKI_BEGIN = '-----BEGIN PUBLIC KEY-----';
|
|
193
|
+
const LICENSE_TRUST_SPKI_END = '-----END PUBLIC KEY-----';
|
|
194
|
+
function getPublicKeySnapshot() {
|
|
195
|
+
const current = readPemEnv('REVEALUI_LICENSE_PUBLIC_KEY');
|
|
196
|
+
const next = readPemEnv('REVEALUI_LICENSE_PUBLIC_KEY_NEXT');
|
|
197
|
+
const candidates = [];
|
|
188
198
|
if (current)
|
|
189
|
-
|
|
190
|
-
const next = process.env.REVEALUI_LICENSE_PUBLIC_KEY_NEXT;
|
|
199
|
+
candidates.push({ role: 'current', publicKey: current });
|
|
191
200
|
if (next)
|
|
192
|
-
|
|
193
|
-
return
|
|
201
|
+
candidates.push({ role: 'next', publicKey: next });
|
|
202
|
+
return candidates;
|
|
203
|
+
}
|
|
204
|
+
function toHex(bytes) {
|
|
205
|
+
let hex = '';
|
|
206
|
+
for (const byte of bytes)
|
|
207
|
+
hex += byte.toString(16).padStart(2, '0');
|
|
208
|
+
return hex;
|
|
209
|
+
}
|
|
210
|
+
function decodePublicKeySpki(publicKeyPem) {
|
|
211
|
+
if (new TextEncoder().encode(publicKeyPem).byteLength > LICENSE_TRUST_PEM_MAX_BYTES) {
|
|
212
|
+
throw new Error('License public key exceeds the supported size');
|
|
213
|
+
}
|
|
214
|
+
if (!(publicKeyPem.startsWith(LICENSE_TRUST_SPKI_BEGIN) &&
|
|
215
|
+
publicKeyPem.endsWith(LICENSE_TRUST_SPKI_END))) {
|
|
216
|
+
throw new Error('License trust entries must contain a public SPKI PEM');
|
|
217
|
+
}
|
|
218
|
+
const body = publicKeyPem
|
|
219
|
+
.slice(LICENSE_TRUST_SPKI_BEGIN.length, -LICENSE_TRUST_SPKI_END.length)
|
|
220
|
+
.split('\n')
|
|
221
|
+
.join('')
|
|
222
|
+
.split('\r')
|
|
223
|
+
.join('');
|
|
224
|
+
if (body.length === 0 || body.includes('-')) {
|
|
225
|
+
throw new Error('License public key PEM body is invalid');
|
|
226
|
+
}
|
|
227
|
+
let binary;
|
|
228
|
+
try {
|
|
229
|
+
binary = atob(body);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
throw new Error('License public key PEM body is invalid');
|
|
233
|
+
}
|
|
234
|
+
if (btoa(binary) !== body)
|
|
235
|
+
throw new Error('License public key PEM body is not canonical base64');
|
|
236
|
+
const der = new Uint8Array(binary.length);
|
|
237
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
238
|
+
der[index] = binary.charCodeAt(index);
|
|
239
|
+
}
|
|
240
|
+
return der;
|
|
241
|
+
}
|
|
242
|
+
async function describeLicensePublicKey(candidate) {
|
|
243
|
+
const spki = decodePublicKeySpki(candidate.publicKey);
|
|
244
|
+
const spkiBuffer = new ArrayBuffer(spki.byteLength);
|
|
245
|
+
new Uint8Array(spkiBuffer).set(spki);
|
|
246
|
+
const key = await crypto.subtle.importKey('spki', spkiBuffer, { name: 'Ed25519' }, true, [
|
|
247
|
+
'verify',
|
|
248
|
+
]);
|
|
249
|
+
if (key.algorithm.name !== 'Ed25519') {
|
|
250
|
+
throw new Error('License trust entries must use Ed25519');
|
|
251
|
+
}
|
|
252
|
+
const canonicalSpki = new Uint8Array(await crypto.subtle.exportKey('spki', key));
|
|
253
|
+
if (canonicalSpki.length !== spki.length ||
|
|
254
|
+
canonicalSpki.some((byte, index) => byte !== spki[index])) {
|
|
255
|
+
throw new Error('License public key SPKI is not canonical');
|
|
256
|
+
}
|
|
257
|
+
const keyId = toHex(new Uint8Array(await crypto.subtle.digest('SHA-256', canonicalSpki)));
|
|
258
|
+
const jwtKid = await computeKeyId(candidate.publicKey);
|
|
259
|
+
return {
|
|
260
|
+
role: candidate.role,
|
|
261
|
+
algorithm: 'EdDSA',
|
|
262
|
+
publicKey: candidate.publicKey,
|
|
263
|
+
jwtKid,
|
|
264
|
+
keyId,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Build the public, versioned trust manifest from the same ordered key snapshot
|
|
269
|
+
* consumed by license verification. Any malformed configured key makes the
|
|
270
|
+
* endpoint fail closed; a malformed NEXT entry is never silently discarded.
|
|
271
|
+
*/
|
|
272
|
+
export async function getLicensePublicKeyTrustManifest() {
|
|
273
|
+
if (LICENSE_ISSUER !== LICENSE_TRUST_ISSUER || LICENSE_AUDIENCE !== LICENSE_TRUST_AUDIENCE) {
|
|
274
|
+
throw new Error('License issuer configuration does not match the hosted trust contract');
|
|
275
|
+
}
|
|
276
|
+
const snapshot = getPublicKeySnapshot();
|
|
277
|
+
if (snapshot.length === 0 || snapshot[0]?.role !== 'current' || snapshot.length > 2) {
|
|
278
|
+
throw new Error('License current public key is not configured');
|
|
279
|
+
}
|
|
280
|
+
const keys = await Promise.all(snapshot.map(describeLicensePublicKey));
|
|
281
|
+
const keyIds = new Set();
|
|
282
|
+
const jwtKids = new Set();
|
|
283
|
+
for (const key of keys) {
|
|
284
|
+
if (keyIds.has(key.keyId) || jwtKids.has(key.jwtKid)) {
|
|
285
|
+
throw new Error('License trust set contains duplicate key identities');
|
|
286
|
+
}
|
|
287
|
+
keyIds.add(key.keyId);
|
|
288
|
+
jwtKids.add(key.jwtKid);
|
|
289
|
+
}
|
|
290
|
+
const version = 1;
|
|
291
|
+
const digestInput = JSON.stringify({
|
|
292
|
+
version,
|
|
293
|
+
issuer: LICENSE_TRUST_ISSUER,
|
|
294
|
+
audience: LICENSE_TRUST_AUDIENCE,
|
|
295
|
+
keys: keys.map(({ role, algorithm, keyId }) => ({ role, algorithm, keyId })),
|
|
296
|
+
});
|
|
297
|
+
const digest = toHex(new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(digestInput))));
|
|
298
|
+
const current = keys[0];
|
|
299
|
+
if (!current)
|
|
300
|
+
throw new Error('License current public key is not configured');
|
|
301
|
+
const manifest = {
|
|
302
|
+
version,
|
|
303
|
+
issuer: LICENSE_TRUST_ISSUER,
|
|
304
|
+
audience: LICENSE_TRUST_AUDIENCE,
|
|
305
|
+
keys,
|
|
306
|
+
digest,
|
|
307
|
+
publicKey: current.publicKey,
|
|
308
|
+
};
|
|
309
|
+
if (new TextEncoder().encode(JSON.stringify(manifest)).byteLength > LICENSE_TRUST_MANIFEST_MAX_BYTES) {
|
|
310
|
+
throw new Error('License trust manifest exceeds the supported size');
|
|
311
|
+
}
|
|
312
|
+
return manifest;
|
|
194
313
|
}
|
|
195
314
|
/**
|
|
196
315
|
* Reads the license key from environment.
|
|
@@ -248,6 +367,79 @@ export async function validateLicenseKey(licenseKey, publicKey, expectedCustomer
|
|
|
248
367
|
// is available for grace-period calculations in isLicensed().
|
|
249
368
|
return verifyAndParseLicenseJwt(licenseKey, publicKey, graceConfig.subscriptionDays * 86_400, expectedCustomerId);
|
|
250
369
|
}
|
|
370
|
+
/**
|
|
371
|
+
* Verify against one already-built trust manifest and identify the exact
|
|
372
|
+
* configured key that accepted the token. The returned digest and key ID let
|
|
373
|
+
* a strict online verifier bind its result to the same set the caller fetched.
|
|
374
|
+
*/
|
|
375
|
+
export async function validateLicenseKeyAgainstTrustManifest(licenseKey, manifest, expectedCustomerId) {
|
|
376
|
+
try {
|
|
377
|
+
// Detach from the caller before the first await. Callers may retain and
|
|
378
|
+
// mutate their input object while signature verification is in flight.
|
|
379
|
+
const snapshot = Object.freeze({
|
|
380
|
+
version: manifest.version,
|
|
381
|
+
issuer: manifest.issuer,
|
|
382
|
+
audience: manifest.audience,
|
|
383
|
+
digest: manifest.digest,
|
|
384
|
+
publicKey: manifest.publicKey,
|
|
385
|
+
keys: Array.isArray(manifest.keys)
|
|
386
|
+
? Object.freeze(manifest.keys.map((key) => Object.freeze({ ...key })))
|
|
387
|
+
: manifest.keys,
|
|
388
|
+
});
|
|
389
|
+
if (snapshot.version !== 1 ||
|
|
390
|
+
snapshot.issuer !== LICENSE_TRUST_ISSUER ||
|
|
391
|
+
snapshot.audience !== LICENSE_TRUST_AUDIENCE ||
|
|
392
|
+
!/^[0-9a-f]{64}$/.test(snapshot.digest) ||
|
|
393
|
+
!Array.isArray(snapshot.keys) ||
|
|
394
|
+
snapshot.keys.length === 0 ||
|
|
395
|
+
snapshot.keys.length > 2 ||
|
|
396
|
+
snapshot.keys[0]?.role !== 'current' ||
|
|
397
|
+
snapshot.keys.some((key, index) => key.role !== (index === 0 ? 'current' : 'next'))) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
const described = await Promise.all(snapshot.keys.map((key) => describeLicensePublicKey({ role: key.role, publicKey: key.publicKey })));
|
|
401
|
+
const keyIds = new Set();
|
|
402
|
+
const jwtKids = new Set();
|
|
403
|
+
for (let index = 0; index < described.length; index += 1) {
|
|
404
|
+
const actual = described[index];
|
|
405
|
+
const supplied = snapshot.keys[index];
|
|
406
|
+
if (!(actual && supplied) ||
|
|
407
|
+
actual.algorithm !== supplied.algorithm ||
|
|
408
|
+
actual.keyId !== supplied.keyId ||
|
|
409
|
+
actual.jwtKid !== supplied.jwtKid ||
|
|
410
|
+
keyIds.has(actual.keyId) ||
|
|
411
|
+
jwtKids.has(actual.jwtKid)) {
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
keyIds.add(actual.keyId);
|
|
415
|
+
jwtKids.add(actual.jwtKid);
|
|
416
|
+
}
|
|
417
|
+
const digestInput = JSON.stringify({
|
|
418
|
+
version: snapshot.version,
|
|
419
|
+
issuer: snapshot.issuer,
|
|
420
|
+
audience: snapshot.audience,
|
|
421
|
+
keys: described.map(({ role, algorithm, keyId }) => ({ role, algorithm, keyId })),
|
|
422
|
+
});
|
|
423
|
+
const expectedDigest = toHex(new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(digestInput))));
|
|
424
|
+
if (snapshot.digest !== expectedDigest || snapshot.publicKey !== described[0]?.publicKey) {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
for (const key of described) {
|
|
428
|
+
const payload = await validateLicenseKey(licenseKey, key.publicKey, expectedCustomerId);
|
|
429
|
+
if (payload) {
|
|
430
|
+
return {
|
|
431
|
+
payload,
|
|
432
|
+
verifiedKeyId: key.keyId,
|
|
433
|
+
trustSetDigest: snapshot.digest,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
catch {
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
251
443
|
/**
|
|
252
444
|
* How far past `exp` a license JWT is still accepted by the refresh endpoint
|
|
253
445
|
* (GAP-287 PR-1). Ratified by the owner 2026-07-18 at 30 days.
|
|
@@ -281,6 +473,12 @@ export async function validateLicenseKeyForRefresh(licenseKey, publicKey, expect
|
|
|
281
473
|
return null;
|
|
282
474
|
return verifyAndParseLicenseJwt(licenseKey, publicKey, refreshAcceptDays * 86_400, bound);
|
|
283
475
|
}
|
|
476
|
+
/** Authenticated operator containment: validates issuer/signature/customer, not entitlement expiry. */
|
|
477
|
+
export async function validateLicenseKeyForOperator(licenseKey, publicKey, expectedCustomerId) {
|
|
478
|
+
if (!expectedCustomerId.trim())
|
|
479
|
+
return null;
|
|
480
|
+
return verifyAndParseLicenseJwt(licenseKey, publicKey, 0, expectedCustomerId, true);
|
|
481
|
+
}
|
|
284
482
|
/**
|
|
285
483
|
* Shared verify + parse path for {@link validateLicenseKey} and
|
|
286
484
|
* {@link validateLicenseKeyForRefresh}. The ONLY behavioral difference between
|
|
@@ -288,7 +486,7 @@ export async function validateLicenseKeyForRefresh(licenseKey, publicKey, expect
|
|
|
288
486
|
* still accepted — so the rotation-aware multi-key loop and the payload schema
|
|
289
487
|
* live in exactly one place.
|
|
290
488
|
*/
|
|
291
|
-
async function verifyAndParseLicenseJwt(licenseKey, publicKey, clockToleranceSeconds, expectedCustomerId) {
|
|
489
|
+
async function verifyAndParseLicenseJwt(licenseKey, publicKey, clockToleranceSeconds, expectedCustomerId, operator = false) {
|
|
292
490
|
const candidates = typeof publicKey === 'string' ? [publicKey] : [...publicKey];
|
|
293
491
|
if (candidates.length === 0)
|
|
294
492
|
return null;
|
|
@@ -303,12 +501,27 @@ async function verifyAndParseLicenseJwt(licenseKey, publicKey, clockToleranceSec
|
|
|
303
501
|
for (const candidate of ordered) {
|
|
304
502
|
try {
|
|
305
503
|
const key = await jose.importSPKI(candidate, 'EdDSA');
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
504
|
+
let payload;
|
|
505
|
+
if (operator) {
|
|
506
|
+
const verified = await jose.compactVerify(licenseKey, key, { algorithms: ['EdDSA'] });
|
|
507
|
+
const claims = JSON.parse(new TextDecoder().decode(verified.payload));
|
|
508
|
+
if (claims.iss !== LICENSE_ISSUER ||
|
|
509
|
+
!(claims.aud === LICENSE_AUDIENCE ||
|
|
510
|
+
(Array.isArray(claims.aud) && claims.aud.includes(LICENSE_AUDIENCE))) ||
|
|
511
|
+
(claims.nbf !== undefined &&
|
|
512
|
+
(typeof claims.nbf !== 'number' || claims.nbf > Date.now() / 1000))) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
payload = claims;
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
({ payload } = await jose.jwtVerify(licenseKey, key, {
|
|
519
|
+
algorithms: ['EdDSA'],
|
|
520
|
+
clockTolerance: clockToleranceSeconds,
|
|
521
|
+
issuer: LICENSE_ISSUER,
|
|
522
|
+
audience: LICENSE_AUDIENCE,
|
|
523
|
+
}));
|
|
524
|
+
}
|
|
312
525
|
verifiedPayload = payload;
|
|
313
526
|
verified = true;
|
|
314
527
|
break;
|
|
@@ -882,17 +1095,18 @@ export async function generateLicenseKey(payload, privateKey, expiresInSeconds =
|
|
|
882
1095
|
// Strip the optional jti from the spread so jose.setJti() is the single
|
|
883
1096
|
// source of the claim (avoids a duplicate field in the payload).
|
|
884
1097
|
const { jti: _ignoredJti, ...rest } = payload;
|
|
1098
|
+
const issuedAt = Math.floor(Date.now() / 1000);
|
|
885
1099
|
const builder = new jose.SignJWT({ ...rest })
|
|
886
1100
|
.setProtectedHeader(header)
|
|
887
|
-
.setIssuedAt()
|
|
1101
|
+
.setIssuedAt(issuedAt)
|
|
888
1102
|
// Phase 1 audit B-2: enforce nbf so tokens cannot be replayed pre-issue
|
|
889
1103
|
// by a clock-skewed client.
|
|
890
|
-
.setNotBefore(
|
|
1104
|
+
.setNotBefore(issuedAt)
|
|
891
1105
|
.setJti(jti)
|
|
892
1106
|
.setIssuer(LICENSE_ISSUER)
|
|
893
1107
|
.setAudience(LICENSE_AUDIENCE);
|
|
894
1108
|
if (expiresInSeconds !== null) {
|
|
895
|
-
builder.setExpirationTime(
|
|
1109
|
+
builder.setExpirationTime(issuedAt + expiresInSeconds);
|
|
896
1110
|
}
|
|
897
1111
|
return builder.sign(key);
|
|
898
1112
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentry `environment` for a deploy.
|
|
3
|
+
*
|
|
4
|
+
* `NODE_ENV=production` is set on staging as well as production, so it is not
|
|
5
|
+
* a safe Sentry label. Prefer `SENTRY_ENVIRONMENT` (then `REVEALUI_DEPLOY_ENV`,
|
|
6
|
+
* then `NEXT_PUBLIC_SENTRY_ENVIRONMENT`). When those are unset, derive the
|
|
7
|
+
* label from public hosts. A `*.staging.revealui.com` host is never reported
|
|
8
|
+
* as production. Vercel preview stays `preview`.
|
|
9
|
+
*/
|
|
10
|
+
export type SentryEnvironmentName = 'production' | 'staging' | 'preview' | 'development' | 'test';
|
|
11
|
+
/** Non-secret label. Set `SENTRY_ENVIRONMENT=staging` on staging Vercel and Fly. */
|
|
12
|
+
export declare const SENTRY_ENVIRONMENT_VAR = "SENTRY_ENVIRONMENT";
|
|
13
|
+
export interface SentryEnvironmentSource {
|
|
14
|
+
SENTRY_ENVIRONMENT?: string | undefined;
|
|
15
|
+
REVEALUI_DEPLOY_ENV?: string | undefined;
|
|
16
|
+
NEXT_PUBLIC_SENTRY_ENVIRONMENT?: string | undefined;
|
|
17
|
+
NODE_ENV?: string | undefined;
|
|
18
|
+
VERCEL_ENV?: string | undefined;
|
|
19
|
+
REVEALUI_API_URL?: string | undefined;
|
|
20
|
+
NEXT_PUBLIC_API_URL?: string | undefined;
|
|
21
|
+
API_URL?: string | undefined;
|
|
22
|
+
REVEALUI_PUBLIC_SERVER_URL?: string | undefined;
|
|
23
|
+
NEXT_PUBLIC_SERVER_URL?: string | undefined;
|
|
24
|
+
VERCEL_PROJECT_PRODUCTION_URL?: string | undefined;
|
|
25
|
+
VERCEL_URL?: string | undefined;
|
|
26
|
+
SESSION_COOKIE_DOMAIN?: string | undefined;
|
|
27
|
+
PASSKEY_RP_ID?: string | undefined;
|
|
28
|
+
PASSKEY_ORIGIN?: string | undefined;
|
|
29
|
+
CORS_ORIGIN?: string | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the Sentry environment label.
|
|
33
|
+
* Staging hosts report `staging`, or `preview` when that explicit label is set.
|
|
34
|
+
* They do not report `production`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveSentryEnvironment(env: SentryEnvironmentSource): SentryEnvironmentName;
|
|
37
|
+
//# sourceMappingURL=sentry-environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sentry-environment.d.ts","sourceRoot":"","sources":["../src/sentry-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC;AAElG,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACtC,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,8BAA8B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,0BAA0B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,6BAA6B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAyED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,uBAAuB,GAAG,qBAAqB,CAoD5F"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentry `environment` for a deploy.
|
|
3
|
+
*
|
|
4
|
+
* `NODE_ENV=production` is set on staging as well as production, so it is not
|
|
5
|
+
* a safe Sentry label. Prefer `SENTRY_ENVIRONMENT` (then `REVEALUI_DEPLOY_ENV`,
|
|
6
|
+
* then `NEXT_PUBLIC_SENTRY_ENVIRONMENT`). When those are unset, derive the
|
|
7
|
+
* label from public hosts. A `*.staging.revealui.com` host is never reported
|
|
8
|
+
* as production. Vercel preview stays `preview`.
|
|
9
|
+
*/
|
|
10
|
+
import { isStagingRevealHost, normalizeRequestHost } from './session-cookie-domain.js';
|
|
11
|
+
/** Non-secret label. Set `SENTRY_ENVIRONMENT=staging` on staging Vercel and Fly. */
|
|
12
|
+
export const SENTRY_ENVIRONMENT_VAR = 'SENTRY_ENVIRONMENT';
|
|
13
|
+
const HOST_KEYS = [
|
|
14
|
+
'REVEALUI_API_URL',
|
|
15
|
+
'NEXT_PUBLIC_API_URL',
|
|
16
|
+
'API_URL',
|
|
17
|
+
'REVEALUI_PUBLIC_SERVER_URL',
|
|
18
|
+
'NEXT_PUBLIC_SERVER_URL',
|
|
19
|
+
'VERCEL_PROJECT_PRODUCTION_URL',
|
|
20
|
+
'VERCEL_URL',
|
|
21
|
+
'SESSION_COOKIE_DOMAIN',
|
|
22
|
+
'PASSKEY_RP_ID',
|
|
23
|
+
'PASSKEY_ORIGIN',
|
|
24
|
+
'CORS_ORIGIN',
|
|
25
|
+
];
|
|
26
|
+
const PRODUCTION_HOSTS = new Set([
|
|
27
|
+
'revealui.com',
|
|
28
|
+
'www.revealui.com',
|
|
29
|
+
'api.revealui.com',
|
|
30
|
+
'admin.revealui.com',
|
|
31
|
+
'docs.revealui.com',
|
|
32
|
+
]);
|
|
33
|
+
function lockedEnvironment(raw) {
|
|
34
|
+
if (raw == null)
|
|
35
|
+
return null;
|
|
36
|
+
const value = raw.trim().toLowerCase();
|
|
37
|
+
switch (value) {
|
|
38
|
+
case 'production':
|
|
39
|
+
case 'staging':
|
|
40
|
+
case 'preview':
|
|
41
|
+
case 'development':
|
|
42
|
+
case 'test':
|
|
43
|
+
return value;
|
|
44
|
+
default:
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function firstLocked(...values) {
|
|
49
|
+
for (const value of values) {
|
|
50
|
+
const locked = lockedEnvironment(value);
|
|
51
|
+
if (locked)
|
|
52
|
+
return locked;
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function splitComma(raw) {
|
|
57
|
+
const parts = [];
|
|
58
|
+
let start = 0;
|
|
59
|
+
for (let index = 0; index <= raw.length; index += 1) {
|
|
60
|
+
if (index === raw.length || raw.charCodeAt(index) === 44) {
|
|
61
|
+
const part = raw.slice(start, index).trim();
|
|
62
|
+
if (part.length > 0)
|
|
63
|
+
parts.push(part);
|
|
64
|
+
start = index + 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return parts;
|
|
68
|
+
}
|
|
69
|
+
function collectHosts(env) {
|
|
70
|
+
const hosts = [];
|
|
71
|
+
for (const key of HOST_KEYS) {
|
|
72
|
+
const raw = env[key];
|
|
73
|
+
if (typeof raw !== 'string' || raw.trim().length === 0)
|
|
74
|
+
continue;
|
|
75
|
+
for (const part of splitComma(raw)) {
|
|
76
|
+
const host = normalizeRequestHost(part);
|
|
77
|
+
if (host)
|
|
78
|
+
hosts.push(host);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return hosts;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Resolve the Sentry environment label.
|
|
85
|
+
* Staging hosts report `staging`, or `preview` when that explicit label is set.
|
|
86
|
+
* They do not report `production`.
|
|
87
|
+
*/
|
|
88
|
+
export function resolveSentryEnvironment(env) {
|
|
89
|
+
const hosts = collectHosts(env);
|
|
90
|
+
let stagingHost = false;
|
|
91
|
+
let productionHost = false;
|
|
92
|
+
for (const host of hosts) {
|
|
93
|
+
if (isStagingRevealHost(host))
|
|
94
|
+
stagingHost = true;
|
|
95
|
+
if (PRODUCTION_HOSTS.has(host))
|
|
96
|
+
productionHost = true;
|
|
97
|
+
}
|
|
98
|
+
const explicit = firstLocked(env.SENTRY_ENVIRONMENT, env.REVEALUI_DEPLOY_ENV, env.NEXT_PUBLIC_SENTRY_ENVIRONMENT);
|
|
99
|
+
if (stagingHost) {
|
|
100
|
+
if (explicit === 'staging' ||
|
|
101
|
+
explicit === 'preview' ||
|
|
102
|
+
explicit === 'development' ||
|
|
103
|
+
explicit === 'test') {
|
|
104
|
+
return explicit;
|
|
105
|
+
}
|
|
106
|
+
return 'staging';
|
|
107
|
+
}
|
|
108
|
+
if (explicit)
|
|
109
|
+
return explicit;
|
|
110
|
+
if (productionHost)
|
|
111
|
+
return 'production';
|
|
112
|
+
const vercel = lockedEnvironment(env.VERCEL_ENV);
|
|
113
|
+
if (vercel === 'preview' ||
|
|
114
|
+
vercel === 'development' ||
|
|
115
|
+
vercel === 'test' ||
|
|
116
|
+
vercel === 'staging') {
|
|
117
|
+
return vercel;
|
|
118
|
+
}
|
|
119
|
+
const nodeEnv = lockedEnvironment(env.NODE_ENV);
|
|
120
|
+
if (nodeEnv === 'development' ||
|
|
121
|
+
nodeEnv === 'test' ||
|
|
122
|
+
nodeEnv === 'staging' ||
|
|
123
|
+
nodeEnv === 'preview') {
|
|
124
|
+
return nodeEnv;
|
|
125
|
+
}
|
|
126
|
+
if (nodeEnv === 'production' || vercel === 'production')
|
|
127
|
+
return 'production';
|
|
128
|
+
return 'development';
|
|
129
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/core",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.4",
|
|
4
4
|
"description": "RevealUI's runtime engine — admin UI, REST API, auth, rich text, plugin system, and access control. The heart of the open-source platform.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
"pg": "^8.22.0",
|
|
24
24
|
"yjs": "^13.6.31",
|
|
25
25
|
"zod": "^4.4.3",
|
|
26
|
-
"@revealui/contracts": "0.
|
|
27
|
-
"@revealui/presentation": "0.
|
|
26
|
+
"@revealui/contracts": "0.13.2",
|
|
27
|
+
"@revealui/presentation": "0.15.2",
|
|
28
28
|
"@revealui/resilience": "0.2.4",
|
|
29
|
-
"@revealui/security": "0.
|
|
29
|
+
"@revealui/security": "0.10.1",
|
|
30
30
|
"@revealui/utils": "0.3.6"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
@@ -71,6 +71,11 @@
|
|
|
71
71
|
"import": "./dist/session-cookie-domain.js",
|
|
72
72
|
"default": "./dist/session-cookie-domain.js"
|
|
73
73
|
},
|
|
74
|
+
"./sentry-environment": {
|
|
75
|
+
"types": "./dist/sentry-environment.d.ts",
|
|
76
|
+
"import": "./dist/sentry-environment.js",
|
|
77
|
+
"default": "./dist/sentry-environment.js"
|
|
78
|
+
},
|
|
74
79
|
"./margin-governor": {
|
|
75
80
|
"types": "./dist/margin-governor.d.ts",
|
|
76
81
|
"import": "./dist/margin-governor.js",
|