@evomap/evolver-core 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/algo/antiDistill.d.ts +35 -0
- package/dist/algo/antiDistill.js +167 -0
- package/dist/algo/bans.d.ts +6 -0
- package/dist/algo/bans.js +33 -0
- package/dist/algo/candidateAssembly.d.ts +65 -0
- package/dist/algo/candidateAssembly.js +196 -0
- package/dist/algo/capabilityCandidates.d.ts +38 -0
- package/dist/algo/capabilityCandidates.js +131 -0
- package/dist/algo/confidence.d.ts +106 -0
- package/dist/algo/confidence.js +196 -0
- package/dist/algo/cycleEngine.d.ts +143 -0
- package/dist/algo/cycleEngine.js +417 -0
- package/dist/algo/cycleFailureClassifier.d.ts +52 -0
- package/dist/algo/cycleFailureClassifier.js +104 -0
- package/dist/algo/epigenetics.d.ts +14 -0
- package/dist/algo/epigenetics.js +41 -0
- package/dist/algo/evolutionEvent.d.ts +23 -0
- package/dist/algo/evolutionEvent.js +24 -0
- package/dist/algo/exploration.d.ts +34 -0
- package/dist/algo/exploration.js +55 -0
- package/dist/algo/geneHealth.d.ts +24 -0
- package/dist/algo/geneHealth.js +16 -0
- package/dist/algo/geneIntake.d.ts +37 -0
- package/dist/algo/geneIntake.js +100 -0
- package/dist/algo/genePromotion.d.ts +48 -0
- package/dist/algo/genePromotion.js +53 -0
- package/dist/algo/geneSelection.d.ts +128 -0
- package/dist/algo/geneSelection.js +222 -0
- package/dist/algo/index.d.ts +18 -0
- package/dist/algo/index.js +18 -0
- package/dist/algo/mutation.d.ts +12 -0
- package/dist/algo/mutation.js +22 -0
- package/dist/algo/orchestrator.d.ts +65 -0
- package/dist/algo/orchestrator.js +63 -0
- package/dist/algo/solidify.d.ts +43 -0
- package/dist/algo/solidify.js +63 -0
- package/dist/algo/strategyPresets.d.ts +32 -0
- package/dist/algo/strategyPresets.js +61 -0
- package/dist/assetstore/index.d.ts +8 -0
- package/dist/assetstore/index.js +8 -0
- package/dist/assetstore/learningHistory.d.ts +25 -0
- package/dist/assetstore/learningHistory.js +38 -0
- package/dist/assetstore/localJsonl.d.ts +34 -0
- package/dist/assetstore/localJsonl.js +182 -0
- package/dist/assetstore/pendingSignals.d.ts +22 -0
- package/dist/assetstore/pendingSignals.js +171 -0
- package/dist/assetstore/provenance.d.ts +39 -0
- package/dist/assetstore/provenance.js +109 -0
- package/dist/assetstore/provider.d.ts +48 -0
- package/dist/assetstore/provider.js +36 -0
- package/dist/assetstore/remoteStub.d.ts +32 -0
- package/dist/assetstore/remoteStub.js +36 -0
- package/dist/assetstore/reviewFilter.d.ts +20 -0
- package/dist/assetstore/reviewFilter.js +44 -0
- package/dist/assetstore/reviewLedger.d.ts +55 -0
- package/dist/assetstore/reviewLedger.js +121 -0
- package/dist/benchmark/antiGeneBenchmark.d.ts +79 -0
- package/dist/benchmark/antiGeneBenchmark.js +241 -0
- package/dist/benchmark/antiGeneRollout.d.ts +80 -0
- package/dist/benchmark/antiGeneRollout.js +256 -0
- package/dist/benchmark/benchmark.d.ts +32 -0
- package/dist/benchmark/benchmark.js +26 -0
- package/dist/benchmark/evolutionThesisSolver.d.ts +25 -0
- package/dist/benchmark/evolutionThesisSolver.js +41 -0
- package/dist/benchmark/index.d.ts +5 -0
- package/dist/benchmark/index.js +5 -0
- package/dist/benchmark/thesis.d.ts +85 -0
- package/dist/benchmark/thesis.js +150 -0
- package/dist/bootstrap/envFingerprint.d.ts +45 -0
- package/dist/bootstrap/envFingerprint.js +72 -0
- package/dist/bootstrap/index.d.ts +2 -0
- package/dist/bootstrap/index.js +2 -0
- package/dist/bootstrap/selfEvolve.d.ts +36 -0
- package/dist/bootstrap/selfEvolve.js +26 -0
- package/dist/cycle/cycleTimeline.d.ts +35 -0
- package/dist/cycle/cycleTimeline.js +74 -0
- package/dist/cycle/index.d.ts +2 -0
- package/dist/cycle/index.js +2 -0
- package/dist/cycle/stateMachine.d.ts +6 -0
- package/dist/cycle/stateMachine.js +25 -0
- package/dist/daemon/cycleContext.d.ts +12 -0
- package/dist/daemon/cycleContext.js +13 -0
- package/dist/daemon/drain.d.ts +11 -0
- package/dist/daemon/drain.js +16 -0
- package/dist/daemon/guards.d.ts +87 -0
- package/dist/daemon/guards.js +142 -0
- package/dist/daemon/idempotency.d.ts +11 -0
- package/dist/daemon/idempotency.js +36 -0
- package/dist/daemon/idleScheduler.d.ts +55 -0
- package/dist/daemon/idleScheduler.js +181 -0
- package/dist/daemon/index.d.ts +8 -0
- package/dist/daemon/index.js +8 -0
- package/dist/daemon/stepRunner.d.ts +12 -0
- package/dist/daemon/stepRunner.js +31 -0
- package/dist/daemon/unhandledRejectionWindow.d.ts +21 -0
- package/dist/daemon/unhandledRejectionWindow.js +52 -0
- package/dist/daemon/watchdog.d.ts +11 -0
- package/dist/daemon/watchdog.js +14 -0
- package/dist/events/eventSchema.d.ts +132 -0
- package/dist/events/eventSchema.js +30 -0
- package/dist/events/eventStore.d.ts +32 -0
- package/dist/events/eventStore.js +137 -0
- package/dist/events/ingest.d.ts +34 -0
- package/dist/events/ingest.js +61 -0
- package/dist/events/paths.d.ts +22 -0
- package/dist/events/paths.js +44 -0
- package/dist/events/projectors.d.ts +9 -0
- package/dist/events/projectors.js +11 -0
- package/dist/events/public.d.ts +14 -0
- package/dist/events/public.js +8 -0
- package/dist/events/replayer.d.ts +26 -0
- package/dist/events/replayer.js +67 -0
- package/dist/events/reports.d.ts +90 -0
- package/dist/events/reports.js +244 -0
- package/dist/events/retention.d.ts +70 -0
- package/dist/events/retention.js +177 -0
- package/dist/events/sink.d.ts +5 -0
- package/dist/events/sink.js +1 -0
- package/dist/exec/autoExec.d.ts +137 -0
- package/dist/exec/autoExec.js +221 -0
- package/dist/exec/autonomousCycle.d.ts +48 -0
- package/dist/exec/autonomousCycle.js +78 -0
- package/dist/exec/claudeBridge.d.ts +112 -0
- package/dist/exec/claudeBridge.js +219 -0
- package/dist/exec/index.d.ts +9 -0
- package/dist/exec/index.js +11 -0
- package/dist/exec/openPrRegistry.d.ts +60 -0
- package/dist/exec/openPrRegistry.js +130 -0
- package/dist/exec/policy/blastRadius.d.ts +31 -0
- package/dist/exec/policy/blastRadius.js +67 -0
- package/dist/exec/policy/constraints.d.ts +26 -0
- package/dist/exec/policy/constraints.js +62 -0
- package/dist/exec/policy/destructive.d.ts +45 -0
- package/dist/exec/policy/destructive.js +108 -0
- package/dist/exec/policy/failureMode.d.ts +33 -0
- package/dist/exec/policy/failureMode.js +49 -0
- package/dist/exec/policy/index.d.ts +24 -0
- package/dist/exec/policy/index.js +30 -0
- package/dist/exec/policy/protectedPaths.d.ts +17 -0
- package/dist/exec/policy/protectedPaths.js +65 -0
- package/dist/exec/policyCheck.d.ts +2 -0
- package/dist/exec/policyCheck.js +7 -0
- package/dist/exec/prompt.d.ts +34 -0
- package/dist/exec/prompt.js +108 -0
- package/dist/exec/proofOfWork.d.ts +9 -0
- package/dist/exec/proofOfWork.js +11 -0
- package/dist/exec/runnerRegistry.d.ts +123 -0
- package/dist/exec/runnerRegistry.js +237 -0
- package/dist/exec/selfPr.d.ts +83 -0
- package/dist/exec/selfPr.js +104 -0
- package/dist/exec/selfPrObfuscation.d.ts +21 -0
- package/dist/exec/selfPrObfuscation.js +85 -0
- package/dist/hooks/hooks.d.ts +117 -0
- package/dist/hooks/hooks.js +89 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hub/assetCallLog.d.ts +43 -0
- package/dist/hub/assetCallLog.js +72 -0
- package/dist/hub/bindings.d.ts +28 -0
- package/dist/hub/bindings.js +90 -0
- package/dist/hub/capability.d.ts +278 -0
- package/dist/hub/capability.js +1 -0
- package/dist/hub/conversationDistiller.d.ts +88 -0
- package/dist/hub/conversationDistiller.js +264 -0
- package/dist/hub/fake.d.ts +45 -0
- package/dist/hub/fake.js +69 -0
- package/dist/hub/hubReview.d.ts +91 -0
- package/dist/hub/hubReview.js +106 -0
- package/dist/hub/index.d.ts +10 -0
- package/dist/hub/index.js +10 -0
- package/dist/hub/ingest.d.ts +15 -0
- package/dist/hub/ingest.js +15 -0
- package/dist/hub/questionGenerator.d.ts +59 -0
- package/dist/hub/questionGenerator.js +406 -0
- package/dist/hub/reuseDecision.d.ts +87 -0
- package/dist/hub/reuseDecision.js +127 -0
- package/dist/hub/sanitize.d.ts +52 -0
- package/dist/hub/sanitize.js +321 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +27 -0
- package/dist/mailbox/catalog.d.ts +17 -0
- package/dist/mailbox/catalog.js +53 -0
- package/dist/mailbox/daemon.d.ts +48 -0
- package/dist/mailbox/daemon.js +61 -0
- package/dist/mailbox/dispatch.d.ts +46 -0
- package/dist/mailbox/dispatch.js +62 -0
- package/dist/mailbox/envelope.d.ts +43 -0
- package/dist/mailbox/envelope.js +52 -0
- package/dist/mailbox/index.d.ts +8 -0
- package/dist/mailbox/index.js +8 -0
- package/dist/mailbox/ipcServer.d.ts +46 -0
- package/dist/mailbox/ipcServer.js +168 -0
- package/dist/mailbox/requestReply.d.ts +40 -0
- package/dist/mailbox/requestReply.js +77 -0
- package/dist/mailbox/store.d.ts +74 -0
- package/dist/mailbox/store.js +308 -0
- package/dist/mailbox/wake.d.ts +45 -0
- package/dist/mailbox/wake.js +60 -0
- package/dist/material/boundary.d.ts +7 -0
- package/dist/material/boundary.js +14 -0
- package/dist/material/consumer.d.ts +21 -0
- package/dist/material/consumer.js +52 -0
- package/dist/material/emit.d.ts +55 -0
- package/dist/material/emit.js +52 -0
- package/dist/material/factory.d.ts +27 -0
- package/dist/material/factory.js +25 -0
- package/dist/material/index.d.ts +8 -0
- package/dist/material/index.js +8 -0
- package/dist/material/materialStore.d.ts +24 -0
- package/dist/material/materialStore.js +76 -0
- package/dist/material/sampling.d.ts +21 -0
- package/dist/material/sampling.js +39 -0
- package/dist/material/sources.d.ts +25 -0
- package/dist/material/sources.js +33 -0
- package/dist/material/watermark.d.ts +21 -0
- package/dist/material/watermark.js +76 -0
- package/dist/observers/cursorRewriteObserver.d.ts +46 -0
- package/dist/observers/cursorRewriteObserver.js +103 -0
- package/dist/observers/distillObserver.d.ts +31 -0
- package/dist/observers/distillObserver.js +93 -0
- package/dist/observers/index.d.ts +5 -0
- package/dist/observers/index.js +5 -0
- package/dist/observers/observerBus.d.ts +44 -0
- package/dist/observers/observerBus.js +73 -0
- package/dist/observers/reflectionObserver.d.ts +31 -0
- package/dist/observers/reflectionObserver.js +124 -0
- package/dist/observers/valueDigestObserver.d.ts +50 -0
- package/dist/observers/valueDigestObserver.js +70 -0
- package/dist/ops/cleanup.d.ts +23 -0
- package/dist/ops/cleanup.js +68 -0
- package/dist/ops/health.d.ts +37 -0
- package/dist/ops/health.js +96 -0
- package/dist/ops/index.d.ts +7 -0
- package/dist/ops/index.js +7 -0
- package/dist/ops/recall.d.ts +65 -0
- package/dist/ops/recall.js +152 -0
- package/dist/ops/reuseOutcomes.d.ts +68 -0
- package/dist/ops/reuseOutcomes.js +126 -0
- package/dist/ops/savingsCore.d.ts +47 -0
- package/dist/ops/savingsCore.js +112 -0
- package/dist/ops/selfUpdate.d.ts +106 -0
- package/dist/ops/selfUpdate.js +294 -0
- package/dist/ops/valueLedger.d.ts +205 -0
- package/dist/ops/valueLedger.js +238 -0
- package/dist/ops/valueOutreach.d.ts +70 -0
- package/dist/ops/valueOutreach.js +244 -0
- package/dist/personality/drift.d.ts +45 -0
- package/dist/personality/drift.js +106 -0
- package/dist/personality/events.d.ts +25 -0
- package/dist/personality/events.js +37 -0
- package/dist/personality/evolveOps.d.ts +20 -0
- package/dist/personality/evolveOps.js +93 -0
- package/dist/personality/index.d.ts +11 -0
- package/dist/personality/index.js +11 -0
- package/dist/personality/mutate.d.ts +21 -0
- package/dist/personality/mutate.js +39 -0
- package/dist/personality/pivot.d.ts +23 -0
- package/dist/personality/pivot.js +22 -0
- package/dist/personality/prompt.d.ts +6 -0
- package/dist/personality/prompt.js +62 -0
- package/dist/personality/riskGate.d.ts +42 -0
- package/dist/personality/riskGate.js +80 -0
- package/dist/personality/schema.d.ts +255 -0
- package/dist/personality/schema.js +119 -0
- package/dist/personality/select.d.ts +46 -0
- package/dist/personality/select.js +71 -0
- package/dist/personality/stats.d.ts +46 -0
- package/dist/personality/stats.js +82 -0
- package/dist/personality/store.d.ts +35 -0
- package/dist/personality/store.js +92 -0
- package/dist/schema/common.d.ts +28 -0
- package/dist/schema/common.js +17 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/material.d.ts +201 -0
- package/dist/schema/material.js +50 -0
- package/dist/schema/problem.d.ts +160 -0
- package/dist/schema/problem.js +45 -0
- package/dist/schema/proofOfWork.d.ts +97 -0
- package/dist/schema/proofOfWork.js +9 -0
- package/dist/schema/signal.d.ts +41 -0
- package/dist/schema/signal.js +19 -0
- package/dist/shadow/index.d.ts +6 -0
- package/dist/shadow/index.js +6 -0
- package/dist/shadow/jsonlSink.d.ts +17 -0
- package/dist/shadow/jsonlSink.js +27 -0
- package/dist/shadow/redact.d.ts +11 -0
- package/dist/shadow/redact.js +18 -0
- package/dist/shadow/shadowHub.d.ts +12 -0
- package/dist/shadow/shadowHub.js +42 -0
- package/dist/shadow/shadowMailbox.d.ts +17 -0
- package/dist/shadow/shadowMailbox.js +25 -0
- package/dist/shadow/shadowStore.d.ts +18 -0
- package/dist/shadow/shadowStore.js +55 -0
- package/dist/shadow/sink.d.ts +37 -0
- package/dist/shadow/sink.js +18 -0
- package/dist/signals/cycleHistoryFromEvents.d.ts +11 -0
- package/dist/signals/cycleHistoryFromEvents.js +96 -0
- package/dist/signals/expand.d.ts +34 -0
- package/dist/signals/expand.js +125 -0
- package/dist/signals/extractor.d.ts +25 -0
- package/dist/signals/extractor.js +57 -0
- package/dist/signals/index.d.ts +6 -0
- package/dist/signals/index.js +6 -0
- package/dist/signals/metaSignals.d.ts +57 -0
- package/dist/signals/metaSignals.js +158 -0
- package/dist/signals/signalGate.d.ts +15 -0
- package/dist/signals/signalGate.js +40 -0
- package/dist/signals/traceSignals.d.ts +44 -0
- package/dist/signals/traceSignals.js +123 -0
- package/dist/signatures/classifier.d.ts +16 -0
- package/dist/signatures/classifier.js +29 -0
- package/dist/signatures/index.d.ts +2 -0
- package/dist/signatures/index.js +2 -0
- package/dist/signatures/signatures.d.ts +22 -0
- package/dist/signatures/signatures.js +42 -0
- package/dist/strategy/experiment.d.ts +48 -0
- package/dist/strategy/experiment.js +63 -0
- package/dist/strategy/index.d.ts +2 -0
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/strategyPoint.d.ts +30 -0
- package/dist/strategy/strategyPoint.js +23 -0
- package/dist/trace/index.d.ts +2 -0
- package/dist/trace/index.js +2 -0
- package/dist/trace/trajectory.d.ts +82 -0
- package/dist/trace/trajectory.js +117 -0
- package/dist/trace/trajectoryExport.d.ts +237 -0
- package/dist/trace/trajectoryExport.js +1818 -0
- package/dist/trigger/budget.d.ts +16 -0
- package/dist/trigger/budget.js +20 -0
- package/dist/trigger/engine.d.ts +12 -0
- package/dist/trigger/engine.js +23 -0
- package/dist/trigger/index.d.ts +6 -0
- package/dist/trigger/index.js +6 -0
- package/dist/trigger/problemBuilder.d.ts +24 -0
- package/dist/trigger/problemBuilder.js +32 -0
- package/dist/trigger/trigger.d.ts +22 -0
- package/dist/trigger/trigger.js +27 -0
- package/dist/trigger/valueModel.d.ts +26 -0
- package/dist/trigger/valueModel.js +25 -0
- package/dist/trigger/wfq.d.ts +13 -0
- package/dist/trigger/wfq.js +25 -0
- package/dist/util/fileLock.d.ts +24 -0
- package/dist/util/fileLock.js +227 -0
- package/dist/util/index.d.ts +2 -0
- package/dist/util/index.js +2 -0
- package/dist/util/version.d.ts +12 -0
- package/dist/util/version.js +51 -0
- package/dist/verify/index.d.ts +4 -0
- package/dist/verify/index.js +4 -0
- package/dist/verify/rollback.d.ts +22 -0
- package/dist/verify/rollback.js +33 -0
- package/dist/verify/sandboxRunner.d.ts +39 -0
- package/dist/verify/sandboxRunner.js +116 -0
- package/dist/verify/sandboxedValidation.d.ts +35 -0
- package/dist/verify/sandboxedValidation.js +56 -0
- package/dist/verify/validation.d.ts +41 -0
- package/dist/verify/validation.js +85 -0
- package/dist/wire/canonicalize.golden.d.ts +23 -0
- package/dist/wire/canonicalize.golden.js +46 -0
- package/dist/wire/geneHints.d.ts +64 -0
- package/dist/wire/geneHints.js +100 -0
- package/dist/wire/index.d.ts +91 -0
- package/dist/wire/index.js +3 -0
- package/dist/wire/schemaGate.d.ts +11 -0
- package/dist/wire/schemaGate.js +49 -0
- package/dist/workflow/dsl.d.ts +54 -0
- package/dist/workflow/dsl.js +15 -0
- package/dist/workflow/engine.d.ts +30 -0
- package/dist/workflow/engine.js +94 -0
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.js +2 -0
- package/package.json +29 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
// Pre-publish sanitize (ported from v1 src/gep/sanitize.js): before any asset leaves for the hub, deep-redact
|
|
2
|
+
// strings (30+ secret/path/email patterns) and scan for leaks (25 scanners + reverse env-value detection).
|
|
3
|
+
// Pure functions, never throw — the block decision is returned to the chokepoint (bindings), which raises a
|
|
4
|
+
// terminal PublishRejectedError. Command point: when redaction changes content the asset_id MUST be recomputed
|
|
5
|
+
// (computeAssetId excludes asset_id by default), else the published body hash won't match its id and the hub
|
|
6
|
+
// rejects it. See feedback_public_repo_no_internal_leak.
|
|
7
|
+
import { computeAssetId } from '../wire/index.js';
|
|
8
|
+
export const REDACTED = '[REDACTED]';
|
|
9
|
+
/** Redaction patterns (ported verbatim from v1, 30 entries). A match is replaced with [REDACTED]. */
|
|
10
|
+
const REDACT_PATTERNS = [
|
|
11
|
+
// API keys & tokens (generic)
|
|
12
|
+
/Bearer\s+[A-Za-z0-9-._~+/]+=*/g,
|
|
13
|
+
/"?node_secret"?\s*[:=]\s*["']?[A-Za-z0-9-._~+/]{16,}["']?/gi,
|
|
14
|
+
/sk-[A-Za-z0-9]{20,}/g,
|
|
15
|
+
/"?token"?[=:]\s*["']?[A-Za-z0-9-._~+/]{16,}["']?/gi,
|
|
16
|
+
/api[_-]?key[=:]\s*["']?[A-Za-z0-9-._~+/]{16,}["']?/gi,
|
|
17
|
+
/secret[=:]\s*["']?[A-Za-z0-9-._~+/]{16,}["']?/gi,
|
|
18
|
+
/password[=:]\s*["']?[^\s"',;)}\]]{6,}["']?/gi,
|
|
19
|
+
// GitHub tokens (ghp_, gho_, ghu_, ghs_, github_pat_)
|
|
20
|
+
/ghp_[A-Za-z0-9]{36,}/g,
|
|
21
|
+
/gho_[A-Za-z0-9]{36,}/g,
|
|
22
|
+
/ghu_[A-Za-z0-9]{36,}/g,
|
|
23
|
+
/ghs_[A-Za-z0-9]{36,}/g,
|
|
24
|
+
/github_pat_[A-Za-z0-9_]{22,}/g,
|
|
25
|
+
// AWS access keys
|
|
26
|
+
/AKIA[0-9A-Z]{16}/g,
|
|
27
|
+
// OpenAI / Anthropic tokens
|
|
28
|
+
/sk-proj-[A-Za-z0-9-_]{20,}/g,
|
|
29
|
+
/sk-ant-[A-Za-z0-9-_]{20,}/g,
|
|
30
|
+
// npm tokens
|
|
31
|
+
/npm_[A-Za-z0-9]{36,}/g,
|
|
32
|
+
// Slack tokens (bot/user/app/refresh/verification)
|
|
33
|
+
/xox[baprsv]-[A-Za-z0-9-]{10,}/g,
|
|
34
|
+
// JSON Web Tokens (header.payload.signature)
|
|
35
|
+
/eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{20,}/g,
|
|
36
|
+
// Azure storage connection strings (redact the key field only)
|
|
37
|
+
/AccountKey=[^;\s]+/gi,
|
|
38
|
+
// Azure AD client secret + App Insights instrumentation key (value only)
|
|
39
|
+
/client_secret=[A-Za-z0-9~._-]{8,}/gi,
|
|
40
|
+
/instrumentationkey=[0-9a-fA-F-]{20,}/gi,
|
|
41
|
+
// Discord bot tokens: three base64url segments (uppercase leading char avoids matching dotted lowercase identifiers).
|
|
42
|
+
/\b[MNO][A-Za-z0-9_-]{23,}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,}\b/g,
|
|
43
|
+
// Private keys
|
|
44
|
+
/-----BEGIN\s+(?:RSA\s+|EC\s+|DSA\s+|OPENSSH\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(?:RSA\s+|EC\s+|DSA\s+|OPENSSH\s+)?PRIVATE\s+KEY-----/g,
|
|
45
|
+
// Basic auth in URLs (redact only credentials, keep :// and @)
|
|
46
|
+
/(?<=:\/\/)[^@\s]+:[^@\s]+(?=@)/g,
|
|
47
|
+
// Email addresses
|
|
48
|
+
/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
|
|
49
|
+
// .env file references — only when the dot-env token looks like a real path (preceded by a path separator) or
|
|
50
|
+
// carries a suffix like `.env.production`. Bare prose mentions such as "Read from `.env` file" are intentionally
|
|
51
|
+
// NOT matched: the filename itself is a convention, not a secret, and over-redacting it strips useful debugging
|
|
52
|
+
// context from capsules without protecting anything the patterns above don't already cover (keys/tokens inside
|
|
53
|
+
// the env file). Ported from v1 src/gep/sanitize.js (PR #151).
|
|
54
|
+
/\.env\.[a-zA-Z]+\b/g,
|
|
55
|
+
/(?<=[\\/])\.env\b/g,
|
|
56
|
+
];
|
|
57
|
+
// Post-filter allowlist (ported from v1 src/gep/sanitize.js, PR #151): strings the patterns above — and the path
|
|
58
|
+
// anonymizer below — WILL catch but that are not actually sensitive. If any entry matches a captured string it is
|
|
59
|
+
// kept verbatim instead of being redacted / anonymized / flagged as a leak. Keeping this as a post-filter rather
|
|
60
|
+
// than bolting more lookaheads into every pattern keeps the patterns readable and the carve-outs easy to audit.
|
|
61
|
+
const REDACT_ALLOWLIST = [
|
|
62
|
+
// --- CI runner paths --- (well-known build infrastructure, no user PII)
|
|
63
|
+
/^\/home\/runner(?:[/]|$)/, // GitHub Actions Linux
|
|
64
|
+
/^\/Users\/runner(?:[/]|$)/, // GitHub Actions macOS
|
|
65
|
+
/^\/home\/circleci(?:[/]|$)/, // CircleCI Linux
|
|
66
|
+
/^\/Users\/distiller(?:[/]|$)/, // CircleCI macOS
|
|
67
|
+
/^\/home\/vsts(?:[/]|$)/, // Azure Pipelines
|
|
68
|
+
/^\/home\/travis(?:[/]|$)/, // Travis CI
|
|
69
|
+
/^\/home\/jenkins(?:[/]|$)/, // Jenkins default
|
|
70
|
+
// --- Bot / no-reply / SSH-alias addresses --- (not personal mailboxes)
|
|
71
|
+
// The domain MUST be anchored to a well-known public code host. An open noreply@<anything> allowlist would leak
|
|
72
|
+
// internal corp infra domains like noreply@internal-codename.corp (Bugbot PR #151 Low).
|
|
73
|
+
/^(?:noreply|no-reply|donotreply|do-not-reply)@(?:github\.com|users\.noreply\.github\.com|gitlab\.com|bitbucket\.org|npmjs\.com|claude\.ai|anthropic\.com)$/i,
|
|
74
|
+
/^[0-9]+\+[a-zA-Z0-9._-]+@users\.noreply\.github\.com$/i, // GitHub commit-author noreply (full digits+user form)
|
|
75
|
+
// The ssh_target scanner's local part is [a-zA-Z0-9_.-]{1,64} (no `+`), so `8275028+user@users.noreply.github.com`
|
|
76
|
+
// is captured as just `user@users.noreply.github.com` — the full-form anchor above can't match the truncated
|
|
77
|
+
// value. Allow any local part on this domain since the domain itself is by design non-personal (Bugbot PR #151
|
|
78
|
+
// round 2 Medium).
|
|
79
|
+
/^[a-zA-Z0-9_.-]+@users\.noreply\.github\.com$/i,
|
|
80
|
+
/^git@github\.com$/i, // SSH alias, not a real mailbox
|
|
81
|
+
/^git@gitlab\.com$/i,
|
|
82
|
+
/^git@bitbucket\.org$/i,
|
|
83
|
+
];
|
|
84
|
+
function isAllowlisted(match) {
|
|
85
|
+
for (const re of REDACT_ALLOWLIST)
|
|
86
|
+
if (re.test(match))
|
|
87
|
+
return true;
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
// Anonymize (not redact) local filesystem paths (#12): a file path is usually the gene's CONTENT ("fix
|
|
91
|
+
// ~/proj/src/auth.ts"), not a secret — only the user/home prefix is PII. Strip the prefix to `~`, keeping the
|
|
92
|
+
// rest of the path so the shared experience stays useful, instead of [REDACTED]-ing the whole thing.
|
|
93
|
+
const ANONYMIZE_PATTERNS = [
|
|
94
|
+
[/\/(?:home|Users)\/[^/\s"',;)}\]]+/g, '~'], // /home/alice/proj → ~/proj
|
|
95
|
+
[/[A-Za-z]:\\Users\\[^\\/\s"',;)}\]]+/g, '~'], // C:\Users\alice\proj → ~\proj
|
|
96
|
+
];
|
|
97
|
+
/** Apply every redaction pattern (secrets → [REDACTED]) then anonymize local paths (~/...) to a single string. */
|
|
98
|
+
export function redactString(s) {
|
|
99
|
+
if (typeof s !== 'string' || !s)
|
|
100
|
+
return s;
|
|
101
|
+
let out = s;
|
|
102
|
+
for (const p of REDACT_PATTERNS) {
|
|
103
|
+
p.lastIndex = 0;
|
|
104
|
+
out = out.replace(p, (m) => (isAllowlisted(m) ? m : REDACTED));
|
|
105
|
+
}
|
|
106
|
+
for (const [p, rep] of ANONYMIZE_PATTERNS) {
|
|
107
|
+
p.lastIndex = 0;
|
|
108
|
+
out = out.replace(p, (m) => (isAllowlisted(m) ? m : rep));
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
/** Deep redaction: recursively redact string values in objects/arrays (keys untouched). Returns a copy; does not mutate the input. */
|
|
113
|
+
export function redactDeep(v) {
|
|
114
|
+
if (typeof v === 'string')
|
|
115
|
+
return redactString(v);
|
|
116
|
+
if (Array.isArray(v))
|
|
117
|
+
return v.map((x) => redactDeep(x));
|
|
118
|
+
if (v && typeof v === 'object') {
|
|
119
|
+
const out = {};
|
|
120
|
+
for (const [k, val] of Object.entries(v))
|
|
121
|
+
out[k] = redactDeep(val);
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
return v;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Redact a single asset and RECOMPUTE its asset_id (command point). When redaction changes content, the id must
|
|
128
|
+
* change with it, otherwise the published body and id disagree. computeAssetId excludes the asset_id field by
|
|
129
|
+
* default; on the rare null return we fall back to the original id.
|
|
130
|
+
*/
|
|
131
|
+
export function sanitizeAsset(asset) {
|
|
132
|
+
const redacted = redactDeep(asset);
|
|
133
|
+
const id = computeAssetId(redacted);
|
|
134
|
+
return { ...redacted, asset_id: id ?? asset.asset_id };
|
|
135
|
+
}
|
|
136
|
+
/** Leak scanners (ported verbatim from v1, 25 entries): each match yields an env-var replacement suggestion. */
|
|
137
|
+
const LEAK_SCANNERS = [
|
|
138
|
+
{ type: 'api_key', pattern: /sk-[A-Za-z0-9]{20,}/g, suggest: 'process.env.OPENAI_API_KEY' },
|
|
139
|
+
{ type: 'api_key', pattern: /sk-proj-[A-Za-z0-9-_]{20,}/g, suggest: 'process.env.OPENAI_API_KEY' },
|
|
140
|
+
{ type: 'api_key', pattern: /sk-ant-[A-Za-z0-9-_]{20,}/g, suggest: 'process.env.ANTHROPIC_API_KEY' },
|
|
141
|
+
{ type: 'api_key', pattern: /AKIA[0-9A-Z]{16}/g, suggest: 'process.env.AWS_ACCESS_KEY_ID' },
|
|
142
|
+
{ type: 'github_token', pattern: /ghp_[A-Za-z0-9]{36,}/g, suggest: 'process.env.GITHUB_TOKEN' },
|
|
143
|
+
{ type: 'github_token', pattern: /github_pat_[A-Za-z0-9_]{22,}/g, suggest: 'process.env.GITHUB_TOKEN' },
|
|
144
|
+
{ type: 'npm_token', pattern: /npm_[A-Za-z0-9]{36,}/g, suggest: 'process.env.NPM_TOKEN' },
|
|
145
|
+
{ type: 'slack_token', pattern: /xox[baprsv]-[A-Za-z0-9-]{10,}/g, suggest: 'process.env.SLACK_TOKEN' },
|
|
146
|
+
{ type: 'jwt', pattern: /eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{20,}/g, suggest: 'process.env.JWT' },
|
|
147
|
+
{ type: 'azure_key', pattern: /AccountKey=[^;\s]+/gi, suggest: 'process.env.AZURE_STORAGE_KEY' },
|
|
148
|
+
{ type: 'azure_client_secret', pattern: /client_secret=[A-Za-z0-9~._-]{8,}/gi, suggest: 'process.env.AZURE_CLIENT_SECRET' },
|
|
149
|
+
{ type: 'azure_instrumentation_key', pattern: /instrumentationkey=[0-9a-fA-F-]{20,}/gi, suggest: 'process.env.APPINSIGHTS_INSTRUMENTATIONKEY' },
|
|
150
|
+
{ type: 'discord_token', pattern: /\b[MNO][A-Za-z0-9_-]{23,}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,}\b/g, suggest: 'process.env.DISCORD_TOKEN' },
|
|
151
|
+
{ type: 'bearer_token', pattern: /Bearer\s+[A-Za-z0-9-._~+/]{20,}=*/g, suggest: 'process.env.AUTH_TOKEN' },
|
|
152
|
+
{ type: 'proxy_token', pattern: /"?token"?[=:]\s*["']?[A-Za-z0-9-._~+/]{16,}["']?/gi, suggest: 'proxy token (ephemeral, stored in settings.json)' },
|
|
153
|
+
{ type: 'private_key', pattern: /-----BEGIN\s+(?:RSA\s+|EC\s+|DSA\s+|OPENSSH\s+)?PRIVATE\s+KEY-----/g, suggest: 'process.env.PRIVATE_KEY_PATH' },
|
|
154
|
+
{ type: 'db_url', pattern: /(?:mongodb|postgres|postgresql|mysql|redis|amqp):\/\/[^\s"',;)}\]]{10,}/gi, suggest: 'process.env.DATABASE_URL' },
|
|
155
|
+
{ type: 'local_path', pattern: /\/home\/[a-zA-Z0-9_.-]+\//g, suggest: 'process.env.HOME' },
|
|
156
|
+
{ type: 'local_path', pattern: /\/Users\/[a-zA-Z0-9_.-]+\//g, suggest: 'process.env.HOME' },
|
|
157
|
+
{ type: 'local_path', pattern: /[A-Z]:\\Users\\[a-zA-Z0-9_.-]+\\/g, suggest: 'process.env.USERPROFILE' },
|
|
158
|
+
{ type: 'internal_ip', pattern: /\b(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})(?::\d{2,5})?\b/g, suggest: 'process.env.SERVICE_HOST' },
|
|
159
|
+
// Bounded quantifiers ({1,64}/{1,255}/{2,24}) instead of unbounded `+`: the unbounded user/host classes against
|
|
160
|
+
// a required `@`/`.` anchor backtrack O(n^2) on long untrusted hub content (100k took ~6s — a real ReDoS, #198).
|
|
161
|
+
// The bounds cover every realistic ssh target (usernames <=64, hosts <=255, TLDs <=24) and make the scan linear.
|
|
162
|
+
{ type: 'ssh_target', pattern: /[a-zA-Z0-9_.-]{1,64}@(?:(?:\d{1,3}\.){3}\d{1,3}|[a-zA-Z0-9.-]{1,255}\.[a-zA-Z]{2,24})/g, suggest: 'process.env.SSH_HOST' },
|
|
163
|
+
{ type: 'password', pattern: /password[=:]\s*["']?[^\s"',;)}\]]{6,}["']?/gi, suggest: 'process.env.PASSWORD' },
|
|
164
|
+
{ type: 'secret', pattern: /secret[=:]\s*["']?[A-Za-z0-9-._~+/]{16,}["']?/gi, suggest: 'process.env.SECRET' },
|
|
165
|
+
{ type: 'basic_auth', pattern: /:\/\/[^@\s:]+:[^@\s]+@/g, suggest: 'process.env.SERVICE_URL' },
|
|
166
|
+
];
|
|
167
|
+
/** Env keys skipped by the reverse-value scan (non-sensitive; ported verbatim from v1). */
|
|
168
|
+
const ENV_SCAN_SKIP_KEYS = new Set([
|
|
169
|
+
'PATH', 'HOME', 'SHELL', 'TERM', 'LANG', 'USER', 'LOGNAME',
|
|
170
|
+
'PWD', 'OLDPWD', 'SHLVL', 'HOSTNAME', 'DISPLAY', 'EDITOR',
|
|
171
|
+
'PAGER', 'LESS', 'LS_COLORS', 'COLORTERM', 'TERM_PROGRAM',
|
|
172
|
+
'XDG_SESSION_ID', 'XDG_RUNTIME_DIR', 'DBUS_SESSION_BUS_ADDRESS',
|
|
173
|
+
'SSH_AUTH_SOCK', 'SSH_AGENT_PID', '_',
|
|
174
|
+
]);
|
|
175
|
+
const ENV_VALUE_FILESYSTEM_PATH_RE = /^(\/|[A-Za-z]:\\)/;
|
|
176
|
+
const ENV_VALUE_URL_RE = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
177
|
+
const SENSITIVE_ENV_KEY_PARTS = new Set([
|
|
178
|
+
'WEBHOOK', 'TOKEN', 'SECRET', 'PASSWORD', 'PASS', 'PASSWD', 'PASSPHRASE',
|
|
179
|
+
'KEY', 'CREDENTIAL', 'CREDENTIALS', 'SIGNATURE', 'SIGNED', 'DSN', 'BEARER',
|
|
180
|
+
'COOKIE', 'SESSION', 'CERT', 'CERTIFICATE',
|
|
181
|
+
]);
|
|
182
|
+
const SENSITIVE_ENV_KEY_RE = /WEBHOOK|TOKEN|SECRET|PASSWORD|CREDENTIAL|SIGNATURE|SIGNED|DSN|BEARER|COOKIE|SESSION|APIKEY|ACCESSKEY|PRIVATEKEY|CERTIFICATE/;
|
|
183
|
+
const HIGH_RISK_URL_QUERY_KEYS = new Set([
|
|
184
|
+
'token', 'access_token', 'auth', 'authorization', 'api_key', 'apikey', 'key',
|
|
185
|
+
'secret', 'signature', 'sig', 'signed', 'x-amz-signature', 'x-amz-credential',
|
|
186
|
+
'x-amz-security-token', 'x-goog-signature', 'x-goog-credential',
|
|
187
|
+
'sharedaccesssignature',
|
|
188
|
+
]);
|
|
189
|
+
function normalizeEnvKey(key) {
|
|
190
|
+
const normalized = key.toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '');
|
|
191
|
+
return normalized || key.toUpperCase();
|
|
192
|
+
}
|
|
193
|
+
function isFilesystemPathEnvValue(value) {
|
|
194
|
+
return ENV_VALUE_FILESYSTEM_PATH_RE.test(value);
|
|
195
|
+
}
|
|
196
|
+
function isUrlEnvValue(value) {
|
|
197
|
+
return ENV_VALUE_URL_RE.test(value);
|
|
198
|
+
}
|
|
199
|
+
function isSensitiveEnvKey(key) {
|
|
200
|
+
const normalized = normalizeEnvKey(key);
|
|
201
|
+
const parts = normalized.split(/[^A-Z0-9]+/).filter(Boolean);
|
|
202
|
+
if (parts.some((part) => SENSITIVE_ENV_KEY_PARTS.has(part)))
|
|
203
|
+
return true;
|
|
204
|
+
return SENSITIVE_ENV_KEY_RE.test(normalized);
|
|
205
|
+
}
|
|
206
|
+
function isHighRiskUrlEnvValue(value) {
|
|
207
|
+
if (!isUrlEnvValue(value))
|
|
208
|
+
return false;
|
|
209
|
+
let parsed;
|
|
210
|
+
try {
|
|
211
|
+
parsed = new URL(value);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
if (parsed.username || parsed.password)
|
|
217
|
+
return true;
|
|
218
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
219
|
+
const pathname = parsed.pathname.toLowerCase();
|
|
220
|
+
if (/(^|\.)hooks?\./.test(hostname) || /(^|\.)webhooks?\./.test(hostname))
|
|
221
|
+
return true;
|
|
222
|
+
if (/\/(?:api\/)?webhooks?\//.test(pathname) || /\/hooks?\//.test(pathname))
|
|
223
|
+
return true;
|
|
224
|
+
if (/\/(?:tokens?|secrets?|signed|signatures?|credentials?)\//.test(pathname))
|
|
225
|
+
return true;
|
|
226
|
+
for (const queryKey of parsed.searchParams.keys()) {
|
|
227
|
+
if (HIGH_RISK_URL_QUERY_KEYS.has(queryKey.toLowerCase()))
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
function shouldSkipEnvValueReverseScan(key, value) {
|
|
233
|
+
if (isSensitiveEnvKey(key))
|
|
234
|
+
return false;
|
|
235
|
+
if (isFilesystemPathEnvValue(value))
|
|
236
|
+
return true;
|
|
237
|
+
if (isUrlEnvValue(value) && !isHighRiskUrlEnvValue(value))
|
|
238
|
+
return true;
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
const clip = (s) => (s.length > 60 ? s.slice(0, 57) + '...' : s);
|
|
242
|
+
/** Pattern-scan content for sensitive info. Does not mutate content; returns a structured result. */
|
|
243
|
+
export function scanForLeaks(content) {
|
|
244
|
+
if (typeof content !== 'string' || !content)
|
|
245
|
+
return { found: false, leaks: [] };
|
|
246
|
+
const leaks = [];
|
|
247
|
+
const seen = new Set();
|
|
248
|
+
for (const scanner of LEAK_SCANNERS) {
|
|
249
|
+
scanner.pattern.lastIndex = 0;
|
|
250
|
+
let m;
|
|
251
|
+
while ((m = scanner.pattern.exec(content)) !== null) {
|
|
252
|
+
const val = m[0];
|
|
253
|
+
// Apply the same allowlist redactString uses: CI runner roots and bot/no-reply/SSH-alias addresses are not
|
|
254
|
+
// leaks. Without this, strict-mode sanitizeBundle would block a publish over a `/home/runner/` path or
|
|
255
|
+
// `noreply@github.com` (an ssh_target) — exactly the false positives the allowlist exists to fix, and a
|
|
256
|
+
// contradiction with redactString, which keeps them verbatim (Bugbot PR #151 Medium).
|
|
257
|
+
if (isAllowlisted(val))
|
|
258
|
+
continue;
|
|
259
|
+
const key = scanner.type + ':' + val;
|
|
260
|
+
if (seen.has(key))
|
|
261
|
+
continue;
|
|
262
|
+
seen.add(key);
|
|
263
|
+
leaks.push({ type: scanner.type, value: clip(val), suggestion: scanner.suggest });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return { found: leaks.length > 0, leaks };
|
|
267
|
+
}
|
|
268
|
+
/** Reverse detection: if any process.env value (>=8 chars) appears verbatim in content, an env value was hardcoded and should be replaced with the env reference. */
|
|
269
|
+
export function detectEnvValueLeaks(content, env) {
|
|
270
|
+
if (typeof content !== 'string' || !content)
|
|
271
|
+
return [];
|
|
272
|
+
const leaks = [];
|
|
273
|
+
for (const [key, val] of Object.entries(env)) {
|
|
274
|
+
if (!val || val.length < 8)
|
|
275
|
+
continue;
|
|
276
|
+
if (ENV_SCAN_SKIP_KEYS.has(normalizeEnvKey(key)))
|
|
277
|
+
continue;
|
|
278
|
+
// Env paths and ordinary URLs are often reproducible runtime metadata; sensitive keys and high-risk URLs still scan.
|
|
279
|
+
if (shouldSkipEnvValueReverseScan(key, val))
|
|
280
|
+
continue;
|
|
281
|
+
if (content.includes(val))
|
|
282
|
+
leaks.push({ type: 'env_value_leak', value: REDACTED, suggestion: 'process.env.' + key });
|
|
283
|
+
}
|
|
284
|
+
return leaks;
|
|
285
|
+
}
|
|
286
|
+
/** Full leak check: pattern scan + reverse env-value detection. */
|
|
287
|
+
export function fullLeakCheck(content, env) {
|
|
288
|
+
const scan = scanForLeaks(content);
|
|
289
|
+
const envLeaks = detectEnvValueLeaks(content, env);
|
|
290
|
+
const all = scan.leaks.concat(envLeaks);
|
|
291
|
+
return { found: all.length > 0, leaks: all };
|
|
292
|
+
}
|
|
293
|
+
/** Leak types that are PII (anonymized, not credentials) and so must NOT hard-block a strict publish (#12). */
|
|
294
|
+
const PII_ONLY_LEAK_TYPES = new Set(['local_path']);
|
|
295
|
+
/** Read the leak-check mode from env (EVOLVER_LEAK_CHECK, default strict, matching v1). */
|
|
296
|
+
export function leakCheckModeFromEnv(env) {
|
|
297
|
+
const v = (env['EVOLVER_LEAK_CHECK'] ?? '').toLowerCase();
|
|
298
|
+
return v === 'warn' || v === 'off' ? v : 'strict';
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Pre-publish sanitize of a bundle (pure, never throws):
|
|
302
|
+
* 1) mode != off: scan the ORIGINAL (pre-redaction) content for leaks; strict + found → blocked=true (chokepoint refuses); warn → flag only.
|
|
303
|
+
* 2) REGARDLESS of mode, always deep-redact every asset + recompute asset_id (the leak-proof floor; off only skips the scan, not the redaction).
|
|
304
|
+
*/
|
|
305
|
+
export function sanitizeBundle(bundle, opts) {
|
|
306
|
+
const mode = opts.mode ?? leakCheckModeFromEnv(opts.env);
|
|
307
|
+
let leaks = [];
|
|
308
|
+
if (mode !== 'off') {
|
|
309
|
+
const combined = bundle.map((a) => JSON.stringify(a)).join('');
|
|
310
|
+
leaks = fullLeakCheck(combined, opts.env).leaks;
|
|
311
|
+
}
|
|
312
|
+
// #12: a bare local path is PII (anonymized to ~/ by the redaction floor), not a credential — it must not
|
|
313
|
+
// hard-block a publish in strict mode. Real secrets (everything else) still block. Path leaks stay reported.
|
|
314
|
+
const blocked = mode === 'strict' && leaks.some((l) => !PII_ONLY_LEAK_TYPES.has(l.type));
|
|
315
|
+
const sanitized = bundle.map((a) => sanitizeAsset(a));
|
|
316
|
+
return { bundle: sanitized, blocked, leaks, mode };
|
|
317
|
+
}
|
|
318
|
+
/** Collapse a leak list into a one-line human-readable summary (for logs / rejection reason). */
|
|
319
|
+
export function summarizeLeaks(leaks) {
|
|
320
|
+
return leaks.map((l) => `${l.type}→${l.suggestion}`).join('; ');
|
|
321
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const PACKAGE = "@evomap/evolver-core";
|
|
2
|
+
export * as schema from './schema/index.js';
|
|
3
|
+
export * as wire from './wire/index.js';
|
|
4
|
+
export * as events from './events/public.js';
|
|
5
|
+
export * as signatures from './signatures/index.js';
|
|
6
|
+
export * as trigger from './trigger/index.js';
|
|
7
|
+
export * as observers from './observers/index.js';
|
|
8
|
+
export * as cycle from './cycle/index.js';
|
|
9
|
+
export * as daemon from './daemon/index.js';
|
|
10
|
+
export * as material from './material/index.js';
|
|
11
|
+
export * as mailbox from './mailbox/index.js';
|
|
12
|
+
export * as assetstore from './assetstore/index.js';
|
|
13
|
+
export * as strategy from './strategy/index.js';
|
|
14
|
+
export * as algo from './algo/index.js';
|
|
15
|
+
export * as personality from './personality/index.js';
|
|
16
|
+
export * as signals from './signals/index.js';
|
|
17
|
+
export * as verify from './verify/index.js';
|
|
18
|
+
export * as exec from './exec/index.js';
|
|
19
|
+
export * as bootstrap from './bootstrap/index.js';
|
|
20
|
+
export * as hooks from './hooks/index.js';
|
|
21
|
+
export * as benchmark from './benchmark/index.js';
|
|
22
|
+
export * as workflow from './workflow/index.js';
|
|
23
|
+
export * as hub from './hub/index.js';
|
|
24
|
+
export * as shadow from './shadow/index.js';
|
|
25
|
+
export * as ops from './ops/index.js';
|
|
26
|
+
export * as util from './util/index.js';
|
|
27
|
+
export * as trace from './trace/index.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const PACKAGE = '@evomap/evolver-core';
|
|
2
|
+
export * as schema from './schema/index.js';
|
|
3
|
+
export * as wire from './wire/index.js';
|
|
4
|
+
export * as events from './events/public.js';
|
|
5
|
+
export * as signatures from './signatures/index.js';
|
|
6
|
+
export * as trigger from './trigger/index.js';
|
|
7
|
+
export * as observers from './observers/index.js';
|
|
8
|
+
export * as cycle from './cycle/index.js';
|
|
9
|
+
export * as daemon from './daemon/index.js';
|
|
10
|
+
export * as material from './material/index.js';
|
|
11
|
+
export * as mailbox from './mailbox/index.js';
|
|
12
|
+
export * as assetstore from './assetstore/index.js';
|
|
13
|
+
export * as strategy from './strategy/index.js';
|
|
14
|
+
export * as algo from './algo/index.js';
|
|
15
|
+
export * as personality from './personality/index.js';
|
|
16
|
+
export * as signals from './signals/index.js';
|
|
17
|
+
export * as verify from './verify/index.js';
|
|
18
|
+
export * as exec from './exec/index.js';
|
|
19
|
+
export * as bootstrap from './bootstrap/index.js';
|
|
20
|
+
export * as hooks from './hooks/index.js';
|
|
21
|
+
export * as benchmark from './benchmark/index.js';
|
|
22
|
+
export * as workflow from './workflow/index.js';
|
|
23
|
+
export * as hub from './hub/index.js';
|
|
24
|
+
export * as shadow from './shadow/index.js';
|
|
25
|
+
export * as ops from './ops/index.js';
|
|
26
|
+
export * as util from './util/index.js';
|
|
27
|
+
export * as trace from './trace/index.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type Direction = 'outbound' | 'inbound' | 'local';
|
|
2
|
+
export type Handler = 'core' | 'proxy' | 'agent';
|
|
3
|
+
export type TtlClass = 'control' | 'default';
|
|
4
|
+
export interface MessageSpec {
|
|
5
|
+
direction: Direction;
|
|
6
|
+
handler: Handler;
|
|
7
|
+
feedsMaterial: boolean;
|
|
8
|
+
ttlClass: TtlClass;
|
|
9
|
+
}
|
|
10
|
+
export declare class UnknownMessageTypeError extends Error {
|
|
11
|
+
readonly type: string;
|
|
12
|
+
constructor(type: string);
|
|
13
|
+
}
|
|
14
|
+
/** 三态消息目录单一来源 (mailbox 草案 §4). handler: core 确定性 / proxy non-agentic hub往返 / agent 需智能. */
|
|
15
|
+
export declare const MESSAGE_CATALOG: Readonly<Record<string, MessageSpec>>;
|
|
16
|
+
export declare function specForType(type: string): MessageSpec | undefined;
|
|
17
|
+
export declare function assertKnownType(type: string): MessageSpec;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export class UnknownMessageTypeError extends Error {
|
|
2
|
+
type;
|
|
3
|
+
constructor(type) {
|
|
4
|
+
super(`未知 mailbox 消息类型: ${type}`);
|
|
5
|
+
this.type = type;
|
|
6
|
+
this.name = 'UnknownMessageTypeError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** 三态消息目录单一来源 (mailbox 草案 §4). handler: core 确定性 / proxy non-agentic hub往返 / agent 需智能. */
|
|
10
|
+
export const MESSAGE_CATALOG = {
|
|
11
|
+
// agent→hub (outbound)
|
|
12
|
+
asset_submit: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
13
|
+
task_claim: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
14
|
+
task_complete: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
15
|
+
task_subscribe: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
16
|
+
task_unsubscribe: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
17
|
+
atp_order: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
18
|
+
atp_deliver: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
19
|
+
atp_settle: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
20
|
+
proxy_trace: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
21
|
+
// hub→agent / local (inbound)
|
|
22
|
+
pending_materials: { direction: 'local', handler: 'agent', feedsMaterial: false, ttlClass: 'default' },
|
|
23
|
+
asset_publish_result: { direction: 'inbound', handler: 'core', feedsMaterial: false, ttlClass: 'default' }, // 拒绝进 Material 在 dispatch 决定
|
|
24
|
+
pending_evomap_task: { direction: 'inbound', handler: 'agent', feedsMaterial: false, ttlClass: 'default' },
|
|
25
|
+
task_available: { direction: 'inbound', handler: 'agent', feedsMaterial: false, ttlClass: 'default' },
|
|
26
|
+
work_assigned: { direction: 'inbound', handler: 'agent', feedsMaterial: false, ttlClass: 'default' },
|
|
27
|
+
dialog_message: { direction: 'inbound', handler: 'agent', feedsMaterial: true, ttlClass: 'default' },
|
|
28
|
+
peer_review_request: { direction: 'inbound', handler: 'agent', feedsMaterial: true, ttlClass: 'default' },
|
|
29
|
+
bounty_review_requested: { direction: 'inbound', handler: 'agent', feedsMaterial: true, ttlClass: 'default' },
|
|
30
|
+
dm: { direction: 'inbound', handler: 'agent', feedsMaterial: true, ttlClass: 'default' },
|
|
31
|
+
feature_flag_update: { direction: 'inbound', handler: 'core', feedsMaterial: false, ttlClass: 'control' },
|
|
32
|
+
force_update: { direction: 'inbound', handler: 'core', feedsMaterial: false, ttlClass: 'control' },
|
|
33
|
+
overdue_tasks: { direction: 'inbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
34
|
+
heartbeat: { direction: 'outbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
35
|
+
credential_rotation: { direction: 'inbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
36
|
+
trace_collection_config: { direction: 'inbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
37
|
+
proxy_trace_config: { direction: 'inbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'control' },
|
|
38
|
+
skill_md_update: { direction: 'inbound', handler: 'proxy', feedsMaterial: false, ttlClass: 'default' },
|
|
39
|
+
};
|
|
40
|
+
const PREFIX_SPECS = [
|
|
41
|
+
['council.', { direction: 'inbound', handler: 'agent', feedsMaterial: true, ttlClass: 'default' }],
|
|
42
|
+
['deliberation.', { direction: 'inbound', handler: 'agent', feedsMaterial: true, ttlClass: 'default' }],
|
|
43
|
+
['swarm.', { direction: 'inbound', handler: 'agent', feedsMaterial: false, ttlClass: 'default' }], // 仅结论进, dispatch 决定
|
|
44
|
+
];
|
|
45
|
+
export function specForType(type) {
|
|
46
|
+
return MESSAGE_CATALOG[type] ?? PREFIX_SPECS.find(([pre]) => type.startsWith(pre))?.[1];
|
|
47
|
+
}
|
|
48
|
+
export function assertKnownType(type) {
|
|
49
|
+
const s = specForType(type);
|
|
50
|
+
if (!s)
|
|
51
|
+
throw new UnknownMessageTypeError(type);
|
|
52
|
+
return s;
|
|
53
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DrainController } from '../daemon/drain.js';
|
|
2
|
+
import type { MailboxStore } from './store.js';
|
|
3
|
+
import type { Dispatcher, DispatchResult } from './dispatch.js';
|
|
4
|
+
import type { AgentWaker, WakeOutcome } from './wake.js';
|
|
5
|
+
import type { Handler } from './catalog.js';
|
|
6
|
+
export interface MailboxDaemonDeps {
|
|
7
|
+
store: MailboxStore;
|
|
8
|
+
dispatcher: Dispatcher;
|
|
9
|
+
waker?: AgentWaker;
|
|
10
|
+
/** 闸2 drain: 注入共享或自建. */
|
|
11
|
+
drain?: DrainController;
|
|
12
|
+
/** 单写文件锁(可选); 防多 daemon 同时 pump 同信箱. */
|
|
13
|
+
lockPath?: string;
|
|
14
|
+
now: () => number;
|
|
15
|
+
/** 每 N 个 tick 跑一次 TTL 扫描(默认 60). */
|
|
16
|
+
expireEveryTicks?: number;
|
|
17
|
+
pumpHandlers?: Handler[];
|
|
18
|
+
}
|
|
19
|
+
export interface TickReport {
|
|
20
|
+
skipped: boolean;
|
|
21
|
+
dispatched: DispatchResult[];
|
|
22
|
+
woken: WakeOutcome[];
|
|
23
|
+
expired: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Mailbox daemon 循环(M2-9), 整进军杰附录 A 四闸:
|
|
27
|
+
* - 闸1 cycle-local: 每 tick 独立(dispatcher 无跨 tick 可变态).
|
|
28
|
+
* - 闸2 drain: draining 时拒新 tick, 排空进行中再退.
|
|
29
|
+
* - 闸3 watchdog: 暴露 lastWriteAt 供外部 watchdog 判挂死.
|
|
30
|
+
* - 闸4 幂等: dispatcher 经 store idempotency 表(无时间窗)去重副作用.
|
|
31
|
+
* 单写: 可选 O_EXCL 文件锁.
|
|
32
|
+
*/
|
|
33
|
+
export declare class MailboxDaemon {
|
|
34
|
+
private readonly deps;
|
|
35
|
+
private readonly drain;
|
|
36
|
+
private lastActivityAt;
|
|
37
|
+
private ticks;
|
|
38
|
+
private locked;
|
|
39
|
+
constructor(deps: MailboxDaemonDeps);
|
|
40
|
+
start(): void;
|
|
41
|
+
/** 一个处理周期: pump(core+proxy) + waker.tick + 周期性 TTL 扫描. */
|
|
42
|
+
tick(): Promise<TickReport>;
|
|
43
|
+
/** 闸3: root_events/活动最后写入时间, 喂外部 Watchdog. */
|
|
44
|
+
lastWriteAt(): number;
|
|
45
|
+
/** 闸2: 优雅停机 — 停接新 tick, 排空进行中, 释放锁. */
|
|
46
|
+
stop(): Promise<void>;
|
|
47
|
+
get isDraining(): boolean;
|
|
48
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { acquireLock, releaseLock } from '../util/fileLock.js';
|
|
2
|
+
import { DrainController } from '../daemon/drain.js';
|
|
3
|
+
/**
|
|
4
|
+
* Mailbox daemon 循环(M2-9), 整进军杰附录 A 四闸:
|
|
5
|
+
* - 闸1 cycle-local: 每 tick 独立(dispatcher 无跨 tick 可变态).
|
|
6
|
+
* - 闸2 drain: draining 时拒新 tick, 排空进行中再退.
|
|
7
|
+
* - 闸3 watchdog: 暴露 lastWriteAt 供外部 watchdog 判挂死.
|
|
8
|
+
* - 闸4 幂等: dispatcher 经 store idempotency 表(无时间窗)去重副作用.
|
|
9
|
+
* 单写: 可选 O_EXCL 文件锁.
|
|
10
|
+
*/
|
|
11
|
+
export class MailboxDaemon {
|
|
12
|
+
deps;
|
|
13
|
+
drain;
|
|
14
|
+
lastActivityAt;
|
|
15
|
+
ticks = 0;
|
|
16
|
+
locked = false;
|
|
17
|
+
constructor(deps) {
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
this.drain = deps.drain ?? new DrainController();
|
|
20
|
+
this.lastActivityAt = deps.now();
|
|
21
|
+
}
|
|
22
|
+
start() {
|
|
23
|
+
if (this.deps.lockPath && !this.locked) {
|
|
24
|
+
acquireLock(this.deps.lockPath);
|
|
25
|
+
this.locked = true;
|
|
26
|
+
}
|
|
27
|
+
this.lastActivityAt = this.deps.now();
|
|
28
|
+
}
|
|
29
|
+
/** 一个处理周期: pump(core+proxy) + waker.tick + 周期性 TTL 扫描. */
|
|
30
|
+
async tick() {
|
|
31
|
+
if (!this.drain.acceptCycle())
|
|
32
|
+
return { skipped: true, dispatched: [], woken: [], expired: 0 };
|
|
33
|
+
this.drain.beginCycle();
|
|
34
|
+
try {
|
|
35
|
+
const now = this.deps.now();
|
|
36
|
+
const dispatched = await this.deps.dispatcher.pump({ handlers: this.deps.pumpHandlers });
|
|
37
|
+
const woken = this.deps.waker ? await this.deps.waker.tick() : [];
|
|
38
|
+
let expired = 0;
|
|
39
|
+
this.ticks += 1;
|
|
40
|
+
if (this.ticks % (this.deps.expireEveryTicks ?? 60) === 0)
|
|
41
|
+
expired = this.deps.store.expireOld(now);
|
|
42
|
+
if (dispatched.length > 0 || woken.some((w) => w.action !== 'none') || expired > 0)
|
|
43
|
+
this.lastActivityAt = now;
|
|
44
|
+
return { skipped: false, dispatched, woken, expired };
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
this.drain.endCycle();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** 闸3: root_events/活动最后写入时间, 喂外部 Watchdog. */
|
|
51
|
+
lastWriteAt() { return this.lastActivityAt; }
|
|
52
|
+
/** 闸2: 优雅停机 — 停接新 tick, 排空进行中, 释放锁. */
|
|
53
|
+
async stop() {
|
|
54
|
+
await this.drain.drain();
|
|
55
|
+
if (this.deps.lockPath && this.locked) {
|
|
56
|
+
releaseLock(this.deps.lockPath);
|
|
57
|
+
this.locked = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
get isDraining() { return this.drain.isDraining; }
|
|
61
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Envelope } from './envelope.js';
|
|
2
|
+
import type { Handler } from './catalog.js';
|
|
3
|
+
import type { MailboxStore } from './store.js';
|
|
4
|
+
export interface DispatchResult {
|
|
5
|
+
id: string;
|
|
6
|
+
handler: Handler;
|
|
7
|
+
handled: boolean;
|
|
8
|
+
fedMaterial: boolean;
|
|
9
|
+
note?: string;
|
|
10
|
+
}
|
|
11
|
+
/** 三类 handler 实现; 由集成层注入. core=确定性, proxy=hub 往返, agent=智能(嵌入式 runtime 时直接处理). */
|
|
12
|
+
export interface DispatchHandlers {
|
|
13
|
+
core: (e: Envelope) => Promise<unknown> | unknown;
|
|
14
|
+
proxy: (e: Envelope) => Promise<unknown> | unknown;
|
|
15
|
+
agent: (e: Envelope) => Promise<unknown> | unknown;
|
|
16
|
+
}
|
|
17
|
+
export interface DispatcherDeps {
|
|
18
|
+
store: MailboxStore;
|
|
19
|
+
handlers: DispatchHandlers;
|
|
20
|
+
/** 选择性 Material 投喂: dispatch 判定通过才调用(集成层把 envelope→Material). */
|
|
21
|
+
onMaterial?: (e: Envelope) => void | Promise<void>;
|
|
22
|
+
now: () => number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 选择性 Material 判定(M2-7). 默认遵目录 feedsMaterial; 两类在 dispatch 决定:
|
|
26
|
+
* - asset_publish_result: 仅 rejected 进(失败=养料 #40); 通过无需.
|
|
27
|
+
* - swarm.*: 仅带结论的进; 中间消息不进.
|
|
28
|
+
*/
|
|
29
|
+
export declare function shouldFeedMaterial(e: Envelope): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* 三-handler 分派器(M2-7). 谁 claim 谁 complete:
|
|
32
|
+
* - daemon 侧 pump core+proxy(确定性/hub 往返).
|
|
33
|
+
* - agent 类常由外部 runtime 经 IPC(M2-6) claim+complete; 嵌入式可显式 pump ['agent'].
|
|
34
|
+
*/
|
|
35
|
+
export declare class Dispatcher {
|
|
36
|
+
private readonly deps;
|
|
37
|
+
constructor(deps: DispatcherDeps);
|
|
38
|
+
dispatchOne(e: Envelope): Promise<DispatchResult>;
|
|
39
|
+
/** 拉一批并分派. 默认 daemon 侧 core+proxy; agent 由 runtime 经 IPC 拉取. */
|
|
40
|
+
pump(opts?: {
|
|
41
|
+
handlers?: Handler[];
|
|
42
|
+
limit?: number;
|
|
43
|
+
leaseMs?: number;
|
|
44
|
+
runtimeNamespace?: string;
|
|
45
|
+
}): Promise<DispatchResult[]>;
|
|
46
|
+
}
|