@howlil/ez-agents 3.5.0 → 4.0.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/README.md +735 -537
- package/agents/ez-architect-agent.md +267 -0
- package/agents/ez-backend-agent.md +303 -0
- package/agents/ez-chief-strategist.md +271 -0
- package/agents/ez-codebase-mapper.md +770 -770
- package/agents/ez-context-manager.md +319 -0
- package/agents/ez-debugger.md +1255 -1255
- package/agents/ez-design-expert.md +347 -0
- package/agents/ez-devops-agent.md +331 -0
- package/agents/ez-executor.md +487 -487
- package/agents/ez-frontend-agent.md +322 -0
- package/agents/ez-phase-researcher.md +553 -553
- package/agents/ez-planner.md +1307 -1307
- package/agents/ez-product-engineer.md +435 -0
- package/agents/ez-project-researcher.md +629 -629
- package/agents/ez-qa-agent.md +320 -0
- package/agents/ez-release-agent.md +333 -333
- package/agents/ez-requirements-agent.md +377 -377
- package/agents/ez-roadmapper.md +650 -650
- package/agents/ez-technical-writer.md +551 -0
- package/agents/ez-ux-expert.md +393 -0
- package/agents/ez-verifier.md +579 -579
- package/bin/guards/autonomy-guard.cjs +346 -0
- package/bin/guards/context-budget-guard.cjs +278 -0
- package/bin/guards/hallucination-guard.cjs +380 -0
- package/bin/guards/hidden-state-guard.cjs +182 -0
- package/bin/guards/team-overhead-guard.cjs +266 -0
- package/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/bin/lib/archetype-detector.cjs +289 -0
- package/bin/lib/assistant-adapter.cjs +361 -0
- package/bin/lib/audit-exec.cjs +175 -0
- package/bin/lib/auth.cjs +176 -0
- package/bin/lib/backup-service.cjs +422 -0
- package/bin/lib/bdd-validator.cjs +622 -0
- package/bin/lib/business-flow-mapper.cjs +429 -0
- package/bin/lib/circuit-breaker.cjs +276 -0
- package/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/bin/lib/codebase-analyzer.cjs +241 -0
- package/bin/lib/commands.cjs +691 -0
- package/bin/lib/config.cjs +236 -0
- package/bin/lib/constraint-extractor.cjs +526 -0
- package/bin/lib/content-scanner.cjs +238 -0
- package/bin/lib/context-cache.cjs +154 -0
- package/bin/lib/context-compressor.cjs +102 -0
- package/bin/lib/context-deduplicator.cjs +105 -0
- package/bin/lib/context-errors.cjs +78 -0
- package/bin/lib/context-manager.cjs +338 -0
- package/bin/lib/context-metadata-tracker.cjs +140 -0
- package/bin/lib/context-relevance-scorer.cjs +99 -0
- package/bin/lib/core.cjs +507 -0
- package/bin/lib/cost-alerts.cjs +174 -0
- package/bin/lib/cost-tracker.cjs +275 -0
- package/bin/lib/crash-recovery.cjs +220 -0
- package/bin/lib/dependency-graph.cjs +319 -0
- package/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/bin/lib/deploy/deploy-status.cjs +74 -0
- package/bin/lib/discussion-synthesizer.cjs +439 -0
- package/bin/lib/error-cache.cjs +114 -0
- package/bin/lib/error-registry.cjs +177 -0
- package/bin/lib/file-access.cjs +207 -0
- package/bin/lib/file-lock.cjs +236 -0
- package/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/bin/lib/finops/cost-reporter.cjs +132 -0
- package/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/bin/lib/finops/spot-manager.cjs +118 -0
- package/bin/lib/framework-detector.cjs +396 -0
- package/bin/lib/frontmatter.cjs +313 -0
- package/bin/lib/fs-utils.cjs +153 -0
- package/bin/lib/gate-executor.cjs +272 -0
- package/bin/lib/gates/README.md +374 -0
- package/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/bin/lib/gates/gate-03-code.cjs +635 -0
- package/bin/lib/gates/gate-04-security.cjs +829 -0
- package/bin/lib/git-errors.cjs +83 -0
- package/bin/lib/git-utils.cjs +321 -0
- package/bin/lib/git-workflow-engine.cjs +1157 -0
- package/bin/lib/health-check.cjs +227 -0
- package/bin/lib/index.cjs +279 -0
- package/bin/lib/init.cjs +725 -0
- package/bin/lib/lock-logger.cjs +194 -0
- package/bin/lib/lock-state.cjs +263 -0
- package/bin/lib/lockfile-validator.cjs +227 -0
- package/bin/lib/log-rotation.cjs +71 -0
- package/bin/lib/logger.cjs +125 -0
- package/bin/lib/memory-compression.cjs +256 -0
- package/bin/lib/milestone.cjs +247 -0
- package/bin/lib/model-provider.cjs +241 -0
- package/bin/lib/package-manager-detector.cjs +203 -0
- package/bin/lib/package-manager-executor.cjs +385 -0
- package/bin/lib/package-manager-service.cjs +216 -0
- package/bin/lib/perf/api-monitor.cjs +88 -0
- package/bin/lib/perf/db-optimizer.cjs +78 -0
- package/bin/lib/perf/frontend-performance.cjs +56 -0
- package/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/bin/lib/perf/perf-baseline.cjs +102 -0
- package/bin/lib/perf/perf-reporter.cjs +117 -0
- package/bin/lib/perf/regression-detector.cjs +92 -0
- package/bin/lib/phase.cjs +963 -0
- package/bin/lib/planning-write.cjs +123 -0
- package/bin/lib/project-reporter.cjs +565 -0
- package/bin/lib/quality-gate.cjs +332 -0
- package/bin/lib/quality-metrics.cjs +324 -0
- package/bin/lib/recovery-manager.cjs +98 -0
- package/bin/lib/release-validator.cjs +617 -0
- package/bin/lib/retry.cjs +119 -0
- package/bin/lib/roadmap.cjs +309 -0
- package/bin/lib/safe-exec.cjs +173 -0
- package/bin/lib/safe-path.cjs +130 -0
- package/bin/lib/security-errors.cjs +62 -0
- package/bin/lib/session-chain.cjs +304 -0
- package/bin/lib/session-errors.cjs +81 -0
- package/bin/lib/session-export.cjs +251 -0
- package/bin/lib/session-import.cjs +262 -0
- package/bin/lib/session-manager.cjs +280 -0
- package/bin/lib/skill-context.cjs +148 -0
- package/bin/lib/skill-matcher.cjs +236 -0
- package/bin/lib/skill-registry.cjs +360 -0
- package/bin/lib/skill-resolver.cjs +449 -0
- package/bin/lib/skill-triggers.cjs +90 -0
- package/bin/lib/skill-validator.cjs +270 -0
- package/bin/lib/skill-versioning.cjs +355 -0
- package/bin/lib/stack-detector.cjs +399 -0
- package/bin/lib/state.cjs +736 -0
- package/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/bin/lib/temp-file.cjs +239 -0
- package/bin/lib/template.cjs +223 -0
- package/bin/lib/test-file-lock.cjs +112 -0
- package/bin/lib/test-graceful.cjs +93 -0
- package/bin/lib/test-logger.cjs +60 -0
- package/bin/lib/test-safe-exec.cjs +38 -0
- package/bin/lib/test-safe-path.cjs +33 -0
- package/bin/lib/test-temp-file.cjs +125 -0
- package/bin/lib/tier-manager.cjs +428 -0
- package/bin/lib/timeout-exec.cjs +63 -0
- package/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/bin/lib/url-fetch.cjs +170 -0
- package/bin/lib/verify.cjs +863 -0
- package/bin/update.js +217 -214
- package/commands/deploy.cjs +53 -0
- package/commands/ez/add-tests.md +41 -41
- package/commands/ez/audit-milestone.md +36 -36
- package/commands/ez/complete-milestone.md +136 -136
- package/commands/ez/discuss-phase.md +90 -90
- package/commands/ez/execute-phase.md +52 -52
- package/commands/ez/help.md +22 -22
- package/commands/ez/map-codebase.md +71 -71
- package/commands/ez/new-milestone.md +44 -44
- package/commands/ez/new-project.md +51 -42
- package/commands/ez/plan-phase.md +53 -53
- package/commands/ez/progress.md +36 -36
- package/commands/ez/quick.md +45 -45
- package/commands/ez/resume-work.md +40 -40
- package/commands/ez/run-phase.md +580 -0
- package/commands/ez/settings.md +36 -36
- package/commands/ez/update.md +37 -37
- package/commands/ez/verify-work.md +402 -38
- package/commands/health-check.cjs +44 -0
- package/commands/rollback.cjs +47 -0
- package/ez-agents/bin/ez-tools.cjs +599 -2
- package/ez-agents/bin/guards/autonomy-guard.cjs +346 -0
- package/ez-agents/bin/guards/context-budget-guard.cjs +247 -0
- package/ez-agents/bin/guards/hallucination-guard.cjs +271 -0
- package/ez-agents/bin/guards/hidden-state-guard.cjs +182 -0
- package/ez-agents/bin/guards/team-overhead-guard.cjs +266 -0
- package/ez-agents/bin/guards/tool-sprawl-guard.cjs +271 -0
- package/ez-agents/bin/lib/analytics/analytics-collector.cjs +86 -0
- package/ez-agents/bin/lib/analytics/analytics-reporter.cjs +130 -0
- package/ez-agents/bin/lib/analytics/cohort-analyzer.cjs +138 -0
- package/ez-agents/bin/lib/analytics/funnel-analyzer.cjs +147 -0
- package/ez-agents/bin/lib/analytics/nps-tracker.cjs +147 -0
- package/ez-agents/bin/lib/archetype-detector.cjs +289 -0
- package/ez-agents/bin/lib/audit-exec.cjs +166 -167
- package/ez-agents/bin/lib/auth.cjs +176 -176
- package/ez-agents/bin/lib/backup-service.cjs +422 -0
- package/ez-agents/bin/lib/bdd-validator.cjs +622 -622
- package/ez-agents/bin/lib/business-flow-mapper.cjs +429 -0
- package/ez-agents/bin/lib/code-complexity-analyzer.cjs +360 -0
- package/ez-agents/bin/lib/codebase-analyzer.cjs +241 -0
- package/ez-agents/bin/lib/commands.cjs +685 -685
- package/ez-agents/bin/lib/config.cjs +41 -1
- package/ez-agents/bin/lib/constraint-extractor.cjs +526 -0
- package/ez-agents/bin/lib/content-scanner.cjs +238 -238
- package/ez-agents/bin/lib/context-cache.cjs +154 -154
- package/ez-agents/bin/lib/context-errors.cjs +71 -71
- package/ez-agents/bin/lib/context-manager.cjs +220 -220
- package/ez-agents/bin/lib/core.cjs +507 -512
- package/ez-agents/bin/lib/cost-tracker.cjs +243 -0
- package/ez-agents/bin/lib/crash-recovery.cjs +172 -0
- package/ez-agents/bin/lib/dependency-graph.cjs +319 -0
- package/ez-agents/bin/lib/deploy/deploy-audit-log.cjs +76 -0
- package/ez-agents/bin/lib/deploy/deploy-detector.cjs +69 -0
- package/ez-agents/bin/lib/deploy/deploy-env-manager.cjs +109 -0
- package/ez-agents/bin/lib/deploy/deploy-health-check.cjs +88 -0
- package/ez-agents/bin/lib/deploy/deploy-pre-flight.cjs +57 -0
- package/ez-agents/bin/lib/deploy/deploy-rollback.cjs +72 -0
- package/ez-agents/bin/lib/deploy/deploy-runner.cjs +97 -0
- package/ez-agents/bin/lib/deploy/deploy-status.cjs +74 -0
- package/ez-agents/bin/lib/file-access.cjs +207 -207
- package/ez-agents/bin/lib/finops/budget-enforcer.cjs +126 -0
- package/ez-agents/bin/lib/finops/cost-reporter.cjs +132 -0
- package/ez-agents/bin/lib/finops/finops-analyzer.cjs +112 -0
- package/ez-agents/bin/lib/finops/spot-manager.cjs +118 -0
- package/ez-agents/bin/lib/framework-detector.cjs +396 -0
- package/ez-agents/bin/lib/frontmatter.cjs +3 -1
- package/ez-agents/bin/lib/gates/README.md +374 -0
- package/ez-agents/bin/lib/gates/gate-01-requirement.cjs +303 -0
- package/ez-agents/bin/lib/gates/gate-02-architecture.cjs +555 -0
- package/ez-agents/bin/lib/gates/gate-03-code.cjs +635 -0
- package/ez-agents/bin/lib/gates/gate-04-security.cjs +829 -0
- package/ez-agents/bin/lib/git-errors.cjs +83 -83
- package/ez-agents/bin/lib/git-utils.cjs +321 -321
- package/ez-agents/bin/lib/git-workflow-engine.cjs +1157 -1157
- package/ez-agents/bin/lib/health-check.cjs +162 -162
- package/ez-agents/bin/lib/index.cjs +2 -8
- package/ez-agents/bin/lib/init.cjs +0 -2
- package/ez-agents/bin/lib/lockfile-validator.cjs +227 -227
- package/ez-agents/bin/lib/log-rotation.cjs +71 -0
- package/ez-agents/bin/lib/logger.cjs +22 -47
- package/ez-agents/bin/lib/memory-compression.cjs +256 -256
- package/ez-agents/bin/lib/package-manager-detector.cjs +203 -203
- package/ez-agents/bin/lib/package-manager-executor.cjs +385 -385
- package/ez-agents/bin/lib/package-manager-service.cjs +216 -216
- package/ez-agents/bin/lib/perf/api-monitor.cjs +88 -0
- package/ez-agents/bin/lib/perf/db-optimizer.cjs +78 -0
- package/ez-agents/bin/lib/perf/frontend-performance.cjs +56 -0
- package/ez-agents/bin/lib/perf/perf-analyzer.cjs +77 -0
- package/ez-agents/bin/lib/perf/perf-baseline.cjs +102 -0
- package/ez-agents/bin/lib/perf/perf-reporter.cjs +117 -0
- package/ez-agents/bin/lib/perf/regression-detector.cjs +92 -0
- package/ez-agents/bin/lib/project-reporter.cjs +502 -0
- package/ez-agents/bin/lib/quality-gate.cjs +332 -0
- package/ez-agents/bin/lib/recovery-manager.cjs +98 -0
- package/ez-agents/bin/lib/release-validator.cjs +617 -614
- package/ez-agents/bin/lib/security-errors.cjs +62 -0
- package/ez-agents/bin/lib/session-chain.cjs +304 -304
- package/ez-agents/bin/lib/session-errors.cjs +81 -81
- package/ez-agents/bin/lib/session-export.cjs +251 -251
- package/ez-agents/bin/lib/session-import.cjs +262 -262
- package/ez-agents/bin/lib/session-manager.cjs +280 -280
- package/ez-agents/bin/lib/skill-context.cjs +148 -0
- package/ez-agents/bin/lib/skill-matcher.cjs +236 -0
- package/ez-agents/bin/lib/skill-registry.cjs +341 -0
- package/ez-agents/bin/lib/skill-resolver.cjs +449 -0
- package/ez-agents/bin/lib/skill-triggers.cjs +90 -0
- package/ez-agents/bin/lib/skill-validator.cjs +270 -0
- package/ez-agents/bin/lib/skill-versioning.cjs +355 -0
- package/ez-agents/bin/lib/stack-detector.cjs +399 -0
- package/ez-agents/bin/lib/tech-debt-analyzer.cjs +309 -0
- package/ez-agents/bin/lib/tier-manager.cjs +428 -428
- package/ez-agents/bin/lib/tradeoff-analyzer.cjs +284 -0
- package/ez-agents/bin/lib/url-fetch.cjs +170 -170
- package/ez-agents/bin/lib/verify.cjs +863 -863
- package/ez-agents/references/decimal-phase-calculation.md +65 -65
- package/ez-agents/references/git-integration.md +248 -248
- package/ez-agents/references/git-planning-commit.md +38 -38
- package/ez-agents/references/metrics-schema.md +118 -118
- package/ez-agents/references/model-profile-resolution.md +34 -34
- package/ez-agents/references/model-profiles.md +93 -93
- package/ez-agents/references/phase-argument-parsing.md +61 -61
- package/ez-agents/references/planning-config.md +340 -340
- package/ez-agents/references/tier-strategy.md +103 -103
- package/ez-agents/references/ui-brand.md +160 -160
- package/ez-agents/references/verification-patterns.md +612 -612
- package/ez-agents/templates/DEBUG.md +164 -164
- package/ez-agents/templates/UAT.md +247 -247
- package/ez-agents/templates/agent-output-format.md +404 -0
- package/ez-agents/templates/bdd-feature.md +173 -173
- package/ez-agents/templates/codebase/architecture.md +255 -255
- package/ez-agents/templates/codebase/structure.md +285 -285
- package/ez-agents/templates/copilot-instructions.md +7 -7
- package/ez-agents/templates/debug-subagent-prompt.md +91 -91
- package/ez-agents/templates/discovery.md +146 -146
- package/ez-agents/templates/discussion.md +68 -68
- package/ez-agents/templates/handoff-protocol.md +294 -0
- package/ez-agents/templates/incident-runbook.md +205 -205
- package/ez-agents/templates/mode-workflow-templates.md +301 -0
- package/ez-agents/templates/phase-prompt.md +610 -610
- package/ez-agents/templates/planner-subagent-prompt.md +117 -117
- package/ez-agents/templates/project.md +184 -184
- package/ez-agents/templates/release-checklist.md +136 -133
- package/ez-agents/templates/research.md +552 -552
- package/ez-agents/templates/rollback-plan.md +201 -201
- package/ez-agents/templates/security-user-setup.md +244 -0
- package/ez-agents/templates/skill-validation-rules.md +476 -0
- package/ez-agents/templates/state.md +180 -176
- package/ez-agents/templates/summary-complex.md +59 -59
- package/ez-agents/tests/gates/gate-01-02.test.cjs +812 -0
- package/ez-agents/tests/gates/gate-03-04.test.cjs +762 -0
- package/ez-agents/tests/gates/gate-05-validator.test.cjs +145 -0
- package/ez-agents/tests/gates/gate-06-docs-validator.test.cjs +244 -0
- package/ez-agents/tests/gates/gate-07-release-validator.test.cjs +219 -0
- package/ez-agents/tests/guards/context-budget-guard.test.cjs +145 -0
- package/ez-agents/tests/guards/edge-case-guards.test.cjs +238 -0
- package/ez-agents/tests/guards/hallucination-guard.test.cjs +124 -0
- package/ez-agents/workflows/audit-milestone.md +1 -1
- package/ez-agents/workflows/autonomous.md +844 -844
- package/ez-agents/workflows/complete-milestone.md +1 -1
- package/ez-agents/workflows/discuss-phase.md +1 -1
- package/ez-agents/workflows/execute-phase.md +124 -3
- package/ez-agents/workflows/help.md +42 -181
- package/ez-agents/workflows/hotfix.md +291 -291
- package/ez-agents/workflows/new-milestone.md +713 -713
- package/ez-agents/workflows/new-project.md +1089 -1107
- package/ez-agents/workflows/plan-phase.md +0 -40
- package/ez-agents/workflows/release.md +253 -253
- package/ez-agents/workflows/resume-session.md +215 -215
- package/ez-agents/workflows/run-phase.md +531 -0
- package/ez-agents/workflows/settings.md +2 -35
- package/hooks/dist/ez-check-update.js +81 -81
- package/hooks/dist/ez-context-monitor.js +148 -141
- package/hooks/dist/ez-statusline.js +115 -115
- package/package.json +78 -71
- package/scripts/fix-qwen-installation.js +144 -144
- package/agents/ez-integration-checker.md +0 -443
- package/agents/ez-nyquist-auditor.md +0 -176
- package/agents/ez-observer-agent.md +0 -260
- package/agents/ez-plan-checker.md +0 -706
- package/agents/ez-research-synthesizer.md +0 -247
- package/agents/ez-scrum-master-agent.md +0 -242
- package/agents/ez-tech-lead-agent.md +0 -267
- package/agents/ez-ui-auditor.md +0 -439
- package/agents/ez-ui-checker.md +0 -300
- package/agents/ez-ui-researcher.md +0 -353
- package/commands/ez/add-phase.md +0 -43
- package/commands/ez/add-todo.md +0 -47
- package/commands/ez/arch-review.md +0 -102
- package/commands/ez/auth.md +0 -87
- package/commands/ez/autonomous.md +0 -41
- package/commands/ez/check-todos.md +0 -45
- package/commands/ez/cleanup.md +0 -18
- package/commands/ez/debug.md +0 -168
- package/commands/ez/export-session.md +0 -79
- package/commands/ez/gather-requirements.md +0 -117
- package/commands/ez/git-workflow.md +0 -72
- package/commands/ez/health.md +0 -22
- package/commands/ez/hotfix.md +0 -120
- package/commands/ez/import-session.md +0 -82
- package/commands/ez/insert-phase.md +0 -32
- package/commands/ez/join-discord.md +0 -18
- package/commands/ez/list-phase-assumptions.md +0 -46
- package/commands/ez/list-sessions.md +0 -96
- package/commands/ez/package-manager.md +0 -316
- package/commands/ez/pause-work.md +0 -38
- package/commands/ez/plan-milestone-gaps.md +0 -34
- package/commands/ez/preflight.md +0 -79
- package/commands/ez/reapply-patches.md +0 -124
- package/commands/ez/release.md +0 -153
- package/commands/ez/remove-phase.md +0 -31
- package/commands/ez/research-phase.md +0 -190
- package/commands/ez/resume.md +0 -107
- package/commands/ez/set-profile.md +0 -34
- package/commands/ez/standup.md +0 -85
- package/commands/ez/stats.md +0 -18
- package/commands/ez/ui-phase.md +0 -34
- package/commands/ez/ui-review.md +0 -32
- package/commands/ez/validate-phase.md +0 -35
- package/ez-agents/bin/lib/metrics-tracker.cjs +0 -406
- package/ez-agents/templates/UI-SPEC.md +0 -100
- package/ez-agents/templates/VALIDATION.md +0 -76
- package/ez-agents/templates/context.md +0 -352
- package/ez-agents/templates/verification-report.md +0 -322
- package/ez-agents/workflows/arch-review.md +0 -54
- package/ez-agents/workflows/export-session.md +0 -255
- package/ez-agents/workflows/gather-requirements.md +0 -206
- package/ez-agents/workflows/import-session.md +0 -303
- package/ez-agents/workflows/research-phase.md +0 -74
- package/ez-agents/workflows/standup.md +0 -64
- package/ez-agents/workflows/ui-phase.md +0 -290
- package/ez-agents/workflows/ui-review.md +0 -157
- package/ez-agents/workflows/validate-phase.md +0 -167
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EZ Safe Path — Path traversal prevention utility
|
|
5
|
+
*
|
|
6
|
+
* Prevents path traversal attacks by:
|
|
7
|
+
* - Resolving and validating paths against base directory
|
|
8
|
+
* - Blocking paths that escape base directory
|
|
9
|
+
* - Handling Windows and Unix path formats
|
|
10
|
+
* - Logging blocked attempts for security audit
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const { normalizePath, isPathSafe, safeReadFile } = require('./safe-path.cjs');
|
|
14
|
+
* const safePath = normalizePath(process.cwd(), userPath);
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
const Logger = require('./logger.cjs');
|
|
20
|
+
const logger = new Logger();
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Normalize and validate a user-provided path against a base directory
|
|
24
|
+
* @param {string} baseDir - Base directory (trusted)
|
|
25
|
+
* @param {string} userPath - User-provided path (untrusted)
|
|
26
|
+
* @returns {string} - Resolved absolute path if safe
|
|
27
|
+
* @throws {Error} If path traversal detected
|
|
28
|
+
*/
|
|
29
|
+
function normalizePath(baseDir, userPath) {
|
|
30
|
+
// Resolve both paths to absolute
|
|
31
|
+
const resolvedBase = path.resolve(baseDir);
|
|
32
|
+
const resolvedUser = path.resolve(baseDir, userPath);
|
|
33
|
+
|
|
34
|
+
// Normalize for comparison (handle Windows backslashes)
|
|
35
|
+
const normalizedBase = resolvedBase + path.sep;
|
|
36
|
+
|
|
37
|
+
// Check if user path is within base directory
|
|
38
|
+
const isWithin =
|
|
39
|
+
resolvedUser === resolvedBase ||
|
|
40
|
+
resolvedUser.startsWith(normalizedBase);
|
|
41
|
+
|
|
42
|
+
if (!isWithin) {
|
|
43
|
+
logger.error('Path traversal detected', {
|
|
44
|
+
baseDir: resolvedBase,
|
|
45
|
+
userPath,
|
|
46
|
+
resolvedUser,
|
|
47
|
+
timestamp: new Date().toISOString()
|
|
48
|
+
});
|
|
49
|
+
throw new Error(`Path traversal detected: ${userPath}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return resolvedUser;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if a path is safe (within base directory) without throwing
|
|
57
|
+
* @param {string} baseDir - Base directory (trusted)
|
|
58
|
+
* @param {string} userPath - User-provided path (untrusted)
|
|
59
|
+
* @returns {boolean} - True if path is safe
|
|
60
|
+
*/
|
|
61
|
+
function isPathSafe(baseDir, userPath) {
|
|
62
|
+
try {
|
|
63
|
+
normalizePath(baseDir, userPath);
|
|
64
|
+
return true;
|
|
65
|
+
} catch (err) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Validate path exists and is safe
|
|
72
|
+
* @param {string} baseDir - Base directory
|
|
73
|
+
* @param {string} userPath - User-provided path
|
|
74
|
+
* @returns {string} - Resolved path if exists and safe
|
|
75
|
+
* @throws {Error} If not found or traversal detected
|
|
76
|
+
*/
|
|
77
|
+
function validatePathExists(baseDir, userPath) {
|
|
78
|
+
const resolvedPath = normalizePath(baseDir, userPath);
|
|
79
|
+
|
|
80
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
81
|
+
logger.warn('Path does not exist', {
|
|
82
|
+
resolvedPath,
|
|
83
|
+
userPath
|
|
84
|
+
});
|
|
85
|
+
throw new Error(`Path not found: ${userPath}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return resolvedPath;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Safely read a file (validates path before reading)
|
|
93
|
+
* @param {string} baseDir - Base directory
|
|
94
|
+
* @param {string} userPath - User-provided path
|
|
95
|
+
* @param {string} encoding - File encoding (default: utf-8)
|
|
96
|
+
* @returns {string} - File content
|
|
97
|
+
* @throws {Error} If path unsafe or file not found
|
|
98
|
+
*/
|
|
99
|
+
function safeReadFile(baseDir, userPath, encoding = 'utf-8') {
|
|
100
|
+
const resolvedPath = validatePathExists(baseDir, userPath);
|
|
101
|
+
|
|
102
|
+
logger.debug('Reading file', { resolvedPath, userPath });
|
|
103
|
+
|
|
104
|
+
return fs.readFileSync(resolvedPath, encoding);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get relative path from base, with validation
|
|
109
|
+
* @param {string} baseDir - Base directory
|
|
110
|
+
* @param {string} fullPath - Full path to convert
|
|
111
|
+
* @returns {string} - Relative path or throws if outside base
|
|
112
|
+
*/
|
|
113
|
+
function toRelativePath(baseDir, fullPath) {
|
|
114
|
+
const resolvedFull = path.resolve(fullPath);
|
|
115
|
+
const resolvedBase = path.resolve(baseDir);
|
|
116
|
+
|
|
117
|
+
if (!isPathSafe(baseDir, resolvedFull)) {
|
|
118
|
+
throw new Error(`Path outside base: ${fullPath}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return path.relative(resolvedBase, resolvedFull);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = {
|
|
125
|
+
normalizePath,
|
|
126
|
+
isPathSafe,
|
|
127
|
+
validatePathExists,
|
|
128
|
+
safeReadFile,
|
|
129
|
+
toRelativePath
|
|
130
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Security Operations Error Classes
|
|
5
|
+
*
|
|
6
|
+
* Provides structured error handling for security operations
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
class SecurityOpsError extends Error {
|
|
10
|
+
constructor(message, context = {}) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'SecurityOpsError';
|
|
13
|
+
this.context = context;
|
|
14
|
+
this.timestamp = new Date().toISOString();
|
|
15
|
+
Error.captureStackTrace(this, SecurityOpsError);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
toJSON() {
|
|
19
|
+
return {
|
|
20
|
+
name: this.name,
|
|
21
|
+
message: this.message,
|
|
22
|
+
context: this.context,
|
|
23
|
+
timestamp: this.timestamp
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
class SecurityScanError extends SecurityOpsError {
|
|
29
|
+
constructor(message, context = {}) {
|
|
30
|
+
super(message, context);
|
|
31
|
+
this.name = 'SecurityScanError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class SecurityProviderError extends SecurityOpsError {
|
|
36
|
+
constructor(message, context = {}) {
|
|
37
|
+
super(message, context);
|
|
38
|
+
this.name = 'SecurityProviderError';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class SecurityComplianceError extends SecurityOpsError {
|
|
43
|
+
constructor(message, context = {}) {
|
|
44
|
+
super(message, context);
|
|
45
|
+
this.name = 'SecurityComplianceError';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
class SecurityAuditError extends SecurityOpsError {
|
|
50
|
+
constructor(message, context = {}) {
|
|
51
|
+
super(message, context);
|
|
52
|
+
this.name = 'SecurityAuditError';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = {
|
|
57
|
+
SecurityOpsError,
|
|
58
|
+
SecurityScanError,
|
|
59
|
+
SecurityProviderError,
|
|
60
|
+
SecurityComplianceError,
|
|
61
|
+
SecurityAuditError
|
|
62
|
+
};
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Session Chain — Navigate linked sessions
|
|
5
|
+
*
|
|
6
|
+
* Provides chain navigation, visualization, and repair capabilities
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { SessionChainError } = require('./session-errors.cjs');
|
|
12
|
+
const { defaultLogger: logger } = require('./logger.cjs');
|
|
13
|
+
|
|
14
|
+
class SessionChain {
|
|
15
|
+
/**
|
|
16
|
+
* Create a SessionChain instance
|
|
17
|
+
* @param {Object} sessionManager - SessionManager instance
|
|
18
|
+
*/
|
|
19
|
+
constructor(sessionManager) {
|
|
20
|
+
this.sessionManager = sessionManager;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Navigate to adjacent session in chain
|
|
25
|
+
* @param {string} sessionId - Current session ID
|
|
26
|
+
* @param {string} direction - Navigation direction ('previous' or 'next')
|
|
27
|
+
* @returns {Object|null} Adjacent session or null
|
|
28
|
+
*/
|
|
29
|
+
navigate(sessionId, direction) {
|
|
30
|
+
const session = this.sessionManager.loadSession(sessionId);
|
|
31
|
+
if (!session) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const chain = session.metadata?.session_chain || [];
|
|
36
|
+
const currentIndex = chain.indexOf(sessionId);
|
|
37
|
+
|
|
38
|
+
if (currentIndex === -1) {
|
|
39
|
+
// Session not in chain, check if it's the last one
|
|
40
|
+
logger.warn('Session not in chain', { sessionId });
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (direction === 'previous') {
|
|
45
|
+
if (currentIndex > 0) {
|
|
46
|
+
const previousId = chain[currentIndex - 1];
|
|
47
|
+
return this.sessionManager.loadSession(previousId);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (direction === 'next') {
|
|
53
|
+
if (currentIndex < chain.length - 1) {
|
|
54
|
+
const nextId = chain[currentIndex + 1];
|
|
55
|
+
return this.sessionManager.loadSession(nextId);
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
throw new SessionChainError(`Invalid direction: ${direction}`, chain);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get full chain as array of session objects
|
|
65
|
+
* @param {string} sessionId - Session ID in the chain
|
|
66
|
+
* @returns {Array} Array of session objects
|
|
67
|
+
*/
|
|
68
|
+
getChain(sessionId) {
|
|
69
|
+
const session = this.sessionManager.loadSession(sessionId);
|
|
70
|
+
if (!session) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const chain = session.metadata?.session_chain || [];
|
|
75
|
+
const chainSessions = [];
|
|
76
|
+
|
|
77
|
+
for (const id of chain) {
|
|
78
|
+
const chainSession = this.sessionManager.loadSession(id);
|
|
79
|
+
if (chainSession) {
|
|
80
|
+
chainSessions.push(chainSession);
|
|
81
|
+
} else {
|
|
82
|
+
logger.warn('Missing session in chain', { id });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Include current session if not already in chain
|
|
87
|
+
if (!chain.includes(sessionId)) {
|
|
88
|
+
chainSessions.push(session);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return chainSessions;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get chain visualization string
|
|
96
|
+
* @param {string} sessionId - Session ID
|
|
97
|
+
* @returns {string} Formatted chain visualization
|
|
98
|
+
*/
|
|
99
|
+
getChainVisualization(sessionId) {
|
|
100
|
+
const session = this.sessionManager.loadSession(sessionId);
|
|
101
|
+
if (!session) {
|
|
102
|
+
return `Session not found: ${sessionId}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const chain = session.metadata?.session_chain || [];
|
|
106
|
+
const currentIndex = chain.indexOf(sessionId);
|
|
107
|
+
|
|
108
|
+
let viz = `Session Chain for ${sessionId}:\n\n`;
|
|
109
|
+
|
|
110
|
+
chain.forEach((id, index) => {
|
|
111
|
+
const chainSession = this.sessionManager.loadSession(id);
|
|
112
|
+
const startedAt = chainSession?.metadata?.started_at || 'Unknown';
|
|
113
|
+
const status = chainSession?.metadata?.status || 'unknown';
|
|
114
|
+
const marker = index === currentIndex ? ' <-- Current' : '';
|
|
115
|
+
viz += `[${index + 1}] ${id} (${startedAt}) - ${status}${marker}\n`;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (!chain.includes(sessionId)) {
|
|
119
|
+
const startedAt = session.metadata?.started_at || 'Unknown';
|
|
120
|
+
const status = session.metadata?.status || 'unknown';
|
|
121
|
+
viz += `[${chain.length + 1}] ${sessionId} (${startedAt}) - ${status} <-- Current\n`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
viz += `\nNavigation:\n`;
|
|
125
|
+
if (currentIndex > 0) {
|
|
126
|
+
viz += `- Previous: ${chain[currentIndex - 1]}\n`;
|
|
127
|
+
} else {
|
|
128
|
+
viz += `- Previous: none\n`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (currentIndex < chain.length - 1) {
|
|
132
|
+
viz += `- Next: ${chain[currentIndex + 1]}\n`;
|
|
133
|
+
} else {
|
|
134
|
+
viz += `- Next: none\n`;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return viz;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Repair broken chain links
|
|
142
|
+
* @param {string} sessionId - Session ID
|
|
143
|
+
* @returns {Object} Repair result with warnings
|
|
144
|
+
*/
|
|
145
|
+
repairChain(sessionId) {
|
|
146
|
+
const session = this.sessionManager.loadSession(sessionId);
|
|
147
|
+
if (!session) {
|
|
148
|
+
throw new SessionChainError(`Session not found: ${sessionId}`, []);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const chain = session.metadata?.session_chain || [];
|
|
152
|
+
const warnings = [];
|
|
153
|
+
const repaired = [];
|
|
154
|
+
|
|
155
|
+
// Get all available sessions
|
|
156
|
+
const allSessions = this.sessionManager.listSessions();
|
|
157
|
+
const availableIds = new Set(allSessions.map(s => s.session_id));
|
|
158
|
+
|
|
159
|
+
// Find missing links
|
|
160
|
+
const missingLinks = [];
|
|
161
|
+
for (const id of chain) {
|
|
162
|
+
if (!availableIds.has(id)) {
|
|
163
|
+
missingLinks.push(id);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (missingLinks.length === 0) {
|
|
168
|
+
return { repaired: false, warnings: ['Chain is intact'] };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Attempt to repair by finding closest timestamp match
|
|
172
|
+
for (const missingId of missingLinks) {
|
|
173
|
+
const match = this._findClosestSessionMatch(missingId, allSessions);
|
|
174
|
+
if (match) {
|
|
175
|
+
logger.info('Auto-repaired chain link', { missing: missingId, found: match.session_id });
|
|
176
|
+
repaired.push({ missing: missingId, found: match.session_id });
|
|
177
|
+
} else {
|
|
178
|
+
warnings.push(`Unrecoverable link: ${missingId}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Update chain with repaired links
|
|
183
|
+
if (repaired.length > 0) {
|
|
184
|
+
const newChain = chain.map(id => {
|
|
185
|
+
const repair = repaired.find(r => r.missing === id);
|
|
186
|
+
return repair ? repair.found : id;
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
this.sessionManager.updateSession(sessionId, {
|
|
190
|
+
metadata: { session_chain: newChain }
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
repaired: repaired.length > 0,
|
|
196
|
+
repairs: repaired,
|
|
197
|
+
warnings
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Find closest session match by timestamp
|
|
203
|
+
* @private
|
|
204
|
+
*/
|
|
205
|
+
_findClosestSessionMatch(missingId, allSessions) {
|
|
206
|
+
// Extract timestamp from missing ID
|
|
207
|
+
const timestampMatch = missingId.match(/session-(.+)/);
|
|
208
|
+
if (!timestampMatch) {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const missingTimestamp = timestampMatch[1];
|
|
213
|
+
|
|
214
|
+
// Find session with closest timestamp
|
|
215
|
+
let closestMatch = null;
|
|
216
|
+
let minDiff = Infinity;
|
|
217
|
+
|
|
218
|
+
for (const session of allSessions) {
|
|
219
|
+
const sessionTimestamp = session.session_id.replace('session-', '');
|
|
220
|
+
const diff = this._compareTimestamps(missingTimestamp, sessionTimestamp);
|
|
221
|
+
|
|
222
|
+
if (diff < minDiff) {
|
|
223
|
+
minDiff = diff;
|
|
224
|
+
closestMatch = session;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Only return match if within reasonable threshold (1 hour)
|
|
229
|
+
if (minDiff < 3600000) {
|
|
230
|
+
return closestMatch;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Compare timestamps and return difference in ms
|
|
238
|
+
* @private
|
|
239
|
+
*/
|
|
240
|
+
_compareTimestamps(ts1, ts2) {
|
|
241
|
+
try {
|
|
242
|
+
const date1 = new Date(ts1.replace(/-/g, ':').replace('T', ' '));
|
|
243
|
+
const date2 = new Date(ts2.replace(/-/g, ':').replace('T', ' '));
|
|
244
|
+
return Math.abs(date1 - date2);
|
|
245
|
+
} catch {
|
|
246
|
+
return Infinity;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Add session to chain
|
|
252
|
+
* @param {string} sessionId - Session ID to add to
|
|
253
|
+
* @param {string} linkedSessionId - Session ID to link
|
|
254
|
+
* @param {string} position - Position ('before' or 'after')
|
|
255
|
+
* @returns {boolean} Success
|
|
256
|
+
*/
|
|
257
|
+
addToChain(sessionId, linkedSessionId, position = 'after') {
|
|
258
|
+
const session = this.sessionManager.loadSession(sessionId);
|
|
259
|
+
if (!session) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const linkedSession = this.sessionManager.loadSession(linkedSessionId);
|
|
264
|
+
if (!linkedSession) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
let chain = session.metadata?.session_chain || [];
|
|
269
|
+
|
|
270
|
+
// Ensure current session is in chain
|
|
271
|
+
if (!chain.includes(sessionId)) {
|
|
272
|
+
chain.push(sessionId);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const currentIndex = chain.indexOf(sessionId);
|
|
276
|
+
|
|
277
|
+
if (position === 'after') {
|
|
278
|
+
// Insert after current
|
|
279
|
+
chain.splice(currentIndex + 1, 0, linkedSessionId);
|
|
280
|
+
} else if (position === 'before') {
|
|
281
|
+
// Insert before current
|
|
282
|
+
chain.splice(currentIndex, 0, linkedSessionId);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Update both sessions
|
|
286
|
+
this.sessionManager.updateSession(sessionId, {
|
|
287
|
+
metadata: { session_chain: chain }
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Also update linked session's chain
|
|
291
|
+
const linkedChain = linkedSession.metadata?.session_chain || [];
|
|
292
|
+
if (!linkedChain.includes(sessionId)) {
|
|
293
|
+
linkedChain.push(sessionId);
|
|
294
|
+
this.sessionManager.updateSession(linkedSessionId, {
|
|
295
|
+
metadata: { session_chain: linkedChain }
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
logger.info('Session added to chain', { sessionId, linkedSessionId, position });
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
module.exports = SessionChain;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Session Error Classes
|
|
5
|
+
*
|
|
6
|
+
* Provides structured error handling for session operations
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
class SessionError extends Error {
|
|
10
|
+
constructor(message, options = {}) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'SessionError';
|
|
13
|
+
this.code = options.code || 'SESSION_ERROR';
|
|
14
|
+
this.details = options.details || {};
|
|
15
|
+
this.timestamp = new Date().toISOString();
|
|
16
|
+
Error.captureStackTrace(this, SessionError);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
toJSON() {
|
|
20
|
+
return {
|
|
21
|
+
name: this.name,
|
|
22
|
+
code: this.code,
|
|
23
|
+
message: this.message,
|
|
24
|
+
details: this.details,
|
|
25
|
+
timestamp: this.timestamp
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class SessionNotFoundError extends SessionError {
|
|
31
|
+
constructor(sessionId, options = {}) {
|
|
32
|
+
super(`Session '${sessionId}' not found`, {
|
|
33
|
+
code: 'SESSION_NOT_FOUND',
|
|
34
|
+
details: { sessionId, ...options.details }
|
|
35
|
+
});
|
|
36
|
+
this.name = 'SessionNotFoundError';
|
|
37
|
+
this.sessionId = sessionId;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class SessionChainError extends SessionError {
|
|
42
|
+
constructor(message, chain = [], options = {}) {
|
|
43
|
+
super(message, {
|
|
44
|
+
code: 'SESSION_CHAIN_ERROR',
|
|
45
|
+
details: { chain, ...options.details }
|
|
46
|
+
});
|
|
47
|
+
this.name = 'SessionChainError';
|
|
48
|
+
this.chain = chain;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class SessionExportError extends SessionError {
|
|
53
|
+
constructor(format, reason, options = {}) {
|
|
54
|
+
super(`Export failed for format '${format}': ${reason}`, {
|
|
55
|
+
code: 'SESSION_EXPORT_ERROR',
|
|
56
|
+
details: { format, reason, ...options.details }
|
|
57
|
+
});
|
|
58
|
+
this.name = 'SessionExportError';
|
|
59
|
+
this.format = format;
|
|
60
|
+
this.reason = reason;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class SessionImportError extends SessionError {
|
|
65
|
+
constructor(message, validationErrors = [], options = {}) {
|
|
66
|
+
super(message, {
|
|
67
|
+
code: 'SESSION_IMPORT_ERROR',
|
|
68
|
+
details: { validationErrors, ...options.details }
|
|
69
|
+
});
|
|
70
|
+
this.name = 'SessionImportError';
|
|
71
|
+
this.validationErrors = validationErrors;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
SessionError,
|
|
77
|
+
SessionNotFoundError,
|
|
78
|
+
SessionChainError,
|
|
79
|
+
SessionExportError,
|
|
80
|
+
SessionImportError
|
|
81
|
+
};
|