@agent-native/core 0.98.1 → 0.98.3
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +18 -0
- package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +1 -1
- package/corpus/core/docs/content/pr-visual-recap.mdx +50 -1
- package/corpus/core/docs/content/template-plan.mdx +1 -1
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +2 -2
- package/corpus/core/src/cli/plan-local.ts +43 -11
- package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -9
- package/corpus/core/src/cli/recap.ts +356 -4
- package/corpus/core/src/cli/skills-content/local-files.ts +17 -12
- package/corpus/core/src/client/analytics.ts +96 -14
- package/corpus/core/src/client/index.ts +7 -0
- package/corpus/core/src/client/session-replay.ts +10 -0
- package/corpus/core/src/client/settings/DemoModeSection.tsx +10 -34
- package/corpus/core/src/client/settings/SettingsPanel.tsx +31 -211
- package/corpus/core/src/client/settings/agent-settings-search.ts +219 -0
- package/corpus/core/src/client/settings/index.ts +4 -0
- package/corpus/core/src/client/url-scrub.ts +13 -0
- package/corpus/core/src/client/use-demo-mode-status.ts +44 -0
- package/corpus/core/src/demo/actions/toggle-demo-mode.ts +2 -2
- package/corpus/core/src/demo/config.ts +6 -6
- package/corpus/core/src/demo/redact.ts +18 -76
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +21 -4
- package/corpus/templates/analytics/AGENTS.md +8 -0
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +18 -4
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +429 -244
- package/corpus/templates/analytics/app/components/layout/command-palette-search.ts +93 -0
- package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +2 -1
- package/corpus/templates/analytics/app/lib/demo-chart-trend.ts +169 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +8 -45
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +205 -70
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +32 -16
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +126 -0
- package/corpus/templates/analytics/changelog/2026-07-12-command-menu-loading-placeholders-now-stay-below-available-r.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-command-menu-search-now-prioritizes-the-best-match.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-daily-dashboard-emails-reliably-include-the-complete-dashboa.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-charts-preserve-source-movement.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-demo-mode-charts-trend-upward.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-replay-storage-settings-stay-readable-at-narrow-widths.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-12-session-replays-preserve-recorded-styling-and-keep-malformed.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +2 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +17 -33
- package/corpus/templates/clips/app/components/player/video-player.tsx +5 -1
- package/corpus/templates/clips/changelog/2026-07-11-clips-no-longer-stay-stuck-on-preparing-clip-when-they-are-r.md +6 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +2 -2
- package/corpus/templates/content/changelog/2026-07-12-the-left-sidebar-stays-fixed-horizontally-while-scrolling-on.md +6 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/references/local-files.md +17 -12
- package/corpus/templates/plan/.agents/skills/visual-recap/references/local-files.md +17 -12
- package/corpus/templates/plan/actions/validate-local-plan-source.ts +4 -4
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -1
- package/corpus/templates/plan/app/lib/plan-local-bridge.ts +41 -0
- package/corpus/templates/plan/app/lib/plan-tracking.ts +3 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -9
- package/corpus/templates/plan/app/root.tsx +13 -3
- package/corpus/templates/plan/changelog/2026-07-12-local-plan-source-now-stays-on-device.md +6 -0
- package/dist/agent/production-agent.js +2 -2
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/plan-local.d.ts +6 -6
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +36 -7
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +2 -8
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +2 -8
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +22 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +286 -2
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills-content/local-files.d.ts +1 -1
- package/dist/cli/skills-content/local-files.d.ts.map +1 -1
- package/dist/cli/skills-content/local-files.js +17 -12
- package/dist/cli/skills-content/local-files.js.map +1 -1
- package/dist/client/analytics.d.ts +8 -0
- package/dist/client/analytics.d.ts.map +1 -1
- package/dist/client/analytics.js +77 -13
- package/dist/client/analytics.js.map +1 -1
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/session-replay.d.ts +2 -0
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +7 -0
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/settings/DemoModeSection.d.ts +3 -3
- package/dist/client/settings/DemoModeSection.d.ts.map +1 -1
- package/dist/client/settings/DemoModeSection.js +8 -27
- package/dist/client/settings/DemoModeSection.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +41 -191
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/agent-settings-search.d.ts +16 -0
- package/dist/client/settings/agent-settings-search.d.ts.map +1 -0
- package/dist/client/settings/agent-settings-search.js +178 -0
- package/dist/client/settings/agent-settings-search.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/client/url-scrub.d.ts.map +1 -1
- package/dist/client/url-scrub.js +14 -0
- package/dist/client/url-scrub.js.map +1 -1
- package/dist/client/use-demo-mode-status.d.ts +12 -0
- package/dist/client/use-demo-mode-status.d.ts.map +1 -0
- package/dist/client/use-demo-mode-status.js +30 -0
- package/dist/client/use-demo-mode-status.js.map +1 -0
- package/dist/collab/routes.d.ts +2 -2
- package/dist/demo/actions/toggle-demo-mode.js +2 -2
- package/dist/demo/actions/toggle-demo-mode.js.map +1 -1
- package/dist/demo/config.js +6 -6
- package/dist/demo/config.js.map +1 -1
- package/dist/demo/redact.d.ts +7 -5
- package/dist/demo/redact.d.ts.map +1 -1
- package/dist/demo/redact.js +19 -54
- package/dist/demo/redact.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +5 -5
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/docs/content/locales/ar-SA/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/ar-SA/template-plan.mdx +1 -1
- package/docs/content/locales/de-DE/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/de-DE/template-plan.mdx +1 -1
- package/docs/content/locales/es-ES/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/es-ES/template-plan.mdx +1 -1
- package/docs/content/locales/fr-FR/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/fr-FR/template-plan.mdx +1 -1
- package/docs/content/locales/hi-IN/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/hi-IN/template-plan.mdx +1 -1
- package/docs/content/locales/ja-JP/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/ja-JP/template-plan.mdx +1 -1
- package/docs/content/locales/ko-KR/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/ko-KR/template-plan.mdx +1 -1
- package/docs/content/locales/pt-BR/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/pt-BR/template-plan.mdx +1 -1
- package/docs/content/locales/zh-CN/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/zh-CN/template-plan.mdx +1 -1
- package/docs/content/locales/zh-TW/pr-visual-recap.mdx +25 -1
- package/docs/content/locales/zh-TW/template-plan.mdx +1 -1
- package/docs/content/pr-visual-recap.mdx +50 -1
- package/docs/content/template-plan.mdx +1 -1
- package/package.json +2 -2
package/dist/demo/redact.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure, dependency-free, deterministic demo-mode redactor.
|
|
3
3
|
*
|
|
4
|
-
* Replaces sensitive values (
|
|
4
|
+
* Replaces sensitive values (emails and free numbers) with stable fake
|
|
5
5
|
* substitutes so a demo looks coherent — the same input always maps to the
|
|
6
6
|
* same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or
|
|
7
|
-
* timestamps
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* timestamps. Names and other free text are deliberately left alone because
|
|
8
|
+
* guessing whether arbitrary text is a person's name is too inaccurate. The
|
|
9
|
+
* string redactor uses a protect-first strategy (mask IDs with opaque
|
|
10
|
+
* placeholders before any transform runs, restore them byte-identical
|
|
11
|
+
* afterwards), and the structure-aware walker additionally protects leaf
|
|
12
|
+
* values by key name.
|
|
11
13
|
*/
|
|
12
14
|
/* ------------------------------------------------------------------ *
|
|
13
15
|
* Seeded hash + PRNG (xmur3 seed → mulberry32 stream)
|
|
@@ -56,7 +58,7 @@ function pick(rng, pool) {
|
|
|
56
58
|
* round-trips back through redaction (e.g. you edit a draft that's
|
|
57
59
|
* already showing fake text, it autosaves, then refetches) it is passed
|
|
58
60
|
* through UNCHANGED instead of being re-faked into something new. This
|
|
59
|
-
* is what stops
|
|
61
|
+
* is what stops emails drifting on every edit.
|
|
60
62
|
*
|
|
61
63
|
* Leak-free by construction: no timers, a hard size cap, and lazy TTL purge
|
|
62
64
|
* on write. Works the same per-tab in the browser and per-process on the
|
|
@@ -223,14 +225,6 @@ const LAST_NAMES = [
|
|
|
223
225
|
/* ------------------------------------------------------------------ *
|
|
224
226
|
* Fake value generators (deterministic in value + salt)
|
|
225
227
|
* ------------------------------------------------------------------ */
|
|
226
|
-
function fakeName(original, salt) {
|
|
227
|
-
return memoFake("name", original, salt, () => {
|
|
228
|
-
const rng = seededRng(`name:${original}`, salt);
|
|
229
|
-
const first = pick(rng, FIRST_NAMES);
|
|
230
|
-
const last = pick(rng, LAST_NAMES);
|
|
231
|
-
return `${first} ${last}`;
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
228
|
// Realistic-looking but safe stand-in domains: real consumer providers (the
|
|
235
229
|
// local part is fake, so no real mailbox is implied) plus the canonical
|
|
236
230
|
// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read
|
|
@@ -427,9 +421,6 @@ function unprotect(text, restore) {
|
|
|
427
421
|
* Transforms (run only on protected text)
|
|
428
422
|
* ------------------------------------------------------------------ */
|
|
429
423
|
const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
|
|
430
|
-
// 2+ capitalized words (each starts uppercase, allows internal lowercase /
|
|
431
|
-
// apostrophes / hyphens). Single-letter middle initials allowed: `Sarah J Connor`.
|
|
432
|
-
const FULL_NAME_RE = /\b[A-Z][a-zA-Z'’-]*(?:\s+[A-Z](?:[a-zA-Z'’-]*)?){1,3}\b/g;
|
|
433
424
|
// A standalone numeric token: optional currency + sign, digits with optional
|
|
434
425
|
// comma grouping and a single optional decimal part. Bounded so it is NOT
|
|
435
426
|
// adjacent to a letter (placeholders already removed letter-mixed tokens, but
|
|
@@ -438,9 +429,6 @@ const NUMBER_RE = /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\d[\d,]*(?:\.\d+)?)(?![A-
|
|
|
438
429
|
function transformEmails(text, salt) {
|
|
439
430
|
return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));
|
|
440
431
|
}
|
|
441
|
-
function transformNames(text, salt) {
|
|
442
|
-
return text.replace(FULL_NAME_RE, (match) => fakeName(match, salt));
|
|
443
|
-
}
|
|
444
432
|
function isProbablyYear(digits) {
|
|
445
433
|
if (digits.length !== 4)
|
|
446
434
|
return false;
|
|
@@ -475,19 +463,17 @@ function transformNumbers(text, salt) {
|
|
|
475
463
|
/* ------------------------------------------------------------------ *
|
|
476
464
|
* Public: string redactor
|
|
477
465
|
* ------------------------------------------------------------------ */
|
|
478
|
-
function redactDemoStringInternal(text, salt
|
|
466
|
+
function redactDemoStringInternal(text, salt) {
|
|
479
467
|
if (typeof text !== "string" || text.length === 0)
|
|
480
468
|
return text;
|
|
481
469
|
const { text: masked, restore } = protect(text);
|
|
482
470
|
let out = masked;
|
|
483
471
|
out = transformEmails(out, salt);
|
|
484
|
-
if (redactNames)
|
|
485
|
-
out = transformNames(out, salt);
|
|
486
472
|
out = transformNumbers(out, salt);
|
|
487
473
|
return unprotect(out, restore);
|
|
488
474
|
}
|
|
489
475
|
export function redactDemoString(text, opts) {
|
|
490
|
-
return redactDemoStringInternal(text, opts?.salt ?? ""
|
|
476
|
+
return redactDemoStringInternal(text, opts?.salt ?? "");
|
|
491
477
|
}
|
|
492
478
|
/* ------------------------------------------------------------------ *
|
|
493
479
|
* Public: structure-aware redactor
|
|
@@ -495,29 +481,11 @@ export function redactDemoString(text, opts) {
|
|
|
495
481
|
// Keys whose leaf values must NEVER be transformed (still recurse into nested
|
|
496
482
|
// objects/arrays under them). Besides ids/urls/timestamps this also covers
|
|
497
483
|
// code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):
|
|
498
|
-
//
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
// RESULTS are what get redacted so the chart still shows fake values.
|
|
484
|
+
// redacting a SQL string mutates literals and can make the query semantically
|
|
485
|
+
// wrong or invalid. The query must run untouched; its RESULTS are what get
|
|
486
|
+
// redacted so the chart still shows fake values.
|
|
502
487
|
const PROTECTED_KEY_RE = /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;
|
|
503
|
-
// UI labels and chart/dashboard titles often look like person names ("Maya
|
|
504
|
-
// Davis (First-party)", "Clicks by Henry Moore") but are structural labels. Keep
|
|
505
|
-
// them stable while still redacting free-text and contact-style person fields.
|
|
506
|
-
const LABEL_TEXT_KEY_RE = /^(name|title|label)$/i;
|
|
507
488
|
const MAX_DEPTH = 64;
|
|
508
|
-
function isStandalonePersonNameLabel(text) {
|
|
509
|
-
const trimmed = text.trim();
|
|
510
|
-
if (!trimmed)
|
|
511
|
-
return false;
|
|
512
|
-
return /^[A-Z][a-zA-Z'’-]+(?:\s+[A-Z]\.?)?\s+[A-Z][a-zA-Z'’-]+$/.test(trimmed);
|
|
513
|
-
}
|
|
514
|
-
function shouldRedactNamesForChild(key, entry) {
|
|
515
|
-
if (!LABEL_TEXT_KEY_RE.test(key))
|
|
516
|
-
return true;
|
|
517
|
-
// Preserve structural labels/titles, but do not let common contact-shaped
|
|
518
|
-
// fields like `{ name: "Olivia Parker" }` leak real person names.
|
|
519
|
-
return typeof entry === "string" ? isStandalonePersonNameLabel(entry) : true;
|
|
520
|
-
}
|
|
521
489
|
function isPlainObject(value) {
|
|
522
490
|
if (value === null || typeof value !== "object")
|
|
523
491
|
return false;
|
|
@@ -528,9 +496,6 @@ function isPlainObject(value) {
|
|
|
528
496
|
const proto = Object.getPrototypeOf(value);
|
|
529
497
|
return proto === Object.prototype || proto === null;
|
|
530
498
|
}
|
|
531
|
-
function redactDemoStringWithSalt(text, salt, redactNames) {
|
|
532
|
-
return redactDemoStringInternal(text, salt, redactNames);
|
|
533
|
-
}
|
|
534
499
|
function redactNumberLeaf(value, salt) {
|
|
535
500
|
if (!Number.isFinite(value))
|
|
536
501
|
return value;
|
|
@@ -545,14 +510,14 @@ function redactNumberLeaf(value, salt) {
|
|
|
545
510
|
return value;
|
|
546
511
|
return n;
|
|
547
512
|
}
|
|
548
|
-
function walk(value, salt, depth, seen
|
|
513
|
+
function walk(value, salt, depth, seen) {
|
|
549
514
|
if (depth > MAX_DEPTH)
|
|
550
515
|
return value;
|
|
551
516
|
if (value === null || value === undefined)
|
|
552
517
|
return value;
|
|
553
518
|
const t = typeof value;
|
|
554
519
|
if (t === "string") {
|
|
555
|
-
return
|
|
520
|
+
return redactDemoStringInternal(value, salt);
|
|
556
521
|
}
|
|
557
522
|
if (t === "number") {
|
|
558
523
|
return redactNumberLeaf(value, salt);
|
|
@@ -566,7 +531,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
566
531
|
if (seen.has(value))
|
|
567
532
|
return value;
|
|
568
533
|
seen.add(value);
|
|
569
|
-
const out = value.map((item) => walk(item, salt, depth + 1, seen
|
|
534
|
+
const out = value.map((item) => walk(item, salt, depth + 1, seen));
|
|
570
535
|
seen.delete(value);
|
|
571
536
|
return out;
|
|
572
537
|
}
|
|
@@ -583,7 +548,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
583
548
|
!(entry instanceof Date)) {
|
|
584
549
|
// Still recurse into nested structures, but the protected key does
|
|
585
550
|
// not transform its own leaf value.
|
|
586
|
-
out[key] = walk(entry, salt, depth + 1, seen
|
|
551
|
+
out[key] = walk(entry, salt, depth + 1, seen);
|
|
587
552
|
}
|
|
588
553
|
else {
|
|
589
554
|
// Leaf under a protected key: pass through completely untouched.
|
|
@@ -591,7 +556,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
591
556
|
}
|
|
592
557
|
continue;
|
|
593
558
|
}
|
|
594
|
-
out[key] = walk(entry, salt, depth + 1, seen
|
|
559
|
+
out[key] = walk(entry, salt, depth + 1, seen);
|
|
595
560
|
}
|
|
596
561
|
seen.delete(value);
|
|
597
562
|
return out;
|
|
@@ -601,7 +566,7 @@ function walk(value, salt, depth, seen, redactNames) {
|
|
|
601
566
|
}
|
|
602
567
|
export function redactDemoData(value, opts) {
|
|
603
568
|
const salt = opts?.salt ?? "";
|
|
604
|
-
return walk(value, salt, 0, new WeakSet()
|
|
569
|
+
return walk(value, salt, 0, new WeakSet());
|
|
605
570
|
}
|
|
606
571
|
/**
|
|
607
572
|
* Clear the stable-mapping caches. Test-only — the caches are process-global
|
package/dist/demo/redact.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/demo/redact.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, dependency-free, deterministic demo-mode redactor.\n *\n * Replaces sensitive values (names, emails, and free numbers) with stable fake\n * substitutes so a demo looks coherent — the same input always maps to the\n * same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or\n * timestamps: under-redaction is safe, corrupting an ID is not. The string\n * redactor uses a protect-first strategy (mask IDs with opaque placeholders\n * before any transform runs, restore them byte-identical afterwards), and the\n * structure-aware walker additionally protects leaf values by key name.\n */\n\nexport interface RedactOptions {\n salt?: string;\n}\n\n/* ------------------------------------------------------------------ *\n * Seeded hash + PRNG (xmur3 seed → mulberry32 stream)\n * ------------------------------------------------------------------ */\n\nfunction xmur3(str: string): () => number {\n let h = 1779033703 ^ str.length;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 3432918353);\n h = (h << 13) | (h >>> 19);\n }\n return function () {\n h = Math.imul(h ^ (h >>> 16), 2246822507);\n h = Math.imul(h ^ (h >>> 13), 3266489909);\n h ^= h >>> 16;\n return h >>> 0;\n };\n}\n\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return function () {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Deterministic PRNG seeded by `value + salt`. */\nfunction seededRng(value: string, salt: string): () => number {\n const seedFn = xmur3(`${value}${salt}`);\n return mulberry32(seedFn());\n}\n\nfunction pick<T>(rng: () => number, pool: readonly T[]): T {\n return pool[Math.floor(rng() * pool.length) % pool.length];\n}\n\n/* ------------------------------------------------------------------ *\n * Stable mapping cache (bounded, TTL, leak-free)\n *\n * The fake values are already a pure deterministic function of\n * (kind, salt, original), so identical input is always stable. This cache\n * adds two things on top:\n *\n * 1. A consistent forward map so the same original keeps the same fake for\n * the life of the entry, even if the algorithm/salt is ever tuned.\n * 2. Idempotency: every fake we emit is remembered, so when a fake value\n * round-trips back through redaction (e.g. you edit a draft that's\n * already showing fake text, it autosaves, then refetches) it is passed\n * through UNCHANGED instead of being re-faked into something new. This\n * is what stops names/emails drifting on every edit.\n *\n * Leak-free by construction: no timers, a hard size cap, and lazy TTL purge\n * on write. Works the same per-tab in the browser and per-process on the\n * server. Memoizing a pure function across users is safe — output depends\n * only on input.\n * ------------------------------------------------------------------ */\n\nconst CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour\nconst CACHE_MAX = 5000;\n\n// original-key → { fake, at }. Insertion-ordered (Map) so the oldest key is\n// first — used for cap eviction.\nconst forwardCache = new Map<string, { value: string; at: number }>();\n// produced fake → last-seen timestamp (same bound/TTL policy).\nconst producedFakes = new Map<string, number>();\n\nfunction purge(map: Map<string, { at: number } | number>): void {\n const now = Date.now();\n for (const [k, v] of map) {\n const at = typeof v === \"number\" ? v : v.at;\n if (now - at > CACHE_TTL_MS) map.delete(k);\n else break; // insertion-ordered: first fresh entry ⇒ rest are fresher\n }\n while (map.size > CACHE_MAX) {\n const oldest = map.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n map.delete(oldest);\n }\n}\n\nfunction rememberProduced(fake: string): string {\n if (fake.length === 0) return fake;\n producedFakes.delete(fake);\n producedFakes.set(fake, Date.now());\n if (producedFakes.size > CACHE_MAX) purge(producedFakes);\n return fake;\n}\n\nfunction isProducedFake(value: string): boolean {\n const at = producedFakes.get(value);\n if (at === undefined) return false;\n if (Date.now() - at > CACHE_TTL_MS) {\n producedFakes.delete(value);\n return false;\n }\n return true;\n}\n\n/**\n * Memoize a deterministic fake by (kind, salt, original). On a hit, the\n * entry's recency is refreshed (LRU-ish). The generated value is also\n * registered as a produced fake so it survives a round-trip unchanged.\n */\nfunction memoFake(\n kind: string,\n original: string,\n salt: string,\n gen: () => string,\n // Numbers opt out: a fake number collides with real numbers far too often\n // to safely treat \"looks like one we emitted\" as \"leave it alone\".\n idempotent = true,\n): string {\n // Already one of our fakes? Leave it exactly as-is (round-trip stable).\n if (idempotent && isProducedFake(original)) return original;\n\n const key = `${kind}${salt}${original}`;\n const hit = forwardCache.get(key);\n const now = Date.now();\n if (hit && now - hit.at <= CACHE_TTL_MS) {\n forwardCache.delete(key);\n forwardCache.set(key, { value: hit.value, at: now });\n return hit.value;\n }\n\n const value = gen();\n forwardCache.set(key, { value, at: now });\n if (forwardCache.size > CACHE_MAX) purge(forwardCache);\n if (idempotent) rememberProduced(value);\n return value;\n}\n\n/* ------------------------------------------------------------------ *\n * Curated name pools\n * ------------------------------------------------------------------ */\n\nconst FIRST_NAMES: readonly string[] = [\n \"Jane\",\n \"John\",\n \"Alex\",\n \"Maria\",\n \"Sam\",\n \"Olivia\",\n \"Liam\",\n \"Emma\",\n \"Noah\",\n \"Ava\",\n \"Lucas\",\n \"Mia\",\n \"Ethan\",\n \"Sofia\",\n \"Mason\",\n \"Isla\",\n \"Leo\",\n \"Aria\",\n \"Henry\",\n \"Zoe\",\n \"Owen\",\n \"Nora\",\n \"Caleb\",\n \"Lily\",\n \"Ryan\",\n \"Ruby\",\n \"Adam\",\n \"Chloe\",\n \"Eli\",\n \"Hazel\",\n \"Max\",\n \"Iris\",\n \"Ben\",\n \"Clara\",\n \"Theo\",\n \"Maya\",\n \"Felix\",\n \"Elena\",\n \"Jonah\",\n \"Greta\",\n];\n\nconst LAST_NAMES: readonly string[] = [\n \"Doe\",\n \"Smith\",\n \"Johnson\",\n \"Lee\",\n \"Brown\",\n \"Garcia\",\n \"Miller\",\n \"Davis\",\n \"Wilson\",\n \"Moore\",\n \"Taylor\",\n \"Anderson\",\n \"Thomas\",\n \"Jackson\",\n \"White\",\n \"Harris\",\n \"Martin\",\n \"Clark\",\n \"Lewis\",\n \"Walker\",\n \"Hall\",\n \"Young\",\n \"King\",\n \"Wright\",\n \"Hill\",\n \"Green\",\n \"Adams\",\n \"Baker\",\n \"Nelson\",\n \"Carter\",\n \"Mitchell\",\n \"Perez\",\n \"Roberts\",\n \"Turner\",\n \"Phillips\",\n \"Campbell\",\n \"Parker\",\n \"Evans\",\n \"Edwards\",\n \"Collins\",\n];\n\n/* ------------------------------------------------------------------ *\n * Fake value generators (deterministic in value + salt)\n * ------------------------------------------------------------------ */\n\nfunction fakeName(original: string, salt: string): string {\n return memoFake(\"name\", original, salt, () => {\n const rng = seededRng(`name:${original}`, salt);\n const first = pick(rng, FIRST_NAMES);\n const last = pick(rng, LAST_NAMES);\n return `${first} ${last}`;\n });\n}\n\n// Realistic-looking but safe stand-in domains: real consumer providers (the\n// local part is fake, so no real mailbox is implied) plus the canonical\n// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read\n// as real businesses but are intentional placeholders. No example.com.\nconst FAKE_EMAIL_DOMAINS: readonly string[] = [\n \"gmail.com\",\n \"outlook.com\",\n \"icloud.com\",\n \"yahoo.com\",\n \"proton.me\",\n \"hey.com\",\n \"fastmail.com\",\n \"contoso.com\",\n \"fabrikam.com\",\n \"northwind.com\",\n \"acme.io\",\n \"globex.net\",\n];\n\nfunction fakeEmail(original: string, salt: string): string {\n return memoFake(\"email\", original.toLowerCase(), salt, () => {\n const rng = seededRng(`email:${original.toLowerCase()}`, salt);\n const first = pick(rng, FIRST_NAMES).toLowerCase();\n const last = pick(rng, LAST_NAMES).toLowerCase();\n const domain = pick(rng, FAKE_EMAIL_DOMAINS);\n // Vary the local part so addresses don't all look templated.\n const shape = Math.floor(rng() * 6);\n let local: string;\n switch (shape) {\n case 0:\n local = `${first}.${last}`;\n break;\n case 1:\n local = `${first}${last}`;\n break;\n case 2:\n local = `${first[0]}${last}`;\n break;\n case 3:\n local = `${first}.${last}${1 + Math.floor(rng() * 89)}`;\n break;\n case 4:\n local = `${first}_${last}`;\n break;\n default:\n local = `${last}.${first}`;\n break;\n }\n return `${local}@${domain}`;\n });\n}\n\n/**\n * Replace every digit in `numericBody` with a freshly-generated digit while\n * preserving non-digit characters (grouping commas, decimal points) exactly.\n * The first digit is forced non-zero so the digit count is observable.\n */\nfunction fakeNumberBody(\n numericBody: string,\n original: string,\n salt: string,\n): string {\n // Stable per original token, but NOT registered as a produced fake — a\n // fake number coincides with real numbers too often to skip on round-trip.\n return memoFake(\n \"num\",\n original,\n salt,\n () => {\n const rng = seededRng(`num:${original}`, salt);\n let out = \"\";\n let seenDigit = false;\n for (const ch of numericBody) {\n if (ch >= \"0\" && ch <= \"9\") {\n let d: number;\n if (!seenDigit) {\n // Leading digit: 1-9 so length is preserved.\n d = 1 + Math.floor(rng() * 9);\n seenDigit = true;\n } else {\n d = Math.floor(rng() * 10);\n }\n out += String(d);\n } else {\n out += ch;\n }\n }\n return out;\n },\n false,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Protect-first tokenizer (ID-safety core)\n * ------------------------------------------------------------------ */\n\n/**\n * Patterns whose matches must be protected from ANY transform. Order matters:\n * the most structural / specific shapes come first so they win the scan.\n */\nconst PROTECT_PATTERNS: RegExp[] = [\n // URLs / URIs with a scheme.\n /\\b[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/[^\\s]+/g,\n /\\b(?:mailto|data|tel|urn):[^\\s]+/gi,\n // UUID.\n /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/g,\n // JWT — three base64url segments separated by dots.\n /\\b[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\b/g,\n // ISO datetime / date.\n /\\b\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?\\b/g,\n // Bare clock time.\n /\\b\\d{1,2}:\\d{2}(?::\\d{2})?\\b/g,\n // Path-like tokens containing a slash (but not bare prose with slashes —\n // require no spaces and at least one slash with adjacent non-space).\n /(?:\\S*\\/\\S+)+/g,\n // nanoid / hex / base64-ish blobs: an unbroken [A-Za-z0-9_-] run that is\n // either long-with-a-digit, mixes letters AND digits at length >= 10, or\n // contains a `_`/`-` inside the run (real names/numbers never look so).\n /[A-Za-z0-9_-]+/g,\n];\n\nconst PLACEHOLDER_PREFIX = \"\u0001P\";\nconst PLACEHOLDER_SUFFIX = \"\u0001\";\n\nfunction makePlaceholder(index: number): string {\n return `${PLACEHOLDER_PREFIX}${index}${PLACEHOLDER_SUFFIX}`;\n}\n\n/** True if a `[A-Za-z0-9_-]+` run is identifier-shaped (must be protected). */\nfunction looksLikeIdentifierToken(tok: string): boolean {\n if (tok.length < 3) return false;\n const hasLetter = /[A-Za-z]/.test(tok);\n const hasDigit = /[0-9]/.test(tok);\n const hasSep = /[_-]/.test(tok);\n\n // A pure number (optionally with separators handled elsewhere) is NOT an\n // identifier here — the number rule handles those.\n if (!hasLetter && !hasSep) return false;\n\n // Long hex/base64-ish blob with a digit.\n if (tok.length >= 16 && hasDigit) return true;\n // nanoid-ish: length >= 10 mixing letters AND digits.\n if (tok.length >= 10 && hasLetter && hasDigit) return true;\n // Any token that has a `_`/`-` joined inside an unbroken run AND also\n // contains a digit or is long — e.g. `order-2024-abc`, `api_key_v2`.\n if (hasSep && (hasDigit || tok.length >= 10)) return true;\n // Mixed letters+digits adjacency (e.g. `abc123`, `v2`, `step3`) — protect so\n // the number rule never bites an embedded number.\n if (hasLetter && hasDigit) return true;\n\n return false;\n}\n\ninterface Protection {\n text: string;\n restore: Map<string, string>;\n}\n\n/**\n * Walk `text`, replace every protected substring with an opaque placeholder,\n * and return the masked text plus a restore map. Non-overlapping, left-to-right\n * earliest-match-wins so a transform literally cannot see a protected value.\n */\nfunction protect(text: string): Protection {\n const restore = new Map<string, string>();\n let counter = 0;\n\n // Collect all candidate matches across patterns, then resolve overlaps by\n // earliest start (and longest on tie).\n interface Span {\n start: number;\n end: number;\n value: string;\n }\n const spans: Span[] = [];\n\n for (let p = 0; p < PROTECT_PATTERNS.length; p++) {\n const re = new RegExp(\n PROTECT_PATTERNS[p].source,\n PROTECT_PATTERNS[p].flags,\n );\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const value = m[0];\n if (value.length === 0) {\n re.lastIndex++;\n continue;\n }\n const isTokenPattern = p === PROTECT_PATTERNS.length - 1;\n if (isTokenPattern && !looksLikeIdentifierToken(value)) {\n continue;\n }\n spans.push({ start: m.index, end: m.index + value.length, value });\n }\n }\n\n if (spans.length === 0) return { text, restore };\n\n spans.sort((a, b) =>\n a.start !== b.start ? a.start - b.start : b.end - a.end,\n );\n\n let out = \"\";\n let cursor = 0;\n for (const span of spans) {\n if (span.start < cursor) continue; // overlapped by an earlier protection\n out += text.slice(cursor, span.start);\n const ph = makePlaceholder(counter++);\n restore.set(ph, span.value);\n out += ph;\n cursor = span.end;\n }\n out += text.slice(cursor);\n\n return { text: out, restore };\n}\n\nfunction unprotect(text: string, restore: Map<string, string>): string {\n if (restore.size === 0) return text;\n let out = text;\n for (const [ph, original] of restore) {\n out = out.split(ph).join(original);\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ *\n * Transforms (run only on protected text)\n * ------------------------------------------------------------------ */\n\nconst EMAIL_RE = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n\n// 2+ capitalized words (each starts uppercase, allows internal lowercase /\n// apostrophes / hyphens). Single-letter middle initials allowed: `Sarah J Connor`.\nconst FULL_NAME_RE = /\\b[A-Z][a-zA-Z'’-]*(?:\\s+[A-Z](?:[a-zA-Z'’-]*)?){1,3}\\b/g;\n\n// A standalone numeric token: optional currency + sign, digits with optional\n// comma grouping and a single optional decimal part. Bounded so it is NOT\n// adjacent to a letter (placeholders already removed letter-mixed tokens, but\n// this keeps the rule self-contained and safe on raw structured values too).\nconst NUMBER_RE =\n /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\\d[\\d,]*(?:\\.\\d+)?)(?![A-Za-z0-9_])/g;\n\nfunction transformEmails(text: string, salt: string): string {\n return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));\n}\n\nfunction transformNames(text: string, salt: string): string {\n return text.replace(FULL_NAME_RE, (match) => fakeName(match, salt));\n}\n\nfunction isProbablyYear(digits: string): boolean {\n if (digits.length !== 4) return false;\n const n = Number(digits);\n return n >= 1900 && n <= 2099;\n}\n\nfunction transformNumbers(text: string, salt: string): string {\n return text.replace(\n NUMBER_RE,\n (_full, pre: string, currency: string, sign: string, body: string) => {\n const hasGrouping = body.includes(\",\");\n const hasDecimal = body.includes(\".\");\n const digitsOnly = body.replace(/[^0-9]/g, \"\");\n\n // Skip bare years like 2026.\n if (\n !currency &&\n !sign &&\n !hasGrouping &&\n !hasDecimal &&\n isProbablyYear(digitsOnly)\n ) {\n return `${pre}${currency}${sign}${body}`;\n }\n\n // Skip standalone integers < 1000 with no currency and no grouping\n // (rewriting \"3 unread\" / \"page 2\" looks broken and isn't sensitive).\n if (!currency && !hasGrouping && !hasDecimal) {\n const n = Number(digitsOnly);\n if (Number.isFinite(n) && n < 1000) {\n return `${pre}${currency}${sign}${body}`;\n }\n }\n\n const fakeBody = fakeNumberBody(body, `${currency}${sign}${body}`, salt);\n return `${pre}${currency}${sign}${fakeBody}`;\n },\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Public: string redactor\n * ------------------------------------------------------------------ */\n\nfunction redactDemoStringInternal(\n text: string,\n salt: string,\n redactNames: boolean,\n): string {\n if (typeof text !== \"string\" || text.length === 0) return text;\n\n const { text: masked, restore } = protect(text);\n let out = masked;\n out = transformEmails(out, salt);\n if (redactNames) out = transformNames(out, salt);\n out = transformNumbers(out, salt);\n return unprotect(out, restore);\n}\n\nexport function redactDemoString(text: string, opts?: RedactOptions): string {\n return redactDemoStringInternal(text, opts?.salt ?? \"\", true);\n}\n\n/* ------------------------------------------------------------------ *\n * Public: structure-aware redactor\n * ------------------------------------------------------------------ */\n\n// Keys whose leaf values must NEVER be transformed (still recurse into nested\n// objects/arrays under them). Besides ids/urls/timestamps this also covers\n// code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):\n// prose-redacting a SQL string injects fake emails/numbers into it and rewrites\n// its leading tokens, producing `syntax error at or near \"Henry\"` /\n// `queries must start with SELECT or WITH`. The query must run untouched; its\n// RESULTS are what get redacted so the chart still shows fake values.\nconst PROTECTED_KEY_RE =\n /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;\n\n// UI labels and chart/dashboard titles often look like person names (\"Maya\n// Davis (First-party)\", \"Clicks by Henry Moore\") but are structural labels. Keep\n// them stable while still redacting free-text and contact-style person fields.\nconst LABEL_TEXT_KEY_RE = /^(name|title|label)$/i;\n\nconst MAX_DEPTH = 64;\n\nfunction isStandalonePersonNameLabel(text: string): boolean {\n const trimmed = text.trim();\n if (!trimmed) return false;\n return /^[A-Z][a-zA-Z'’-]+(?:\\s+[A-Z]\\.?)?\\s+[A-Z][a-zA-Z'’-]+$/.test(\n trimmed,\n );\n}\n\nfunction shouldRedactNamesForChild(key: string, entry: unknown): boolean {\n if (!LABEL_TEXT_KEY_RE.test(key)) return true;\n // Preserve structural labels/titles, but do not let common contact-shaped\n // fields like `{ name: \"Olivia Parker\" }` leak real person names.\n return typeof entry === \"string\" ? isStandalonePersonNameLabel(entry) : true;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n if (value instanceof Date) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction redactDemoStringWithSalt(\n text: string,\n salt: string,\n redactNames: boolean,\n): string {\n return redactDemoStringInternal(text, salt, redactNames);\n}\n\nfunction redactNumberLeaf(value: number, salt: string): number {\n if (!Number.isFinite(value)) return value;\n const repr = String(value);\n // Re-use the string number transform but only if the representation is a\n // clean numeric token we can round-trip back to a JS number.\n const redacted = transformNumbers(repr, salt);\n if (redacted === repr) return value;\n const n = Number(redacted);\n if (!Number.isFinite(n)) return value;\n return n;\n}\n\nfunction walk(\n value: unknown,\n salt: string,\n depth: number,\n seen: WeakSet<object>,\n redactNames: boolean,\n): unknown {\n if (depth > MAX_DEPTH) return value;\n\n if (value === null || value === undefined) return value;\n\n const t = typeof value;\n\n if (t === \"string\") {\n return redactDemoStringWithSalt(value as string, salt, redactNames);\n }\n\n if (t === \"number\") {\n return redactNumberLeaf(value as number, salt);\n }\n\n if (t === \"boolean\" || t === \"bigint\" || t === \"function\" || t === \"symbol\") {\n return value;\n }\n\n if (value instanceof Date) return value;\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out = value.map((item) =>\n walk(item, salt, depth + 1, seen, redactNames),\n );\n seen.delete(value);\n return out;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n const keyIsProtected = PROTECTED_KEY_RE.test(key);\n if (keyIsProtected) {\n if (\n entry !== null &&\n typeof entry === \"object\" &&\n !(entry instanceof Date)\n ) {\n // Still recurse into nested structures, but the protected key does\n // not transform its own leaf value.\n out[key] = walk(entry, salt, depth + 1, seen, redactNames);\n } else {\n // Leaf under a protected key: pass through completely untouched.\n out[key] = entry;\n }\n continue;\n }\n out[key] = walk(\n entry,\n salt,\n depth + 1,\n seen,\n redactNames && shouldRedactNamesForChild(key, entry),\n );\n }\n seen.delete(value);\n return out;\n }\n\n // Unknown object kind (Map, Set, class instance, etc.) — leave untouched.\n return value;\n}\n\nexport function redactDemoData<T>(value: T, opts?: RedactOptions): T {\n const salt = opts?.salt ?? \"\";\n return walk(value, salt, 0, new WeakSet<object>(), true) as T;\n}\n\n/**\n * Clear the stable-mapping caches. Test-only — the caches are process-global\n * (intentionally, so mappings stay stable for a tab's session), which would\n * otherwise let one test's produced fakes leak into another's assertions.\n */\nexport function __resetDemoRedactCacheForTests(): void {\n forwardCache.clear();\n producedFakes.clear();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/demo/redact.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure, dependency-free, deterministic demo-mode redactor.\n *\n * Replaces sensitive values (emails and free numbers) with stable fake\n * substitutes so a demo looks coherent — the same input always maps to the\n * same fake. Crucially, it NEVER rewrites identifiers, structural tokens, or\n * timestamps. Names and other free text are deliberately left alone because\n * guessing whether arbitrary text is a person's name is too inaccurate. The\n * string redactor uses a protect-first strategy (mask IDs with opaque\n * placeholders before any transform runs, restore them byte-identical\n * afterwards), and the structure-aware walker additionally protects leaf\n * values by key name.\n */\n\nexport interface RedactOptions {\n salt?: string;\n}\n\n/* ------------------------------------------------------------------ *\n * Seeded hash + PRNG (xmur3 seed → mulberry32 stream)\n * ------------------------------------------------------------------ */\n\nfunction xmur3(str: string): () => number {\n let h = 1779033703 ^ str.length;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 3432918353);\n h = (h << 13) | (h >>> 19);\n }\n return function () {\n h = Math.imul(h ^ (h >>> 16), 2246822507);\n h = Math.imul(h ^ (h >>> 13), 3266489909);\n h ^= h >>> 16;\n return h >>> 0;\n };\n}\n\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return function () {\n a = (a + 0x6d2b79f5) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 15), t | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** Deterministic PRNG seeded by `value + salt`. */\nfunction seededRng(value: string, salt: string): () => number {\n const seedFn = xmur3(`${value}${salt}`);\n return mulberry32(seedFn());\n}\n\nfunction pick<T>(rng: () => number, pool: readonly T[]): T {\n return pool[Math.floor(rng() * pool.length) % pool.length];\n}\n\n/* ------------------------------------------------------------------ *\n * Stable mapping cache (bounded, TTL, leak-free)\n *\n * The fake values are already a pure deterministic function of\n * (kind, salt, original), so identical input is always stable. This cache\n * adds two things on top:\n *\n * 1. A consistent forward map so the same original keeps the same fake for\n * the life of the entry, even if the algorithm/salt is ever tuned.\n * 2. Idempotency: every fake we emit is remembered, so when a fake value\n * round-trips back through redaction (e.g. you edit a draft that's\n * already showing fake text, it autosaves, then refetches) it is passed\n * through UNCHANGED instead of being re-faked into something new. This\n * is what stops emails drifting on every edit.\n *\n * Leak-free by construction: no timers, a hard size cap, and lazy TTL purge\n * on write. Works the same per-tab in the browser and per-process on the\n * server. Memoizing a pure function across users is safe — output depends\n * only on input.\n * ------------------------------------------------------------------ */\n\nconst CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour\nconst CACHE_MAX = 5000;\n\n// original-key → { fake, at }. Insertion-ordered (Map) so the oldest key is\n// first — used for cap eviction.\nconst forwardCache = new Map<string, { value: string; at: number }>();\n// produced fake → last-seen timestamp (same bound/TTL policy).\nconst producedFakes = new Map<string, number>();\n\nfunction purge(map: Map<string, { at: number } | number>): void {\n const now = Date.now();\n for (const [k, v] of map) {\n const at = typeof v === \"number\" ? v : v.at;\n if (now - at > CACHE_TTL_MS) map.delete(k);\n else break; // insertion-ordered: first fresh entry ⇒ rest are fresher\n }\n while (map.size > CACHE_MAX) {\n const oldest = map.keys().next().value as string | undefined;\n if (oldest === undefined) break;\n map.delete(oldest);\n }\n}\n\nfunction rememberProduced(fake: string): string {\n if (fake.length === 0) return fake;\n producedFakes.delete(fake);\n producedFakes.set(fake, Date.now());\n if (producedFakes.size > CACHE_MAX) purge(producedFakes);\n return fake;\n}\n\nfunction isProducedFake(value: string): boolean {\n const at = producedFakes.get(value);\n if (at === undefined) return false;\n if (Date.now() - at > CACHE_TTL_MS) {\n producedFakes.delete(value);\n return false;\n }\n return true;\n}\n\n/**\n * Memoize a deterministic fake by (kind, salt, original). On a hit, the\n * entry's recency is refreshed (LRU-ish). The generated value is also\n * registered as a produced fake so it survives a round-trip unchanged.\n */\nfunction memoFake(\n kind: string,\n original: string,\n salt: string,\n gen: () => string,\n // Numbers opt out: a fake number collides with real numbers far too often\n // to safely treat \"looks like one we emitted\" as \"leave it alone\".\n idempotent = true,\n): string {\n // Already one of our fakes? Leave it exactly as-is (round-trip stable).\n if (idempotent && isProducedFake(original)) return original;\n\n const key = `${kind}${salt}${original}`;\n const hit = forwardCache.get(key);\n const now = Date.now();\n if (hit && now - hit.at <= CACHE_TTL_MS) {\n forwardCache.delete(key);\n forwardCache.set(key, { value: hit.value, at: now });\n return hit.value;\n }\n\n const value = gen();\n forwardCache.set(key, { value, at: now });\n if (forwardCache.size > CACHE_MAX) purge(forwardCache);\n if (idempotent) rememberProduced(value);\n return value;\n}\n\n/* ------------------------------------------------------------------ *\n * Curated name pools\n * ------------------------------------------------------------------ */\n\nconst FIRST_NAMES: readonly string[] = [\n \"Jane\",\n \"John\",\n \"Alex\",\n \"Maria\",\n \"Sam\",\n \"Olivia\",\n \"Liam\",\n \"Emma\",\n \"Noah\",\n \"Ava\",\n \"Lucas\",\n \"Mia\",\n \"Ethan\",\n \"Sofia\",\n \"Mason\",\n \"Isla\",\n \"Leo\",\n \"Aria\",\n \"Henry\",\n \"Zoe\",\n \"Owen\",\n \"Nora\",\n \"Caleb\",\n \"Lily\",\n \"Ryan\",\n \"Ruby\",\n \"Adam\",\n \"Chloe\",\n \"Eli\",\n \"Hazel\",\n \"Max\",\n \"Iris\",\n \"Ben\",\n \"Clara\",\n \"Theo\",\n \"Maya\",\n \"Felix\",\n \"Elena\",\n \"Jonah\",\n \"Greta\",\n];\n\nconst LAST_NAMES: readonly string[] = [\n \"Doe\",\n \"Smith\",\n \"Johnson\",\n \"Lee\",\n \"Brown\",\n \"Garcia\",\n \"Miller\",\n \"Davis\",\n \"Wilson\",\n \"Moore\",\n \"Taylor\",\n \"Anderson\",\n \"Thomas\",\n \"Jackson\",\n \"White\",\n \"Harris\",\n \"Martin\",\n \"Clark\",\n \"Lewis\",\n \"Walker\",\n \"Hall\",\n \"Young\",\n \"King\",\n \"Wright\",\n \"Hill\",\n \"Green\",\n \"Adams\",\n \"Baker\",\n \"Nelson\",\n \"Carter\",\n \"Mitchell\",\n \"Perez\",\n \"Roberts\",\n \"Turner\",\n \"Phillips\",\n \"Campbell\",\n \"Parker\",\n \"Evans\",\n \"Edwards\",\n \"Collins\",\n];\n\n/* ------------------------------------------------------------------ *\n * Fake value generators (deterministic in value + salt)\n * ------------------------------------------------------------------ */\n\n// Realistic-looking but safe stand-in domains: real consumer providers (the\n// local part is fake, so no real mailbox is implied) plus the canonical\n// reserved fictional-company domains (Contoso/Fabrikam/Northwind), which read\n// as real businesses but are intentional placeholders. No example.com.\nconst FAKE_EMAIL_DOMAINS: readonly string[] = [\n \"gmail.com\",\n \"outlook.com\",\n \"icloud.com\",\n \"yahoo.com\",\n \"proton.me\",\n \"hey.com\",\n \"fastmail.com\",\n \"contoso.com\",\n \"fabrikam.com\",\n \"northwind.com\",\n \"acme.io\",\n \"globex.net\",\n];\n\nfunction fakeEmail(original: string, salt: string): string {\n return memoFake(\"email\", original.toLowerCase(), salt, () => {\n const rng = seededRng(`email:${original.toLowerCase()}`, salt);\n const first = pick(rng, FIRST_NAMES).toLowerCase();\n const last = pick(rng, LAST_NAMES).toLowerCase();\n const domain = pick(rng, FAKE_EMAIL_DOMAINS);\n // Vary the local part so addresses don't all look templated.\n const shape = Math.floor(rng() * 6);\n let local: string;\n switch (shape) {\n case 0:\n local = `${first}.${last}`;\n break;\n case 1:\n local = `${first}${last}`;\n break;\n case 2:\n local = `${first[0]}${last}`;\n break;\n case 3:\n local = `${first}.${last}${1 + Math.floor(rng() * 89)}`;\n break;\n case 4:\n local = `${first}_${last}`;\n break;\n default:\n local = `${last}.${first}`;\n break;\n }\n return `${local}@${domain}`;\n });\n}\n\n/**\n * Replace every digit in `numericBody` with a freshly-generated digit while\n * preserving non-digit characters (grouping commas, decimal points) exactly.\n * The first digit is forced non-zero so the digit count is observable.\n */\nfunction fakeNumberBody(\n numericBody: string,\n original: string,\n salt: string,\n): string {\n // Stable per original token, but NOT registered as a produced fake — a\n // fake number coincides with real numbers too often to skip on round-trip.\n return memoFake(\n \"num\",\n original,\n salt,\n () => {\n const rng = seededRng(`num:${original}`, salt);\n let out = \"\";\n let seenDigit = false;\n for (const ch of numericBody) {\n if (ch >= \"0\" && ch <= \"9\") {\n let d: number;\n if (!seenDigit) {\n // Leading digit: 1-9 so length is preserved.\n d = 1 + Math.floor(rng() * 9);\n seenDigit = true;\n } else {\n d = Math.floor(rng() * 10);\n }\n out += String(d);\n } else {\n out += ch;\n }\n }\n return out;\n },\n false,\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Protect-first tokenizer (ID-safety core)\n * ------------------------------------------------------------------ */\n\n/**\n * Patterns whose matches must be protected from ANY transform. Order matters:\n * the most structural / specific shapes come first so they win the scan.\n */\nconst PROTECT_PATTERNS: RegExp[] = [\n // URLs / URIs with a scheme.\n /\\b[a-zA-Z][a-zA-Z0-9+.-]*:\\/\\/[^\\s]+/g,\n /\\b(?:mailto|data|tel|urn):[^\\s]+/gi,\n // UUID.\n /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/g,\n // JWT — three base64url segments separated by dots.\n /\\b[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\.[A-Za-z0-9_-]{4,}\\b/g,\n // ISO datetime / date.\n /\\b\\d{4}-\\d{2}-\\d{2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?\\b/g,\n // Bare clock time.\n /\\b\\d{1,2}:\\d{2}(?::\\d{2})?\\b/g,\n // Path-like tokens containing a slash (but not bare prose with slashes —\n // require no spaces and at least one slash with adjacent non-space).\n /(?:\\S*\\/\\S+)+/g,\n // nanoid / hex / base64-ish blobs: an unbroken [A-Za-z0-9_-] run that is\n // either long-with-a-digit, mixes letters AND digits at length >= 10, or\n // contains a `_`/`-` inside the run (real names/numbers never look so).\n /[A-Za-z0-9_-]+/g,\n];\n\nconst PLACEHOLDER_PREFIX = \"\u0001P\";\nconst PLACEHOLDER_SUFFIX = \"\u0001\";\n\nfunction makePlaceholder(index: number): string {\n return `${PLACEHOLDER_PREFIX}${index}${PLACEHOLDER_SUFFIX}`;\n}\n\n/** True if a `[A-Za-z0-9_-]+` run is identifier-shaped (must be protected). */\nfunction looksLikeIdentifierToken(tok: string): boolean {\n if (tok.length < 3) return false;\n const hasLetter = /[A-Za-z]/.test(tok);\n const hasDigit = /[0-9]/.test(tok);\n const hasSep = /[_-]/.test(tok);\n\n // A pure number (optionally with separators handled elsewhere) is NOT an\n // identifier here — the number rule handles those.\n if (!hasLetter && !hasSep) return false;\n\n // Long hex/base64-ish blob with a digit.\n if (tok.length >= 16 && hasDigit) return true;\n // nanoid-ish: length >= 10 mixing letters AND digits.\n if (tok.length >= 10 && hasLetter && hasDigit) return true;\n // Any token that has a `_`/`-` joined inside an unbroken run AND also\n // contains a digit or is long — e.g. `order-2024-abc`, `api_key_v2`.\n if (hasSep && (hasDigit || tok.length >= 10)) return true;\n // Mixed letters+digits adjacency (e.g. `abc123`, `v2`, `step3`) — protect so\n // the number rule never bites an embedded number.\n if (hasLetter && hasDigit) return true;\n\n return false;\n}\n\ninterface Protection {\n text: string;\n restore: Map<string, string>;\n}\n\n/**\n * Walk `text`, replace every protected substring with an opaque placeholder,\n * and return the masked text plus a restore map. Non-overlapping, left-to-right\n * earliest-match-wins so a transform literally cannot see a protected value.\n */\nfunction protect(text: string): Protection {\n const restore = new Map<string, string>();\n let counter = 0;\n\n // Collect all candidate matches across patterns, then resolve overlaps by\n // earliest start (and longest on tie).\n interface Span {\n start: number;\n end: number;\n value: string;\n }\n const spans: Span[] = [];\n\n for (let p = 0; p < PROTECT_PATTERNS.length; p++) {\n const re = new RegExp(\n PROTECT_PATTERNS[p].source,\n PROTECT_PATTERNS[p].flags,\n );\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n const value = m[0];\n if (value.length === 0) {\n re.lastIndex++;\n continue;\n }\n const isTokenPattern = p === PROTECT_PATTERNS.length - 1;\n if (isTokenPattern && !looksLikeIdentifierToken(value)) {\n continue;\n }\n spans.push({ start: m.index, end: m.index + value.length, value });\n }\n }\n\n if (spans.length === 0) return { text, restore };\n\n spans.sort((a, b) =>\n a.start !== b.start ? a.start - b.start : b.end - a.end,\n );\n\n let out = \"\";\n let cursor = 0;\n for (const span of spans) {\n if (span.start < cursor) continue; // overlapped by an earlier protection\n out += text.slice(cursor, span.start);\n const ph = makePlaceholder(counter++);\n restore.set(ph, span.value);\n out += ph;\n cursor = span.end;\n }\n out += text.slice(cursor);\n\n return { text: out, restore };\n}\n\nfunction unprotect(text: string, restore: Map<string, string>): string {\n if (restore.size === 0) return text;\n let out = text;\n for (const [ph, original] of restore) {\n out = out.split(ph).join(original);\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ *\n * Transforms (run only on protected text)\n * ------------------------------------------------------------------ */\n\nconst EMAIL_RE = /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b/g;\n\n// A standalone numeric token: optional currency + sign, digits with optional\n// comma grouping and a single optional decimal part. Bounded so it is NOT\n// adjacent to a letter (placeholders already removed letter-mixed tokens, but\n// this keeps the rule self-contained and safe on raw structured values too).\nconst NUMBER_RE =\n /(^|[^A-Za-z0-9_])([$€£]?)([+-]?)(\\d[\\d,]*(?:\\.\\d+)?)(?![A-Za-z0-9_])/g;\n\nfunction transformEmails(text: string, salt: string): string {\n return text.replace(EMAIL_RE, (match) => fakeEmail(match, salt));\n}\n\nfunction isProbablyYear(digits: string): boolean {\n if (digits.length !== 4) return false;\n const n = Number(digits);\n return n >= 1900 && n <= 2099;\n}\n\nfunction transformNumbers(text: string, salt: string): string {\n return text.replace(\n NUMBER_RE,\n (_full, pre: string, currency: string, sign: string, body: string) => {\n const hasGrouping = body.includes(\",\");\n const hasDecimal = body.includes(\".\");\n const digitsOnly = body.replace(/[^0-9]/g, \"\");\n\n // Skip bare years like 2026.\n if (\n !currency &&\n !sign &&\n !hasGrouping &&\n !hasDecimal &&\n isProbablyYear(digitsOnly)\n ) {\n return `${pre}${currency}${sign}${body}`;\n }\n\n // Skip standalone integers < 1000 with no currency and no grouping\n // (rewriting \"3 unread\" / \"page 2\" looks broken and isn't sensitive).\n if (!currency && !hasGrouping && !hasDecimal) {\n const n = Number(digitsOnly);\n if (Number.isFinite(n) && n < 1000) {\n return `${pre}${currency}${sign}${body}`;\n }\n }\n\n const fakeBody = fakeNumberBody(body, `${currency}${sign}${body}`, salt);\n return `${pre}${currency}${sign}${fakeBody}`;\n },\n );\n}\n\n/* ------------------------------------------------------------------ *\n * Public: string redactor\n * ------------------------------------------------------------------ */\n\nfunction redactDemoStringInternal(text: string, salt: string): string {\n if (typeof text !== \"string\" || text.length === 0) return text;\n\n const { text: masked, restore } = protect(text);\n let out = masked;\n out = transformEmails(out, salt);\n out = transformNumbers(out, salt);\n return unprotect(out, restore);\n}\n\nexport function redactDemoString(text: string, opts?: RedactOptions): string {\n return redactDemoStringInternal(text, opts?.salt ?? \"\");\n}\n\n/* ------------------------------------------------------------------ *\n * Public: structure-aware redactor\n * ------------------------------------------------------------------ */\n\n// Keys whose leaf values must NEVER be transformed (still recurse into nested\n// objects/arrays under them). Besides ids/urls/timestamps this also covers\n// code/query-bearing keys (`sql`, `query`, `expression`, `formula`, `code`):\n// redacting a SQL string mutates literals and can make the query semantically\n// wrong or invalid. The query must run untouched; its RESULTS are what get\n// redacted so the chart still shows fake values.\nconst PROTECTED_KEY_RE =\n /^id$|(^|_)id$|Id$|Ids$|uuid|guid|slug|token|secret|password|passwd|apikey|api_key|hash|sha\\d*|etag|cursor|nonce|sessionid|messageid|threadid|nodeid|(^|_)key$|keyid|(^|_)ref$|url$|uri$|href$|src$|path$|filename$|mimetype|mime|^sql$|sql$|query|expression|formula|^code$|createdat|updatedat|deletedat|expiresat|timestamp|.+at$|.+_at$/i;\n\nconst MAX_DEPTH = 64;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n if (value instanceof Date) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction redactNumberLeaf(value: number, salt: string): number {\n if (!Number.isFinite(value)) return value;\n const repr = String(value);\n // Re-use the string number transform but only if the representation is a\n // clean numeric token we can round-trip back to a JS number.\n const redacted = transformNumbers(repr, salt);\n if (redacted === repr) return value;\n const n = Number(redacted);\n if (!Number.isFinite(n)) return value;\n return n;\n}\n\nfunction walk(\n value: unknown,\n salt: string,\n depth: number,\n seen: WeakSet<object>,\n): unknown {\n if (depth > MAX_DEPTH) return value;\n\n if (value === null || value === undefined) return value;\n\n const t = typeof value;\n\n if (t === \"string\") {\n return redactDemoStringInternal(value as string, salt);\n }\n\n if (t === \"number\") {\n return redactNumberLeaf(value as number, salt);\n }\n\n if (t === \"boolean\" || t === \"bigint\" || t === \"function\" || t === \"symbol\") {\n return value;\n }\n\n if (value instanceof Date) return value;\n\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out = value.map((item) => walk(item, salt, depth + 1, seen));\n seen.delete(value);\n return out;\n }\n\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n const keyIsProtected = PROTECTED_KEY_RE.test(key);\n if (keyIsProtected) {\n if (\n entry !== null &&\n typeof entry === \"object\" &&\n !(entry instanceof Date)\n ) {\n // Still recurse into nested structures, but the protected key does\n // not transform its own leaf value.\n out[key] = walk(entry, salt, depth + 1, seen);\n } else {\n // Leaf under a protected key: pass through completely untouched.\n out[key] = entry;\n }\n continue;\n }\n out[key] = walk(entry, salt, depth + 1, seen);\n }\n seen.delete(value);\n return out;\n }\n\n // Unknown object kind (Map, Set, class instance, etc.) — leave untouched.\n return value;\n}\n\nexport function redactDemoData<T>(value: T, opts?: RedactOptions): T {\n const salt = opts?.salt ?? \"\";\n return walk(value, salt, 0, new WeakSet<object>()) as T;\n}\n\n/**\n * Clear the stable-mapping caches. Test-only — the caches are process-global\n * (intentionally, so mappings stay stable for a tab's session), which would\n * otherwise let one test's produced fakes leak into another's assertions.\n */\nexport function __resetDemoRedactCacheForTests(): void {\n forwardCache.clear();\n producedFakes.clear();\n}\n"]}
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
14
|
count: number;
|
|
15
15
|
updated?: undefined;
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error?: undefined;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
count?: undefined;
|
|
20
20
|
updated: number;
|
|
21
|
-
ok?: undefined;
|
|
22
21
|
error?: undefined;
|
|
22
|
+
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
25
25
|
updated?: undefined;
|
|
@@ -41,28 +41,28 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
-
error?: undefined;
|
|
45
|
-
ok?: undefined;
|
|
46
44
|
summary: import("./types.js").TraceSummary;
|
|
47
45
|
spans: import("./types.js").TraceSpan[];
|
|
48
46
|
id?: undefined;
|
|
49
|
-
} | {
|
|
50
47
|
error?: undefined;
|
|
51
48
|
ok?: undefined;
|
|
49
|
+
} | {
|
|
52
50
|
summary?: undefined;
|
|
53
51
|
spans?: undefined;
|
|
54
52
|
id: string;
|
|
55
|
-
|
|
53
|
+
error?: undefined;
|
|
56
54
|
ok?: undefined;
|
|
55
|
+
} | {
|
|
57
56
|
summary?: undefined;
|
|
58
57
|
spans?: undefined;
|
|
59
58
|
id?: undefined;
|
|
60
59
|
error: any;
|
|
60
|
+
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
-
error?: undefined;
|
|
63
62
|
summary?: undefined;
|
|
64
63
|
spans?: undefined;
|
|
65
64
|
id?: undefined;
|
|
65
|
+
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
73
73
|
offset?: unknown;
|
|
74
74
|
limit?: unknown;
|
|
75
75
|
}, {
|
|
76
|
+
deleted?: undefined;
|
|
76
77
|
jobs: {
|
|
77
78
|
id: string;
|
|
78
79
|
name: string;
|
|
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
83
84
|
updatedAt: string;
|
|
84
85
|
}[];
|
|
85
86
|
total: number;
|
|
86
|
-
deleted?: undefined;
|
|
87
87
|
jobId?: undefined;
|
|
88
88
|
} | {
|
|
89
89
|
jobs?: undefined;
|
|
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
91
91
|
deleted: boolean;
|
|
92
92
|
jobId: string;
|
|
93
93
|
} | {
|
|
94
|
+
deleted?: undefined;
|
|
94
95
|
jobs?: undefined;
|
|
95
96
|
total?: undefined;
|
|
96
|
-
deleted?: undefined;
|
|
97
97
|
jobId?: undefined;
|
|
98
98
|
hits: Record<string, unknown>[];
|
|
99
99
|
offset: number;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
|
|
|
34
34
|
/** POST /_agent-native/secrets/:key — write a secret. */
|
|
35
35
|
export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
36
36
|
error: string;
|
|
37
|
-
ok?: undefined;
|
|
38
37
|
status?: undefined;
|
|
38
|
+
ok?: undefined;
|
|
39
39
|
} | {
|
|
40
|
-
error?: undefined;
|
|
41
40
|
ok: boolean;
|
|
42
41
|
status: string;
|
|
42
|
+
error?: undefined;
|
|
43
43
|
} | {
|
|
44
|
-
ok?: undefined;
|
|
45
44
|
error: string;
|
|
46
45
|
removed?: undefined;
|
|
46
|
+
ok?: undefined;
|
|
47
47
|
} | {
|
|
48
|
-
error?: undefined;
|
|
49
48
|
ok: boolean;
|
|
50
49
|
removed: boolean;
|
|
50
|
+
error?: undefined;
|
|
51
51
|
}>>;
|
|
52
52
|
/**
|
|
53
53
|
* POST /_agent-native/secrets/:key/test — re-run the validator against the
|
|
54
54
|
* current stored value without changing anything. Useful for the "Test" button.
|
|
55
55
|
*/
|
|
56
56
|
export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
57
|
-
ok?: undefined;
|
|
58
57
|
error: string;
|
|
59
58
|
note?: undefined;
|
|
59
|
+
ok?: undefined;
|
|
60
60
|
} | {
|
|
61
|
-
error?: undefined;
|
|
62
61
|
ok: boolean;
|
|
63
62
|
note?: undefined;
|
|
64
|
-
} | {
|
|
65
63
|
error?: undefined;
|
|
64
|
+
} | {
|
|
66
65
|
ok: boolean;
|
|
67
66
|
note: string;
|
|
67
|
+
error?: undefined;
|
|
68
68
|
} | {
|
|
69
69
|
note?: undefined;
|
|
70
70
|
ok: boolean;
|
|
@@ -95,12 +95,12 @@ export interface AdHocSecretPayload {
|
|
|
95
95
|
export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
|
|
96
96
|
error: string;
|
|
97
97
|
} | {
|
|
98
|
-
error?: undefined;
|
|
99
98
|
ok: boolean;
|
|
100
99
|
key: string;
|
|
101
|
-
} | {
|
|
102
100
|
error?: undefined;
|
|
101
|
+
} | {
|
|
103
102
|
ok: boolean;
|
|
104
103
|
removed: boolean;
|
|
104
|
+
error?: undefined;
|
|
105
105
|
}>>;
|
|
106
106
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
27
27
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
28
28
|
error: any;
|
|
29
29
|
} | {
|
|
30
|
-
error?: undefined;
|
|
31
30
|
ok: boolean;
|
|
32
31
|
key: string;
|
|
33
32
|
baseUrlKey?: string;
|
|
34
33
|
scope: AgentEngineApiKeyScope;
|
|
34
|
+
error?: undefined;
|
|
35
35
|
}>>;
|
|
36
36
|
export {};
|
|
37
37
|
//# sourceMappingURL=agent-engine-api-key-route.d.ts.map
|
|
@@ -123,6 +123,28 @@ npx @agent-native/core@latest recap doctor
|
|
|
123
123
|
يثبت مجلد `visual-recap` المخصص له، ويضبط متغير المستودع
|
|
124
124
|
`VISUAL_RECAP_SKILL_SOURCE=repo`.
|
|
125
125
|
|
|
126
|
+
## اختيار المشغّل
|
|
127
|
+
|
|
128
|
+
يعمل سير العمل افتراضيًا على مشغّلات `ubuntu-latest` المستضافة من GitHub. لاستخدام مشغّل مستضاف آخر أو مشغّل ذاتي الاستضافة، اضبط متغير المستودع أو المؤسسة `VISUAL_RECAP_RUNS_ON` على سلسلة JSON صالحة أو مصفوفة JSON من تسميات المشغّل:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
"ubuntu-latest"
|
|
132
|
+
["self-hosted", "linux", "x64", "visual-recap"]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
علامات الاقتباس في JSON مطلوبة. تحدد هذه القيمة مشغّل مهمة `recap` الكاملة. لتكوينه أثناء الإعداد الموجّه، مرّر قيمة JSON نفسها إلى `--runs-on`، ثم تحقق من سير العمل وتوفر المشغّل باستخدام `doctor`:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx @agent-native/core@latest recap setup --runs-on '["self-hosted","linux","x64","visual-recap"]'
|
|
139
|
+
npx @agent-native/core@latest recap doctor
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
تستخدم بوابة الأمان الخفيفة `ubuntu-latest` بشكل منفصل. يمكن للمستودعات التي تعطل مشغّلات GitHub المستضافة ضبط `VISUAL_RECAP_GATE_RUNS_ON` على تسمية نصية واحدة بلا JSON، أو استخدام `--gate-runs-on visual-recap-gate`. تُستخدم التسمية المخصصة فقط لمؤلفي `OWNER` أو `MEMBER` أو `COLLABORATOR` من المستودع نفسه؛ تُفرض `ubuntu-latest` على الفروع والمؤلفين الآخرين وقد تبقى عملياتهم بلا جدولة عند تعطيل مشغّلات GitHub المستضافة. استخدم مشغّلًا مخصصًا ويفضل أن يكون مؤقتًا؛ لا تسحب البوابة القياسية شجرة PR وتقيّم منطق سير العمل وبيانات PR الوصفية.
|
|
143
|
+
|
|
144
|
+
يرفض `recap doctor` بيانات JSON غير الصالحة أو غير المدعومة، ويبلغ عندما لا يعرض GitHub مشغّلًا متصلًا يطابق جميع التسميات المكوّنة. يظل تسجيل المشغّل وتثبيته وترقياته وسعته وصيانته من مسؤوليتك؛ يحدد Agent Native التسميات ولكنه لا يوفر المشغّل ولا يديره.
|
|
145
|
+
|
|
146
|
+
**الأمان:** يُفضّل استخدام مشغّلات ذاتية الاستضافة مؤقتة. يجب أن تخدم المشغّلات الدائمة ذاتية الاستضافة المستودعات الخاصة التي يقتصر المساهمون فيها على أشخاص موثوق بهم. يُغلق سير العمل بأمان قبل جدولة عمل ذاتي الاستضافة لمؤلفي PR غير الموثوق بهم في المستودعات العامة أو المتفرعة، لكن الجهاز الدائم يظل محتفظًا بحالة مساحة العمل والعمليات بين المهام. لا تضعف هذه البوابة ولا توجه مساهمات غير موثوقة إلى مشغّل دائم.
|
|
147
|
+
|
|
126
148
|
## تحديد الخلفية
|
|
127
149
|
|
|
128
150
|
اختر وكيل الترميز الذي يقوم بتشغيل المهارة باستخدام متغير المستودع `VISUAL_RECAP_AGENT`:
|
|
@@ -460,10 +482,12 @@ jobs:
|
|
|
460
482
|
model: ${{ vars.VISUAL_RECAP_MODEL || '' }}
|
|
461
483
|
reasoning: ${{ vars.VISUAL_RECAP_REASONING || '' }}
|
|
462
484
|
skill-source: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || 'auto' }}
|
|
485
|
+
runs-on: ${{ vars.VISUAL_RECAP_RUNS_ON || '"ubuntu-latest"' }}
|
|
486
|
+
gate-runs-on: ${{ vars.VISUAL_RECAP_GATE_RUNS_ON || 'ubuntu-latest' }}
|
|
463
487
|
# cli-version: "latest" # pin to a specific @agent-native/core version
|
|
464
488
|
```
|
|
465
489
|
|
|
466
|
-
تنطبق
|
|
490
|
+
تنطبق الأسرار والمتغيرات نفسها الموضحة في [Secrets and variables](#secrets-and-variables). يمرر المتصل القابل لإعادة الاستخدام `VISUAL_RECAP_RUNS_ON` كـ `runs-on` للمهمة الكاملة، و`VISUAL_RECAP_GATE_RUNS_ON` كتسمية مفردة `gate-runs-on` للبوابة. يستخدم كلاهما `ubuntu-latest` عند الحذف.
|
|
467
491
|
|
|
468
492
|
### التثبيت عبر CLI
|
|
469
493
|
|
|
@@ -290,7 +290,7 @@ npx @agent-native/core@latest plan local serve --dir plans/<slug> --kind plan --
|
|
|
290
290
|
```
|
|
291
291
|
|
|
292
292
|
يبدو شكل الجسر URL
|
|
293
|
-
`https://plan.agent-native.com/local-plans
|
|
293
|
+
`https://plan.agent-native.com/local-plans/local-<opaque-id>#bridge=http://127.0.0.1:...`.
|
|
294
294
|
الصفحة هي عارض الخطة العادي، لكن المتصفح يجلب `plan.mdx`،
|
|
295
295
|
`canvas.mdx`، و`prototype.mdx`، و`.plan-state.json`، وأصول الصور المحلية من
|
|
296
296
|
جسر المضيف المحلي. لا تتم كتابة محتوى الخطة في قاعدة البيانات المستضافة وهي
|
|
@@ -123,6 +123,28 @@ Referenzdateien, mit denen der Skill geliefert wird. Wenn Ihr Repo absichtlich a
|
|
|
123
123
|
pinnen den festgeschriebenen `visual-recap`-Ordner an und legen die Repository-Variable fest
|
|
124
124
|
`VISUAL_RECAP_SKILL_SOURCE=repo`.
|
|
125
125
|
|
|
126
|
+
## Runner-Auswahl
|
|
127
|
+
|
|
128
|
+
Standardmäßig wird der Workflow auf von GitHub gehosteten `ubuntu-latest`-Runnern ausgeführt. Um einen anderen gehosteten Runner oder einen eigenen selbst gehosteten Runner zu verwenden, setzen Sie die Repository- oder Organisationsvariable `VISUAL_RECAP_RUNS_ON` auf eine gültige JSON-Zeichenfolge oder ein JSON-Array mit Runner-Labels:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
"ubuntu-latest"
|
|
132
|
+
["self-hosted", "linux", "x64", "visual-recap"]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Die JSON-Anführungszeichen sind erforderlich. Dieser Wert wählt den Runner für den vollständigen `recap`-Job. Übergeben Sie zur Konfiguration während der geführten Einrichtung denselben JSON-Wert an `--runs-on` und prüfen Sie anschließend den Workflow und die Verfügbarkeit des Runners mit `doctor`:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
npx @agent-native/core@latest recap setup --runs-on '["self-hosted","linux","x64","visual-recap"]'
|
|
139
|
+
npx @agent-native/core@latest recap doctor
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Das einfache Gate verwendet separat `ubuntu-latest`. Repositorys ohne von GitHub gehostete Runner können `VISUAL_RECAP_GATE_RUNS_ON` auf ein einzelnes Klartext-Label ohne JSON setzen oder `--gate-runs-on visual-recap-gate` verwenden. Das benutzerdefinierte Label gilt nur für `OWNER`-, `MEMBER`- oder `COLLABORATOR`-Autoren desselben Repositorys; Forks und andere Autoren werden auf `ubuntu-latest` gezwungen und können ohne GitHub-gehostete Runner ungeplant bleiben. Nutzen Sie einen dedizierten, möglichst kurzlebigen Runner: Das Standard-Gate checkt den PR-Baum nicht aus und wertet Workflow-Logik sowie PR-Metadaten aus.
|
|
143
|
+
|
|
144
|
+
`recap doctor` lehnt fehlerhaftes oder nicht unterstütztes JSON ab und meldet, wenn GitHub keinen Online-Runner bereitstellt, der alle konfigurierten Labels erfüllt. Registrierung, Installation, Upgrades, Kapazität und Wartung des Runners liegen weiterhin in Ihrer Verantwortung; Agent Native wählt die Labels aus, stellt oder betreibt den Runner jedoch nicht.
|
|
145
|
+
|
|
146
|
+
**Sicherheit:** Bevorzugen Sie kurzlebige selbst gehostete Runner. Persistente selbst gehostete Runner sollten nur privaten Repositorys mit vertrauenswürdigen Mitwirkenden dienen. Der Workflow bricht ab, bevor selbst gehostete Arbeit für nicht vertrauenswürdige Autoren öffentlicher oder Fork-PRs eingeplant wird, doch eine persistente Maschine behält zwischen Jobs weiterhin Arbeitsbereichs- und Prozesszustand. Schwächen Sie dieses Gate nicht ab und leiten Sie keine nicht vertrauenswürdigen Beiträge an einen persistenten Runner weiter.
|
|
147
|
+
|
|
126
148
|
## Backend-Auswahl
|
|
127
149
|
|
|
128
150
|
Wählen Sie mit der Repository-Variable `VISUAL_RECAP_AGENT` aus, welcher Codierungsagent den Skill ausführt:
|
|
@@ -460,10 +482,12 @@ jobs:
|
|
|
460
482
|
model: ${{ vars.VISUAL_RECAP_MODEL || '' }}
|
|
461
483
|
reasoning: ${{ vars.VISUAL_RECAP_REASONING || '' }}
|
|
462
484
|
skill-source: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || 'auto' }}
|
|
485
|
+
runs-on: ${{ vars.VISUAL_RECAP_RUNS_ON || '"ubuntu-latest"' }}
|
|
486
|
+
gate-runs-on: ${{ vars.VISUAL_RECAP_GATE_RUNS_ON || 'ubuntu-latest' }}
|
|
463
487
|
# cli-version: "latest" # pin to a specific @agent-native/core version
|
|
464
488
|
```
|
|
465
489
|
|
|
466
|
-
Es gelten
|
|
490
|
+
Es gelten dieselben Geheimnisse und Variablen wie unter [Secrets and variables](#secrets-and-variables). Der wiederverwendbare Aufrufer leitet `VISUAL_RECAP_RUNS_ON` als `runs-on` für den vollständigen Job und `VISUAL_RECAP_GATE_RUNS_ON` als einfaches `gate-runs-on`-Label für das Gate weiter. Ohne Eingabe verwenden beide `ubuntu-latest`.
|
|
467
491
|
|
|
468
492
|
### Installation über CLI
|
|
469
493
|
|