@revealui/core 0.11.1 → 0.12.1
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/README.md +2 -3
- package/dist/api/rest.js +4 -4
- package/dist/client/admin/utils/csrf.d.ts +9 -6
- package/dist/client/admin/utils/csrf.d.ts.map +1 -1
- package/dist/client/admin/utils/csrf.js +9 -6
- package/dist/collections/operations/fieldValidation.d.ts +5 -16
- package/dist/collections/operations/fieldValidation.d.ts.map +1 -1
- package/dist/collections/operations/fieldValidation.js +5 -20
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +4 -2
- package/dist/database/safe-parse.js +3 -3
- package/dist/database/universal-postgres.d.ts.map +1 -1
- package/dist/database/universal-postgres.js +10 -13
- package/dist/deployment-mode.d.ts +44 -0
- package/dist/deployment-mode.d.ts.map +1 -0
- package/dist/deployment-mode.js +58 -0
- package/dist/error-handling/error-boundary.d.ts +16 -2
- package/dist/error-handling/error-boundary.d.ts.map +1 -1
- package/dist/error-handling/error-boundary.js +18 -3
- package/dist/error-handling/error-reporter.d.ts +1 -1
- package/dist/error-handling/error-reporter.d.ts.map +1 -1
- package/dist/error-handling/error-reporter.js +6 -2
- package/dist/error-handling/index.d.ts +1 -1
- package/dist/error-handling/index.d.ts.map +1 -1
- package/dist/error-handling/index.js +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/instance/logger.d.ts +18 -7
- package/dist/instance/logger.d.ts.map +1 -1
- package/dist/instance/logger.js +66 -17
- package/dist/license/mint-client.d.ts +72 -0
- package/dist/license/mint-client.d.ts.map +1 -0
- package/dist/license/mint-client.js +175 -0
- package/dist/license.d.ts +109 -0
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +153 -6
- package/dist/observability/index.d.ts +5 -2
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +5 -2
- package/dist/observability/logger.d.ts +5 -3
- package/dist/observability/logger.d.ts.map +1 -1
- package/dist/observability/logger.js +5 -3
- package/dist/relationships/analyzer.js +2 -2
- package/dist/revforge-license.d.ts +9 -0
- package/dist/revforge-license.d.ts.map +1 -1
- package/dist/revforge-license.js +12 -2
- package/dist/storage/object-storage.d.ts.map +1 -1
- package/dist/storage/object-storage.js +3 -3
- package/dist/utils/errors.d.ts +16 -4
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +14 -2
- package/dist/utils/json-parsing.d.ts.map +1 -1
- package/dist/utils/json-parsing.js +4 -2
- package/dist/utils/logger-client.d.ts +6 -27
- package/dist/utils/logger-client.d.ts.map +1 -1
- package/dist/utils/logger-client.js +5 -51
- package/dist/utils/logger-server.d.ts +16 -20
- package/dist/utils/logger-server.d.ts.map +1 -1
- package/dist/utils/logger-server.js +40 -53
- package/dist/utils/logger.d.ts +7 -9
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +6 -8
- package/package.json +154 -76
- package/dist/caching/index.d.ts +0 -6
- package/dist/caching/index.d.ts.map +0 -1
- package/dist/caching/index.js +0 -5
- package/dist/observability/tracing.d.ts +0 -149
- package/dist/observability/tracing.d.ts.map +0 -1
- package/dist/observability/tracing.js +0 -380
package/dist/license.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// other modules in the auth route bundle during page data collection.
|
|
16
16
|
import { z } from 'zod';
|
|
17
17
|
import { decryptLicenseKey } from './license-encryption.js';
|
|
18
|
-
import { logger } from './
|
|
18
|
+
import { logger } from './observability/logger.js';
|
|
19
19
|
async function getJose() {
|
|
20
20
|
return await import('jose');
|
|
21
21
|
}
|
|
@@ -127,6 +127,20 @@ let cachedState = {
|
|
|
127
127
|
export function normalizePem(raw) {
|
|
128
128
|
return raw.split('\\n').join('\n');
|
|
129
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Read a PEM from `env[name]` (defaults to `process.env`), trim, and normalize
|
|
132
|
+
* escaped newlines. Returns `undefined` when missing or blank after trim.
|
|
133
|
+
* Canonical helper for the former 8+ copy-pasted license/webhook PEM unescapes (GAP-396).
|
|
134
|
+
*/
|
|
135
|
+
export function readPemEnv(name, env = process.env) {
|
|
136
|
+
const raw = env[name];
|
|
137
|
+
if (raw === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
const trimmed = raw.trim();
|
|
140
|
+
if (trimmed.length === 0)
|
|
141
|
+
return undefined;
|
|
142
|
+
return normalizePem(trimmed);
|
|
143
|
+
}
|
|
130
144
|
/**
|
|
131
145
|
* The ordered public-key candidates used to verify license JWTs.
|
|
132
146
|
*
|
|
@@ -204,6 +218,47 @@ export async function computeKeyId(publicKeyPem) {
|
|
|
204
218
|
* options below. Signature is enforced via the public key.
|
|
205
219
|
*/
|
|
206
220
|
export async function validateLicenseKey(licenseKey, publicKey, expectedCustomerId) {
|
|
221
|
+
// Accept tokens expired within the subscription grace window so the payload
|
|
222
|
+
// is available for grace-period calculations in isLicensed().
|
|
223
|
+
return verifyAndParseLicenseJwt(licenseKey, publicKey, graceConfig.subscriptionDays * 86_400, expectedCustomerId);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* How far past `exp` a license JWT is still accepted by the refresh endpoint
|
|
227
|
+
* (GAP-287 PR-1). Ratified by the owner 2026-07-18 at 30 days.
|
|
228
|
+
*
|
|
229
|
+
* Deliberately wider than the subscription validation grace
|
|
230
|
+
* (`LICENSE_GRACE_SUBSCRIPTION_DAYS`, default 3): the validation grace answers
|
|
231
|
+
* "may you still run", the refresh-accept window answers "may you still fetch
|
|
232
|
+
* your renewal". A customer returning from a month away should still be able to
|
|
233
|
+
* pull their current key rather than being bricked. Beyond this window the
|
|
234
|
+
* refresh path refuses and re-delivery goes through the authenticated admin
|
|
235
|
+
* account page.
|
|
236
|
+
*/
|
|
237
|
+
export const REFRESH_ACCEPT_DAYS = 30;
|
|
238
|
+
/**
|
|
239
|
+
* Refresh-path validator (GAP-287 PR-1). Verifies a presented license JWT for
|
|
240
|
+
* `POST /api/license/refresh`, accepting a token whose `exp` is past by at most
|
|
241
|
+
* `refreshAcceptDays` (default {@link REFRESH_ACCEPT_DAYS}).
|
|
242
|
+
*
|
|
243
|
+
* It reuses the SAME ordered multi-key verification (GAP-259 rotation
|
|
244
|
+
* composition) and payload schema as {@link validateLicenseKey}, so a token
|
|
245
|
+
* minted under the outgoing private key during a dual-key rotation window still
|
|
246
|
+
* verifies. It performs NO `customerId` binding: the refresh endpoint trusts
|
|
247
|
+
* the token's `customerId` claim and then independently requires an ACTIVE
|
|
248
|
+
* license row for it. This function only proves possession of a recently-valid
|
|
249
|
+
* signed key. It never mints and never grants entitlement on its own.
|
|
250
|
+
*/
|
|
251
|
+
export async function validateLicenseKeyForRefresh(licenseKey, publicKey, refreshAcceptDays = REFRESH_ACCEPT_DAYS) {
|
|
252
|
+
return verifyAndParseLicenseJwt(licenseKey, publicKey, refreshAcceptDays * 86_400);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Shared verify + parse path for {@link validateLicenseKey} and
|
|
256
|
+
* {@link validateLicenseKeyForRefresh}. The ONLY behavioral difference between
|
|
257
|
+
* the two callers is `clockToleranceSeconds` — how far past `exp` a token is
|
|
258
|
+
* still accepted — so the rotation-aware multi-key loop and the payload schema
|
|
259
|
+
* live in exactly one place.
|
|
260
|
+
*/
|
|
261
|
+
async function verifyAndParseLicenseJwt(licenseKey, publicKey, clockToleranceSeconds, expectedCustomerId) {
|
|
207
262
|
const candidates = typeof publicKey === 'string' ? [publicKey] : [...publicKey];
|
|
208
263
|
if (candidates.length === 0)
|
|
209
264
|
return null;
|
|
@@ -218,11 +273,9 @@ export async function validateLicenseKey(licenseKey, publicKey, expectedCustomer
|
|
|
218
273
|
for (const candidate of ordered) {
|
|
219
274
|
try {
|
|
220
275
|
const key = await jose.importSPKI(candidate, 'EdDSA');
|
|
221
|
-
// Accept tokens expired within the subscription grace window so the
|
|
222
|
-
// payload is available for grace-period calculations in isLicensed().
|
|
223
276
|
const { payload } = await jose.jwtVerify(licenseKey, key, {
|
|
224
277
|
algorithms: ['EdDSA'],
|
|
225
|
-
clockTolerance:
|
|
278
|
+
clockTolerance: clockToleranceSeconds,
|
|
226
279
|
issuer: LICENSE_ISSUER,
|
|
227
280
|
audience: LICENSE_AUDIENCE,
|
|
228
281
|
});
|
|
@@ -232,7 +285,7 @@ export async function validateLicenseKey(licenseKey, publicKey, expectedCustomer
|
|
|
232
285
|
}
|
|
233
286
|
catch {
|
|
234
287
|
// This candidate did not verify (wrong key, malformed PEM, bad
|
|
235
|
-
// iss/aud, or expired beyond
|
|
288
|
+
// iss/aud, or expired beyond tolerance) — try the next before giving up.
|
|
236
289
|
}
|
|
237
290
|
}
|
|
238
291
|
if (!verified) {
|
|
@@ -617,6 +670,100 @@ export function getMaxAgentTasks() {
|
|
|
617
670
|
return 10_000;
|
|
618
671
|
return 1_000;
|
|
619
672
|
}
|
|
673
|
+
/**
|
|
674
|
+
* Default subscription license JWT lifetime (seconds) — one year. Used as the
|
|
675
|
+
* fallback when a subscription's billing period is unavailable at mint time (an
|
|
676
|
+
* abnormal Stripe shape) so a period-bound token is never SHORTER than the
|
|
677
|
+
* pre-GAP-287 behavior, and as the default lifetime for {@link generateLicenseKey}
|
|
678
|
+
* when no explicit value is passed.
|
|
679
|
+
*/
|
|
680
|
+
export const DEFAULT_SUBSCRIPTION_TTL_SECONDS = 365 * 24 * 60 * 60;
|
|
681
|
+
/**
|
|
682
|
+
* Slack added to a hosted subscription's `current_period_end` when deriving the
|
|
683
|
+
* license JWT `exp` (GAP-287 PR-2). Ratified by the owner 2026-07-18 at 7 days.
|
|
684
|
+
*
|
|
685
|
+
* The token's lifetime equals what billing has actually granted plus this slack.
|
|
686
|
+
* The slack must cover the Stripe dunning/retry window so a card that recovers
|
|
687
|
+
* on retry never presents a lapsed key. Renewals advance the exp each billing
|
|
688
|
+
* cycle by re-minting on `invoice.payment_succeeded`.
|
|
689
|
+
*/
|
|
690
|
+
export const RENEWAL_SLACK_DAYS = 7;
|
|
691
|
+
export const RENEWAL_SLACK_SECONDS = RENEWAL_SLACK_DAYS * 24 * 60 * 60;
|
|
692
|
+
/**
|
|
693
|
+
* Default lifetime, in days, for a license JWT minted by the admin
|
|
694
|
+
* `POST /generate` manual-mint endpoint when the caller does not supply an
|
|
695
|
+
* explicit `expiresInDays` (GAP-287 PR-3). Ratified by the owner 2026-07-18 at
|
|
696
|
+
* 90, down from the prior flat 365-day default: this is an operator tool, and
|
|
697
|
+
* a short default nudges the right renewal habit for manually-issued keys. An
|
|
698
|
+
* explicit `expiresInDays` on the request is always honored unchanged.
|
|
699
|
+
*/
|
|
700
|
+
export const DEFAULT_MANUAL_MINT_DAYS = 90;
|
|
701
|
+
/**
|
|
702
|
+
* Derives the relative `expiresInSeconds` argument for {@link generateLicenseKey}
|
|
703
|
+
* at the hosted subscription mint sites (GAP-287 PR-2): the token should expire
|
|
704
|
+
* at `periodEnd + RENEWAL_SLACK_SECONDS`. Because generateLicenseKey interprets a
|
|
705
|
+
* numeric lifetime relative to issue time, this returns that absolute bound minus
|
|
706
|
+
* now.
|
|
707
|
+
*
|
|
708
|
+
* Falls back to {@link DEFAULT_SUBSCRIPTION_TTL_SECONDS} when `periodEnd` is
|
|
709
|
+
* absent (a subscription with no billing period) so an unexpected Stripe shape
|
|
710
|
+
* never mints a shorter-than-before token. Never returns a non-positive lifetime:
|
|
711
|
+
* a period end already in the past floors at one second, leaving expiry to the
|
|
712
|
+
* validation grace + refresh window rather than minting an already-invalid token.
|
|
713
|
+
*/
|
|
714
|
+
export function subscriptionLicenseExpiresInSeconds(periodEnd, nowMs = Date.now()) {
|
|
715
|
+
if (!periodEnd)
|
|
716
|
+
return DEFAULT_SUBSCRIPTION_TTL_SECONDS;
|
|
717
|
+
const boundMs = periodEnd.getTime() + RENEWAL_SLACK_SECONDS * 1000;
|
|
718
|
+
return Math.max(1, Math.floor((boundMs - nowMs) / 1000));
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Absolute epoch-second bound `periodEnd + RENEWAL_SLACK_SECONDS` a hosted
|
|
722
|
+
* subscription key should reach (GAP-287 PR-2). The renewal cadence re-mints IFF
|
|
723
|
+
* the stored key's `exp` is below this bound, so the comparison uses this
|
|
724
|
+
* absolute form while the mint uses the relative
|
|
725
|
+
* {@link subscriptionLicenseExpiresInSeconds}.
|
|
726
|
+
*/
|
|
727
|
+
export function subscriptionExpBound(periodEnd) {
|
|
728
|
+
return Math.floor(periodEnd.getTime() / 1000) + RENEWAL_SLACK_SECONDS;
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Idempotency tolerance for the renewal re-mint decision (fast-follow from the
|
|
732
|
+
* non-blocking finding on the #1978 guardrail-2 verdict). `subscriptionLicenseExpiresInSeconds`
|
|
733
|
+
* floors its relative TTL to whole seconds and the JWT signer floors `exp` to
|
|
734
|
+
* `iat + expiresInSeconds` at its own second granularity, so the `exp` actually
|
|
735
|
+
* persisted for a subscription key can land exactly 1s below
|
|
736
|
+
* {@link subscriptionExpBound}'s value even though the mint targeted that bound.
|
|
737
|
+
* Without this tolerance a duplicate/retried `invoice.payment_succeeded` lands on
|
|
738
|
+
* that 1s gap and re-enters the re-mint path instead of no-opping.
|
|
739
|
+
*/
|
|
740
|
+
export const RENEWAL_IDEMPOTENCY_TOLERANCE_SECONDS = 1;
|
|
741
|
+
/**
|
|
742
|
+
* True when a stored license `exp` already covers the renewal bound, within the
|
|
743
|
+
* {@link RENEWAL_IDEMPOTENCY_TOLERANCE_SECONDS} idempotency tolerance - i.e. the
|
|
744
|
+
* renewal re-mint should be SKIPPED. `null` (perpetual token, or an undecodable
|
|
745
|
+
* key) never covers, so the caller falls through to re-mint.
|
|
746
|
+
*/
|
|
747
|
+
export function coversRenewalBound(storedExp, newBound) {
|
|
748
|
+
return storedExp !== null && storedExp >= newBound - RENEWAL_IDEMPOTENCY_TOLERANCE_SECONDS;
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Reads the `exp` (epoch seconds) claim from a license JWT WITHOUT verifying its
|
|
752
|
+
* signature. Internal use only, for the GAP-287 PR-2 renewal cadence: the token
|
|
753
|
+
* comes from our OWN store and the caller needs only its expiry to decide whether
|
|
754
|
+
* to re-mint — never as an authentication or entitlement decision. Returns null
|
|
755
|
+
* for a perpetual token (no exp claim) or one that cannot be decoded.
|
|
756
|
+
*/
|
|
757
|
+
export async function readLicenseExp(licenseKey) {
|
|
758
|
+
try {
|
|
759
|
+
const jose = await getJose();
|
|
760
|
+
const payload = jose.decodeJwt(licenseKey);
|
|
761
|
+
return typeof payload.exp === 'number' ? payload.exp : null;
|
|
762
|
+
}
|
|
763
|
+
catch {
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
620
767
|
/**
|
|
621
768
|
* Generates a signed license key JWT.
|
|
622
769
|
* Server-only in practice (requires the private key) but edge-compatible —
|
|
@@ -630,7 +777,7 @@ export function getMaxAgentTasks() {
|
|
|
630
777
|
* claim is added to the JWT header for forward-compatible key rotation.
|
|
631
778
|
* @returns Signed JWT string
|
|
632
779
|
*/
|
|
633
|
-
export async function generateLicenseKey(payload, privateKey, expiresInSeconds =
|
|
780
|
+
export async function generateLicenseKey(payload, privateKey, expiresInSeconds = DEFAULT_SUBSCRIPTION_TTL_SECONDS, publicKey) {
|
|
634
781
|
const jose = await getJose();
|
|
635
782
|
const key = await jose.importPKCS8(privateKey, 'EdDSA');
|
|
636
783
|
const kid = publicKey ? await computeKeyId(publicKey) : undefined;
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
* Observability Module
|
|
3
3
|
*
|
|
4
4
|
* Centralized exports for observability functionality including logging,
|
|
5
|
-
* metrics,
|
|
5
|
+
* metrics, alerts, and health checks.
|
|
6
|
+
*
|
|
7
|
+
* In-memory `TracingSystem` was removed (fleet-redundancy C11, 2026-07-23):
|
|
8
|
+
* unmounted, tests-only, zero app consumers. Prefer OpenTelemetry when
|
|
9
|
+
* distributed tracing is wired.
|
|
6
10
|
*/
|
|
7
11
|
export * from './alerts.js';
|
|
8
12
|
export * from './health-check.js';
|
|
9
13
|
export * from './logger.js';
|
|
10
14
|
export * from './metrics.js';
|
|
11
|
-
export * from './tracing.js';
|
|
12
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* Observability Module
|
|
3
3
|
*
|
|
4
4
|
* Centralized exports for observability functionality including logging,
|
|
5
|
-
* metrics,
|
|
5
|
+
* metrics, alerts, and health checks.
|
|
6
|
+
*
|
|
7
|
+
* In-memory `TracingSystem` was removed (fleet-redundancy C11, 2026-07-23):
|
|
8
|
+
* unmounted, tests-only, zero app consumers. Prefer OpenTelemetry when
|
|
9
|
+
* distributed tracing is wired.
|
|
6
10
|
*/
|
|
7
11
|
export * from './alerts.js';
|
|
8
12
|
export * from './health-check.js';
|
|
9
13
|
export * from './logger.js';
|
|
10
14
|
export * from './metrics.js';
|
|
11
|
-
export * from './tracing.js';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Structured Logging Infrastructure
|
|
2
|
+
* Structured Logging Infrastructure (canonical core facade)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Preferred import for packages that already depend on `@revealui/core`
|
|
5
|
+
* (ADR-008). Re-exports `@revealui/utils/logger` and adds core-only helpers
|
|
6
|
+
* (`createRequestLogger`, `logPerformance`, …). Leaf packages without a core
|
|
7
|
+
* dependency should import `@revealui/utils/logger` directly.
|
|
6
8
|
*/
|
|
7
9
|
export type { LogContext, LogEntry, LoggerConfig, LogLevel, } from '@revealui/utils/logger';
|
|
8
10
|
export { createLogger, Logger, logAudit, logError, logger, logQuery, } from '@revealui/utils/logger';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;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,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Structured Logging Infrastructure
|
|
2
|
+
* Structured Logging Infrastructure (canonical core facade)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Preferred import for packages that already depend on `@revealui/core`
|
|
5
|
+
* (ADR-008). Re-exports `@revealui/utils/logger` and adds core-only helpers
|
|
6
|
+
* (`createRequestLogger`, `logPerformance`, …). Leaf packages without a core
|
|
7
|
+
* dependency should import `@revealui/utils/logger` directly.
|
|
6
8
|
*/
|
|
7
9
|
// Import logger for internal use
|
|
8
10
|
import { logger as utilsLogger } from '@revealui/utils/logger';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logger } from '../observability/logger.js';
|
|
2
2
|
/**
|
|
3
3
|
* Analyzes a collection or global configuration and extracts all relationship fields
|
|
4
4
|
* with their storage metadata for proper query building.
|
|
@@ -51,7 +51,7 @@ export function getRelationshipFields(config, collectionSlug) {
|
|
|
51
51
|
const validation = validateRelationshipMetadata(relationships);
|
|
52
52
|
if (!validation.valid) {
|
|
53
53
|
for (const error of validation.errors) {
|
|
54
|
-
|
|
54
|
+
logger.warn(`[RelationshipAnalyzer] ${error}`);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
return relationships;
|
|
@@ -14,6 +14,15 @@ import { type LicensePayload } from './license.js';
|
|
|
14
14
|
export declare const SLUG_PATTERN: RegExp;
|
|
15
15
|
export declare const VALID_REVFORGE_TIERS: readonly ["pro", "max", "enterprise"];
|
|
16
16
|
export type RevForgeTier = (typeof VALID_REVFORGE_TIERS)[number];
|
|
17
|
+
/**
|
|
18
|
+
* Default lifetime, in days, for a RevForge kit license JWT when neither
|
|
19
|
+
* `expiresInDays` nor `perpetual` is supplied (GAP-287 PR-3). Ratified by the
|
|
20
|
+
* owner 2026-07-18: stays at 365 (no behavior change), matching the annual
|
|
21
|
+
* kit contract — the renewal path already exists via the GAP-316
|
|
22
|
+
* `stamp.sh --license-only` re-mint. This constant only names the value that
|
|
23
|
+
* was previously an inline literal.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_KIT_MINT_DAYS = 365;
|
|
17
26
|
export interface IssueRevForgeLicenseOptions {
|
|
18
27
|
/** Customer slug; becomes the JWT customerId. Must match SLUG_PATTERN. */
|
|
19
28
|
slug: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revforge-license.d.ts","sourceRoot":"","sources":["../src/revforge-license.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsB,KAAK,cAAc,EAAsB,MAAM,cAAc,CAAC;AAE3F,eAAO,MAAM,YAAY,QAAyB,CAAC;AAEnD,eAAO,MAAM,oBAAoB,uCAAwC,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,MAAM,WAAW,2BAA2B;IAC1C,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,IAAI,EAAE,YAAY,CAAC;IACnB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,IAAI,EAAE,YAAY,CAAC;IACnB,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oFAAoF;IACpF,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;CACtD;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,2BAA2B,EACjC,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,0BAA0B,CAAC,
|
|
1
|
+
{"version":3,"file":"revforge-license.d.ts","sourceRoot":"","sources":["../src/revforge-license.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsB,KAAK,cAAc,EAAsB,MAAM,cAAc,CAAC;AAE3F,eAAO,MAAM,YAAY,QAAyB,CAAC;AAEnD,eAAO,MAAM,oBAAoB,uCAAwC,CAAC;AAC1E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,MAAM,WAAW,2BAA2B;IAC1C,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,IAAI,EAAE,YAAY,CAAC;IACnB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,IAAI,EAAE,YAAY,CAAC;IACnB,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oFAAoF;IACpF,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;CACtD;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,2BAA2B,EACjC,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC,0BAA0B,CAAC,CAwFrC"}
|
package/dist/revforge-license.js
CHANGED
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
import { generateLicenseKey, validateLicenseKey } from './license.js';
|
|
14
14
|
export const SLUG_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
15
15
|
export const VALID_REVFORGE_TIERS = ['pro', 'max', 'enterprise'];
|
|
16
|
+
/**
|
|
17
|
+
* Default lifetime, in days, for a RevForge kit license JWT when neither
|
|
18
|
+
* `expiresInDays` nor `perpetual` is supplied (GAP-287 PR-3). Ratified by the
|
|
19
|
+
* owner 2026-07-18: stays at 365 (no behavior change), matching the annual
|
|
20
|
+
* kit contract — the renewal path already exists via the GAP-316
|
|
21
|
+
* `stamp.sh --license-only` re-mint. This constant only names the value that
|
|
22
|
+
* was previously an inline literal.
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_KIT_MINT_DAYS = 365;
|
|
16
25
|
/**
|
|
17
26
|
* Issue a signed RevForge license JWT for a paying customer.
|
|
18
27
|
*
|
|
@@ -55,12 +64,13 @@ export async function issueRevForgeLicense(opts, keys) {
|
|
|
55
64
|
...(opts.domains && opts.domains.length > 0 ? { domains: opts.domains } : {}),
|
|
56
65
|
};
|
|
57
66
|
// Perpetual: pass null to omit exp claim. Otherwise translate days → seconds.
|
|
58
|
-
// Default (neither flag):
|
|
67
|
+
// Default (neither flag): DEFAULT_KIT_MINT_DAYS (GAP-287 PR-3 named constant;
|
|
68
|
+
// value unchanged at 365).
|
|
59
69
|
const expiresInSeconds = opts.perpetual
|
|
60
70
|
? null
|
|
61
71
|
: opts.expiresInDays !== undefined
|
|
62
72
|
? opts.expiresInDays * 24 * 60 * 60
|
|
63
|
-
:
|
|
73
|
+
: DEFAULT_KIT_MINT_DAYS * 24 * 60 * 60;
|
|
64
74
|
const issuedAtMs = Date.now();
|
|
65
75
|
const licenseKey = await generateLicenseKey(payload, keys.privateKey, expiresInSeconds, keys.publicKey);
|
|
66
76
|
// Pair-match guard: prove the supplied public key can verify the JWT we just
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-storage.d.ts","sourceRoot":"","sources":["../../src/storage/object-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,2FAA2F;IAC3F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF;;;;;;OAMG;IACH,eAAe,EAAE,MAAM,eAAe,CAAC;IACvC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"object-storage.d.ts","sourceRoot":"","sources":["../../src/storage/object-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,2FAA2F;IAC3F,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,WAAW,CAAC,EAAE;QACZ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF;;;;;;OAMG;IACH,eAAe,EAAE,MAAM,eAAe,CAAC;IACvC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAuGjE"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* WARNING: This module is server-only.
|
|
18
18
|
* Do NOT import in client-side code or edge runtime.
|
|
19
19
|
*/
|
|
20
|
-
import {
|
|
20
|
+
import { logger } from '../observability/logger.js';
|
|
21
21
|
export function objectStorage(config) {
|
|
22
22
|
const prefix = config.prefix || 'uploads';
|
|
23
23
|
// Memoize the provider so the underlying client (S3 / Blob) is constructed
|
|
@@ -71,7 +71,7 @@ export function objectStorage(config) {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
catch (error) {
|
|
74
|
-
|
|
74
|
+
logger.error('Object storage upload error', error instanceof Error ? error : new Error(String(error)));
|
|
75
75
|
throw error;
|
|
76
76
|
}
|
|
77
77
|
},
|
|
@@ -86,7 +86,7 @@ export function objectStorage(config) {
|
|
|
86
86
|
await getProvider().del(keyOrUrl);
|
|
87
87
|
}
|
|
88
88
|
catch (error) {
|
|
89
|
-
|
|
89
|
+
logger.error('Object storage delete error', error instanceof Error ? error : new Error(String(error)));
|
|
90
90
|
throw error;
|
|
91
91
|
}
|
|
92
92
|
},
|
package/dist/utils/errors.d.ts
CHANGED
|
@@ -14,14 +14,26 @@ export declare class ApplicationError extends Error {
|
|
|
14
14
|
constructor(message: string, code: string, statusCode?: number, context?: Record<string, unknown> | undefined);
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Validation Error
|
|
18
|
-
*
|
|
17
|
+
* Validation Error (canonical domain / API / field-ingress class)
|
|
18
|
+
*
|
|
19
|
+
* Single source for server-side validation failures. Carries HTTP 400 via
|
|
20
|
+
* `status` / `statusCode` so REST and middleware treat field-ingress and
|
|
21
|
+
* API validation the same. Distinct from `ClientValidationError` in the
|
|
22
|
+
* React error-boundary module (client form field map).
|
|
23
|
+
*
|
|
24
|
+
* Always branch with `instanceof ValidationError` — never `name ===
|
|
25
|
+
* 'ValidationError'`, which false-positives against other classes that
|
|
26
|
+
* historically shared the same name.
|
|
19
27
|
*/
|
|
20
28
|
export declare class ValidationError extends Error {
|
|
21
29
|
field: string;
|
|
22
|
-
value
|
|
30
|
+
value?: unknown | undefined;
|
|
23
31
|
context?: Record<string, unknown> | undefined;
|
|
24
|
-
|
|
32
|
+
/** HTTP status for transports that read `error.status` (e.g. rest.ts). */
|
|
33
|
+
readonly status = 400;
|
|
34
|
+
/** Alias for handlers that read `statusCode`. */
|
|
35
|
+
readonly statusCode = 400;
|
|
36
|
+
constructor(message: string, field: string, value?: unknown | undefined, context?: Record<string, unknown> | undefined);
|
|
25
37
|
}
|
|
26
38
|
/**
|
|
27
39
|
* Database Error
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAGhC,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAHxC,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAY,EACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAM3C;AAED
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAGhC,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAHxC,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAY,EACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAM3C;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IAQ/B,KAAK,EAAE,MAAM;IACb,KAAK,CAAC,EAAE,OAAO;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAT1C,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,OAAO;IACtB,iDAAiD;IACjD,QAAQ,CAAC,UAAU,OAAO;gBAGxB,OAAO,EAAE,MAAM,EACR,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,OAAO,YAAA,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAM3C;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAG7B,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;IAClB,MAAM,CAAC,EAAE,MAAM;IACf,UAAU,CAAC,EAAE,MAAM;IACnB,KAAK,CAAC,EAAE,MAAM;IACd,MAAM,CAAC,EAAE,MAAM;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAPxC,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAY,EACxB,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,KAAK,CAAC,EAAE,MAAM,YAAA,EACd,MAAM,CAAC,EAAE,MAAM,YAAA,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAM3C;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,gBAAgB;gBAC3C,OAAO,SAA4B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAKnF;AAED;;;GAGG;AACH,qBAAa,kBAAmB,SAAQ,gBAAgB;gBAC1C,OAAO,SAA6B,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAKpF;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,gBAAgB;gBACrC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAMrF;AAED;;;GAGG;AACH,qBAAa,aAAc,SAAQ,gBAAgB;gBACrC,OAAO,SAAsB,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAK7E;AAED;;;GAGG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAGzC,YAAY,CAAC,EAAE,MAAM;gBAD5B,OAAO,SAAsB,EACtB,YAAY,CAAC,EAAE,MAAM,YAAA,EAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAMpC;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;CAkCpB,CAAC;AAkCX;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,CAmH7E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,KAAK,CA4WP"}
|
package/dist/utils/errors.js
CHANGED
|
@@ -22,13 +22,25 @@ export class ApplicationError extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Validation Error
|
|
26
|
-
*
|
|
25
|
+
* Validation Error (canonical domain / API / field-ingress class)
|
|
26
|
+
*
|
|
27
|
+
* Single source for server-side validation failures. Carries HTTP 400 via
|
|
28
|
+
* `status` / `statusCode` so REST and middleware treat field-ingress and
|
|
29
|
+
* API validation the same. Distinct from `ClientValidationError` in the
|
|
30
|
+
* React error-boundary module (client form field map).
|
|
31
|
+
*
|
|
32
|
+
* Always branch with `instanceof ValidationError` — never `name ===
|
|
33
|
+
* 'ValidationError'`, which false-positives against other classes that
|
|
34
|
+
* historically shared the same name.
|
|
27
35
|
*/
|
|
28
36
|
export class ValidationError extends Error {
|
|
29
37
|
field;
|
|
30
38
|
value;
|
|
31
39
|
context;
|
|
40
|
+
/** HTTP status for transports that read `error.status` (e.g. rest.ts). */
|
|
41
|
+
status = 400;
|
|
42
|
+
/** Alias for handlers that read `statusCode`. */
|
|
43
|
+
statusCode = 400;
|
|
32
44
|
constructor(message, field, value, context) {
|
|
33
45
|
super(message);
|
|
34
46
|
this.field = field;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-parsing.d.ts","sourceRoot":"","sources":["../../src/utils/json-parsing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAetD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,
|
|
1
|
+
{"version":3,"file":"json-parsing.d.ts","sourceRoot":"","sources":["../../src/utils/json-parsing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAetD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CA6DhB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASjE"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Utilities for serializing and deserializing JSON fields in database operations.
|
|
5
5
|
* Handles the _json column pattern used for storing complex field types.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { logger } from '../observability/logger.js';
|
|
8
8
|
/**
|
|
9
9
|
* Parse a JSON field value safely
|
|
10
10
|
*
|
|
@@ -67,7 +67,9 @@ export function deserializeJsonFields(doc, tableName) {
|
|
|
67
67
|
}
|
|
68
68
|
catch (error) {
|
|
69
69
|
// Invalid JSON - log for debugging but continue
|
|
70
|
-
|
|
70
|
+
logger.warn(`Failed to parse _json in ${tableName || 'unknown'}`, {
|
|
71
|
+
error: error instanceof Error ? { message: error.message, name: error.name } : error,
|
|
72
|
+
});
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
// Remove _json from result (internal column)
|
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Client-
|
|
2
|
+
* Client-safe logger entry (ADR-008 D4)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Info/warn messages are no-ops in production to avoid console pollution.
|
|
4
|
+
* Re-exports `@revealui/utils/logger` (no Node async_hooks). Prefer
|
|
5
|
+
* `@revealui/core/observability/logger` for packages that already depend on core.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
* React component. Adding 'use client' causes Next.js to create a reference
|
|
10
|
-
* proxy when imported from server code (API routes), stripping all methods.
|
|
7
|
+
* Package export: `@revealui/core/utils/logger/client`
|
|
11
8
|
*/
|
|
12
|
-
export type
|
|
13
|
-
export
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
}
|
|
16
|
-
export interface Logger {
|
|
17
|
-
debug(message: string, context?: LogContext): void;
|
|
18
|
-
info(message: string, context?: LogContext): void;
|
|
19
|
-
warn(message: string, context?: LogContext): void;
|
|
20
|
-
error(message: string, context?: LogContext): void;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Create a client-safe logger instance
|
|
24
|
-
*
|
|
25
|
-
* @returns Logger instance safe for client-side use
|
|
26
|
-
*/
|
|
27
|
-
export declare function createLogger(): Logger;
|
|
28
|
-
/**
|
|
29
|
-
* Default client-safe logger instance
|
|
30
|
-
*/
|
|
31
|
-
export declare const logger: Logger;
|
|
9
|
+
export type { LogContext, LogEntry, LoggerConfig, LogLevel, } from '@revealui/utils/logger';
|
|
10
|
+
export { createLogger, Logger, logAudit, logError, logger, logQuery, } from '@revealui/utils/logger';
|
|
32
11
|
//# sourceMappingURL=logger-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger-client.d.ts","sourceRoot":"","sources":["../../src/utils/logger-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger-client.d.ts","sourceRoot":"","sources":["../../src/utils/logger-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,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"}
|
|
@@ -1,55 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Client-
|
|
2
|
+
* Client-safe logger entry (ADR-008 D4)
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Info/warn messages are no-ops in production to avoid console pollution.
|
|
4
|
+
* Re-exports `@revealui/utils/logger` (no Node async_hooks). Prefer
|
|
5
|
+
* `@revealui/core/observability/logger` for packages that already depend on core.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
* React component. Adding 'use client' causes Next.js to create a reference
|
|
10
|
-
* proxy when imported from server code (API routes), stripping all methods.
|
|
7
|
+
* Package export: `@revealui/core/utils/logger/client`
|
|
11
8
|
*/
|
|
12
|
-
|
|
13
|
-
* Client-safe logger implementation
|
|
14
|
-
* Simple console-based logging without Node.js dependencies
|
|
15
|
-
*/
|
|
16
|
-
class ClientLogger {
|
|
17
|
-
formatMessage(level, message, context) {
|
|
18
|
-
const timestamp = new Date().toISOString();
|
|
19
|
-
const prefix = `[${timestamp}] [RevealUI] [${level.toUpperCase()}]`;
|
|
20
|
-
if (context && Object.keys(context).length > 0) {
|
|
21
|
-
return `${prefix} ${message} ${JSON.stringify(context)}`;
|
|
22
|
-
}
|
|
23
|
-
return `${prefix} ${message}`;
|
|
24
|
-
}
|
|
25
|
-
debug(message, context) {
|
|
26
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
27
|
-
console.debug(this.formatMessage('debug', message, context));
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
info(message, context) {
|
|
31
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
32
|
-
console.info(this.formatMessage('info', message, context));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
warn(message, context) {
|
|
36
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
37
|
-
console.warn(this.formatMessage('warn', message, context));
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
error(message, context) {
|
|
41
|
-
console.error(this.formatMessage('error', message, context));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Create a client-safe logger instance
|
|
46
|
-
*
|
|
47
|
-
* @returns Logger instance safe for client-side use
|
|
48
|
-
*/
|
|
49
|
-
export function createLogger() {
|
|
50
|
-
return new ClientLogger();
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Default client-safe logger instance
|
|
54
|
-
*/
|
|
55
|
-
export const logger = createLogger();
|
|
9
|
+
export { createLogger, Logger, logAudit, logError, logger, logQuery, } from '@revealui/utils/logger';
|