tapps-agents 3.5.40__py3-none-any.whl → 3.6.0__py3-none-any.whl
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.
- tapps_agents/__init__.py +2 -2
- tapps_agents/agents/__init__.py +22 -22
- tapps_agents/agents/analyst/__init__.py +5 -5
- tapps_agents/agents/architect/__init__.py +5 -5
- tapps_agents/agents/architect/agent.py +1033 -1033
- tapps_agents/agents/architect/pattern_detector.py +75 -75
- tapps_agents/agents/cleanup/__init__.py +7 -7
- tapps_agents/agents/cleanup/agent.py +445 -445
- tapps_agents/agents/debugger/__init__.py +7 -7
- tapps_agents/agents/debugger/agent.py +310 -310
- tapps_agents/agents/debugger/error_analyzer.py +437 -437
- tapps_agents/agents/designer/__init__.py +5 -5
- tapps_agents/agents/designer/agent.py +786 -786
- tapps_agents/agents/designer/visual_designer.py +638 -638
- tapps_agents/agents/documenter/__init__.py +7 -7
- tapps_agents/agents/documenter/agent.py +531 -531
- tapps_agents/agents/documenter/doc_generator.py +472 -472
- tapps_agents/agents/documenter/doc_validator.py +393 -393
- tapps_agents/agents/documenter/framework_doc_updater.py +493 -493
- tapps_agents/agents/enhancer/__init__.py +7 -7
- tapps_agents/agents/evaluator/__init__.py +7 -7
- tapps_agents/agents/evaluator/agent.py +443 -443
- tapps_agents/agents/evaluator/priority_evaluator.py +641 -641
- tapps_agents/agents/evaluator/quality_analyzer.py +147 -147
- tapps_agents/agents/evaluator/report_generator.py +344 -344
- tapps_agents/agents/evaluator/usage_analyzer.py +192 -192
- tapps_agents/agents/evaluator/workflow_analyzer.py +189 -189
- tapps_agents/agents/implementer/__init__.py +7 -7
- tapps_agents/agents/implementer/agent.py +798 -798
- tapps_agents/agents/implementer/auto_fix.py +1119 -1119
- tapps_agents/agents/implementer/code_generator.py +73 -73
- tapps_agents/agents/improver/__init__.py +1 -1
- tapps_agents/agents/improver/agent.py +753 -753
- tapps_agents/agents/ops/__init__.py +1 -1
- tapps_agents/agents/ops/agent.py +619 -619
- tapps_agents/agents/ops/dependency_analyzer.py +600 -600
- tapps_agents/agents/orchestrator/__init__.py +5 -5
- tapps_agents/agents/orchestrator/agent.py +522 -522
- tapps_agents/agents/planner/__init__.py +7 -7
- tapps_agents/agents/planner/agent.py +1127 -1127
- tapps_agents/agents/reviewer/__init__.py +24 -24
- tapps_agents/agents/reviewer/agent.py +3513 -3513
- tapps_agents/agents/reviewer/aggregator.py +213 -213
- tapps_agents/agents/reviewer/batch_review.py +448 -448
- tapps_agents/agents/reviewer/cache.py +443 -443
- tapps_agents/agents/reviewer/context7_enhancer.py +630 -630
- tapps_agents/agents/reviewer/context_detector.py +203 -203
- tapps_agents/agents/reviewer/docker_compose_validator.py +158 -158
- tapps_agents/agents/reviewer/dockerfile_validator.py +176 -176
- tapps_agents/agents/reviewer/error_handling.py +126 -126
- tapps_agents/agents/reviewer/feedback_generator.py +490 -490
- tapps_agents/agents/reviewer/influxdb_validator.py +316 -316
- tapps_agents/agents/reviewer/issue_tracking.py +169 -169
- tapps_agents/agents/reviewer/library_detector.py +295 -295
- tapps_agents/agents/reviewer/library_patterns.py +268 -268
- tapps_agents/agents/reviewer/maintainability_scorer.py +593 -593
- tapps_agents/agents/reviewer/metric_strategies.py +276 -276
- tapps_agents/agents/reviewer/mqtt_validator.py +160 -160
- tapps_agents/agents/reviewer/output_enhancer.py +105 -105
- tapps_agents/agents/reviewer/pattern_detector.py +241 -241
- tapps_agents/agents/reviewer/performance_scorer.py +357 -357
- tapps_agents/agents/reviewer/phased_review.py +516 -516
- tapps_agents/agents/reviewer/progressive_review.py +435 -435
- tapps_agents/agents/reviewer/react_scorer.py +331 -331
- tapps_agents/agents/reviewer/score_constants.py +228 -228
- tapps_agents/agents/reviewer/score_validator.py +507 -507
- tapps_agents/agents/reviewer/scorer_registry.py +373 -373
- tapps_agents/agents/reviewer/scoring.py +1566 -1566
- tapps_agents/agents/reviewer/service_discovery.py +534 -534
- tapps_agents/agents/reviewer/tools/__init__.py +41 -41
- tapps_agents/agents/reviewer/tools/parallel_executor.py +581 -581
- tapps_agents/agents/reviewer/tools/ruff_grouping.py +250 -250
- tapps_agents/agents/reviewer/tools/scoped_mypy.py +284 -284
- tapps_agents/agents/reviewer/typescript_scorer.py +1142 -1142
- tapps_agents/agents/reviewer/validation.py +208 -208
- tapps_agents/agents/reviewer/websocket_validator.py +132 -132
- tapps_agents/agents/tester/__init__.py +7 -7
- tapps_agents/agents/tester/accessibility_auditor.py +309 -309
- tapps_agents/agents/tester/agent.py +1080 -1080
- tapps_agents/agents/tester/batch_generator.py +54 -54
- tapps_agents/agents/tester/context_learner.py +51 -51
- tapps_agents/agents/tester/coverage_analyzer.py +386 -386
- tapps_agents/agents/tester/coverage_test_generator.py +290 -290
- tapps_agents/agents/tester/debug_enhancer.py +238 -238
- tapps_agents/agents/tester/device_emulator.py +241 -241
- tapps_agents/agents/tester/integration_generator.py +62 -62
- tapps_agents/agents/tester/network_recorder.py +300 -300
- tapps_agents/agents/tester/performance_monitor.py +320 -320
- tapps_agents/agents/tester/test_fixer.py +316 -316
- tapps_agents/agents/tester/test_generator.py +632 -632
- tapps_agents/agents/tester/trace_manager.py +234 -234
- tapps_agents/agents/tester/visual_regression.py +291 -291
- tapps_agents/analysis/pattern_detector.py +36 -36
- tapps_agents/beads/hydration.py +213 -213
- tapps_agents/beads/parse.py +32 -32
- tapps_agents/beads/specs.py +206 -206
- tapps_agents/cli/__init__.py +9 -9
- tapps_agents/cli/__main__.py +8 -8
- tapps_agents/cli/base.py +478 -478
- tapps_agents/cli/command_classifier.py +72 -72
- tapps_agents/cli/commands/__init__.py +2 -2
- tapps_agents/cli/commands/analyst.py +173 -173
- tapps_agents/cli/commands/architect.py +109 -109
- tapps_agents/cli/commands/cleanup_agent.py +92 -92
- tapps_agents/cli/commands/common.py +126 -126
- tapps_agents/cli/commands/debugger.py +90 -90
- tapps_agents/cli/commands/designer.py +112 -112
- tapps_agents/cli/commands/documenter.py +136 -136
- tapps_agents/cli/commands/enhancer.py +110 -110
- tapps_agents/cli/commands/evaluator.py +255 -255
- tapps_agents/cli/commands/health.py +665 -665
- tapps_agents/cli/commands/implementer.py +301 -301
- tapps_agents/cli/commands/improver.py +91 -91
- tapps_agents/cli/commands/knowledge.py +111 -111
- tapps_agents/cli/commands/learning.py +172 -172
- tapps_agents/cli/commands/observability.py +283 -283
- tapps_agents/cli/commands/ops.py +135 -135
- tapps_agents/cli/commands/orchestrator.py +116 -116
- tapps_agents/cli/commands/planner.py +237 -237
- tapps_agents/cli/commands/reviewer.py +1872 -1872
- tapps_agents/cli/commands/status.py +285 -285
- tapps_agents/cli/commands/task.py +227 -219
- tapps_agents/cli/commands/tester.py +191 -191
- tapps_agents/cli/commands/top_level.py +3586 -3586
- tapps_agents/cli/feedback.py +936 -936
- tapps_agents/cli/formatters.py +608 -608
- tapps_agents/cli/help/__init__.py +7 -7
- tapps_agents/cli/help/static_help.py +425 -425
- tapps_agents/cli/network_detection.py +110 -110
- tapps_agents/cli/output_compactor.py +274 -274
- tapps_agents/cli/parsers/__init__.py +2 -2
- tapps_agents/cli/parsers/analyst.py +186 -186
- tapps_agents/cli/parsers/architect.py +167 -167
- tapps_agents/cli/parsers/cleanup_agent.py +228 -228
- tapps_agents/cli/parsers/debugger.py +116 -116
- tapps_agents/cli/parsers/designer.py +182 -182
- tapps_agents/cli/parsers/documenter.py +134 -134
- tapps_agents/cli/parsers/enhancer.py +113 -113
- tapps_agents/cli/parsers/evaluator.py +213 -213
- tapps_agents/cli/parsers/implementer.py +168 -168
- tapps_agents/cli/parsers/improver.py +132 -132
- tapps_agents/cli/parsers/ops.py +159 -159
- tapps_agents/cli/parsers/orchestrator.py +98 -98
- tapps_agents/cli/parsers/planner.py +145 -145
- tapps_agents/cli/parsers/reviewer.py +462 -462
- tapps_agents/cli/parsers/tester.py +124 -124
- tapps_agents/cli/progress_heartbeat.py +254 -254
- tapps_agents/cli/streaming_progress.py +336 -336
- tapps_agents/cli/utils/__init__.py +6 -6
- tapps_agents/cli/utils/agent_lifecycle.py +48 -48
- tapps_agents/cli/utils/error_formatter.py +82 -82
- tapps_agents/cli/utils/error_recovery.py +188 -188
- tapps_agents/cli/utils/output_handler.py +59 -59
- tapps_agents/cli/utils/prompt_enhancer.py +319 -319
- tapps_agents/cli/validators/__init__.py +9 -9
- tapps_agents/cli/validators/command_validator.py +81 -81
- tapps_agents/context7/__init__.py +112 -112
- tapps_agents/context7/agent_integration.py +869 -869
- tapps_agents/context7/analytics.py +382 -382
- tapps_agents/context7/analytics_dashboard.py +299 -299
- tapps_agents/context7/async_cache.py +681 -681
- tapps_agents/context7/backup_client.py +958 -958
- tapps_agents/context7/cache_locking.py +194 -194
- tapps_agents/context7/cache_metadata.py +214 -214
- tapps_agents/context7/cache_prewarm.py +488 -488
- tapps_agents/context7/cache_structure.py +168 -168
- tapps_agents/context7/cache_warming.py +604 -604
- tapps_agents/context7/circuit_breaker.py +376 -376
- tapps_agents/context7/cleanup.py +461 -461
- tapps_agents/context7/commands.py +858 -858
- tapps_agents/context7/credential_validation.py +276 -276
- tapps_agents/context7/cross_reference_resolver.py +168 -168
- tapps_agents/context7/cross_references.py +424 -424
- tapps_agents/context7/doc_manager.py +225 -225
- tapps_agents/context7/fuzzy_matcher.py +369 -369
- tapps_agents/context7/kb_cache.py +404 -404
- tapps_agents/context7/language_detector.py +219 -219
- tapps_agents/context7/library_detector.py +725 -725
- tapps_agents/context7/lookup.py +738 -738
- tapps_agents/context7/metadata.py +258 -258
- tapps_agents/context7/refresh_queue.py +300 -300
- tapps_agents/context7/security.py +373 -373
- tapps_agents/context7/staleness_policies.py +278 -278
- tapps_agents/context7/tiles_integration.py +47 -47
- tapps_agents/continuous_bug_fix/__init__.py +20 -20
- tapps_agents/continuous_bug_fix/bug_finder.py +306 -306
- tapps_agents/continuous_bug_fix/bug_fix_coordinator.py +177 -177
- tapps_agents/continuous_bug_fix/commit_manager.py +178 -178
- tapps_agents/continuous_bug_fix/continuous_bug_fixer.py +322 -322
- tapps_agents/continuous_bug_fix/proactive_bug_finder.py +285 -285
- tapps_agents/core/__init__.py +298 -298
- tapps_agents/core/adaptive_cache_config.py +432 -432
- tapps_agents/core/agent_base.py +647 -647
- tapps_agents/core/agent_cache.py +466 -466
- tapps_agents/core/agent_learning.py +1865 -1865
- tapps_agents/core/analytics_dashboard.py +563 -563
- tapps_agents/core/analytics_enhancements.py +597 -597
- tapps_agents/core/anonymization.py +274 -274
- tapps_agents/core/artifact_context_builder.py +293 -0
- tapps_agents/core/ast_parser.py +228 -228
- tapps_agents/core/async_file_ops.py +402 -402
- tapps_agents/core/best_practice_consultant.py +299 -299
- tapps_agents/core/brownfield_analyzer.py +299 -299
- tapps_agents/core/brownfield_review.py +541 -541
- tapps_agents/core/browser_controller.py +513 -513
- tapps_agents/core/capability_registry.py +418 -418
- tapps_agents/core/change_impact_analyzer.py +190 -190
- tapps_agents/core/checkpoint_manager.py +377 -377
- tapps_agents/core/code_generator.py +329 -329
- tapps_agents/core/code_validator.py +276 -276
- tapps_agents/core/command_registry.py +327 -327
- tapps_agents/core/config.py +33 -0
- tapps_agents/core/context_gathering/__init__.py +2 -2
- tapps_agents/core/context_gathering/repository_explorer.py +28 -28
- tapps_agents/core/context_intelligence/__init__.py +2 -2
- tapps_agents/core/context_intelligence/relevance_scorer.py +24 -24
- tapps_agents/core/context_intelligence/token_budget_manager.py +27 -27
- tapps_agents/core/context_manager.py +240 -240
- tapps_agents/core/cursor_feedback_monitor.py +146 -146
- tapps_agents/core/cursor_verification.py +290 -290
- tapps_agents/core/customization_loader.py +280 -280
- tapps_agents/core/customization_schema.py +260 -260
- tapps_agents/core/customization_template.py +238 -238
- tapps_agents/core/debug_logger.py +124 -124
- tapps_agents/core/design_validator.py +298 -298
- tapps_agents/core/diagram_generator.py +226 -226
- tapps_agents/core/docker_utils.py +232 -232
- tapps_agents/core/document_generator.py +617 -617
- tapps_agents/core/domain_detector.py +30 -30
- tapps_agents/core/error_envelope.py +454 -454
- tapps_agents/core/error_handler.py +270 -270
- tapps_agents/core/estimation_tracker.py +189 -189
- tapps_agents/core/eval_prompt_engine.py +116 -116
- tapps_agents/core/evaluation_base.py +119 -119
- tapps_agents/core/evaluation_models.py +320 -320
- tapps_agents/core/evaluation_orchestrator.py +225 -225
- tapps_agents/core/evaluators/__init__.py +7 -7
- tapps_agents/core/evaluators/architectural_evaluator.py +205 -205
- tapps_agents/core/evaluators/behavioral_evaluator.py +160 -160
- tapps_agents/core/evaluators/performance_profile_evaluator.py +160 -160
- tapps_agents/core/evaluators/security_posture_evaluator.py +148 -148
- tapps_agents/core/evaluators/spec_compliance_evaluator.py +181 -181
- tapps_agents/core/exceptions.py +107 -107
- tapps_agents/core/expert_config_generator.py +293 -293
- tapps_agents/core/export_schema.py +202 -202
- tapps_agents/core/external_feedback_models.py +102 -102
- tapps_agents/core/external_feedback_storage.py +213 -213
- tapps_agents/core/fallback_strategy.py +314 -314
- tapps_agents/core/feedback_analyzer.py +162 -162
- tapps_agents/core/feedback_collector.py +178 -178
- tapps_agents/core/git_operations.py +445 -445
- tapps_agents/core/hardware_profiler.py +151 -151
- tapps_agents/core/instructions.py +324 -324
- tapps_agents/core/io_guardrails.py +69 -69
- tapps_agents/core/issue_manifest.py +249 -249
- tapps_agents/core/issue_schema.py +139 -139
- tapps_agents/core/json_utils.py +128 -128
- tapps_agents/core/knowledge_graph.py +446 -446
- tapps_agents/core/language_detector.py +296 -296
- tapps_agents/core/learning_confidence.py +242 -242
- tapps_agents/core/learning_dashboard.py +246 -246
- tapps_agents/core/learning_decision.py +384 -384
- tapps_agents/core/learning_explainability.py +578 -578
- tapps_agents/core/learning_export.py +287 -287
- tapps_agents/core/learning_integration.py +228 -228
- tapps_agents/core/llm_behavior.py +232 -232
- tapps_agents/core/long_duration_support.py +786 -786
- tapps_agents/core/mcp_setup.py +106 -106
- tapps_agents/core/memory_integration.py +396 -396
- tapps_agents/core/meta_learning.py +666 -666
- tapps_agents/core/module_path_sanitizer.py +199 -199
- tapps_agents/core/multi_agent_orchestrator.py +382 -382
- tapps_agents/core/network_errors.py +125 -125
- tapps_agents/core/nfr_validator.py +336 -336
- tapps_agents/core/offline_mode.py +158 -158
- tapps_agents/core/output_contracts.py +300 -300
- tapps_agents/core/output_formatter.py +300 -300
- tapps_agents/core/path_normalizer.py +174 -174
- tapps_agents/core/path_validator.py +322 -322
- tapps_agents/core/pattern_library.py +250 -250
- tapps_agents/core/performance_benchmark.py +301 -301
- tapps_agents/core/performance_monitor.py +184 -184
- tapps_agents/core/playwright_mcp_controller.py +771 -771
- tapps_agents/core/policy_loader.py +135 -135
- tapps_agents/core/progress.py +166 -166
- tapps_agents/core/project_profile.py +354 -354
- tapps_agents/core/project_type_detector.py +454 -454
- tapps_agents/core/prompt_base.py +223 -223
- tapps_agents/core/prompt_learning/__init__.py +2 -2
- tapps_agents/core/prompt_learning/learning_loop.py +24 -24
- tapps_agents/core/prompt_learning/project_prompt_store.py +25 -25
- tapps_agents/core/prompt_learning/skills_prompt_analyzer.py +35 -35
- tapps_agents/core/prompt_optimization/__init__.py +6 -6
- tapps_agents/core/prompt_optimization/ab_tester.py +114 -114
- tapps_agents/core/prompt_optimization/correlation_analyzer.py +160 -160
- tapps_agents/core/prompt_optimization/progressive_refiner.py +129 -129
- tapps_agents/core/prompt_optimization/prompt_library.py +37 -37
- tapps_agents/core/requirements_evaluator.py +431 -431
- tapps_agents/core/resource_aware_executor.py +449 -449
- tapps_agents/core/resource_monitor.py +343 -343
- tapps_agents/core/resume_handler.py +298 -298
- tapps_agents/core/retry_handler.py +197 -197
- tapps_agents/core/review_checklists.py +479 -479
- tapps_agents/core/role_loader.py +201 -201
- tapps_agents/core/role_template_loader.py +201 -201
- tapps_agents/core/runtime_mode.py +60 -60
- tapps_agents/core/security_scanner.py +342 -342
- tapps_agents/core/skill_agent_registry.py +194 -194
- tapps_agents/core/skill_integration.py +208 -208
- tapps_agents/core/skill_loader.py +492 -492
- tapps_agents/core/skill_template.py +341 -341
- tapps_agents/core/skill_validator.py +478 -478
- tapps_agents/core/stack_analyzer.py +35 -35
- tapps_agents/core/startup.py +174 -174
- tapps_agents/core/storage_manager.py +397 -397
- tapps_agents/core/storage_models.py +166 -166
- tapps_agents/core/story_evaluator.py +410 -410
- tapps_agents/core/subprocess_utils.py +170 -170
- tapps_agents/core/task_duration.py +296 -296
- tapps_agents/core/task_memory.py +582 -582
- tapps_agents/core/task_state.py +226 -226
- tapps_agents/core/tech_stack_priorities.py +208 -208
- tapps_agents/core/temp_directory.py +194 -194
- tapps_agents/core/template_merger.py +600 -600
- tapps_agents/core/template_selector.py +280 -280
- tapps_agents/core/test_generator.py +286 -286
- tapps_agents/core/tiered_context.py +253 -253
- tapps_agents/core/token_monitor.py +345 -345
- tapps_agents/core/traceability.py +254 -254
- tapps_agents/core/trajectory_tracker.py +50 -50
- tapps_agents/core/unicode_safe.py +143 -143
- tapps_agents/core/unified_cache_config.py +170 -170
- tapps_agents/core/unified_state.py +324 -324
- tapps_agents/core/validate_cursor_setup.py +237 -237
- tapps_agents/core/validation_registry.py +136 -136
- tapps_agents/core/validators/__init__.py +4 -4
- tapps_agents/core/validators/python_validator.py +87 -87
- tapps_agents/core/verification_agent.py +90 -90
- tapps_agents/core/visual_feedback.py +644 -644
- tapps_agents/core/workflow_validator.py +197 -197
- tapps_agents/core/worktree.py +367 -367
- tapps_agents/docker/__init__.py +10 -10
- tapps_agents/docker/analyzer.py +186 -186
- tapps_agents/docker/debugger.py +229 -229
- tapps_agents/docker/error_patterns.py +216 -216
- tapps_agents/epic/__init__.py +22 -22
- tapps_agents/epic/beads_sync.py +115 -115
- tapps_agents/epic/markdown_sync.py +105 -105
- tapps_agents/epic/models.py +96 -96
- tapps_agents/experts/__init__.py +163 -163
- tapps_agents/experts/agent_integration.py +243 -243
- tapps_agents/experts/auto_generator.py +331 -331
- tapps_agents/experts/base_expert.py +536 -536
- tapps_agents/experts/builtin_registry.py +261 -261
- tapps_agents/experts/business_metrics.py +565 -565
- tapps_agents/experts/cache.py +266 -266
- tapps_agents/experts/confidence_breakdown.py +306 -306
- tapps_agents/experts/confidence_calculator.py +336 -336
- tapps_agents/experts/confidence_metrics.py +236 -236
- tapps_agents/experts/domain_config.py +311 -311
- tapps_agents/experts/domain_detector.py +550 -550
- tapps_agents/experts/domain_utils.py +84 -84
- tapps_agents/experts/expert_config.py +113 -113
- tapps_agents/experts/expert_engine.py +465 -465
- tapps_agents/experts/expert_registry.py +744 -744
- tapps_agents/experts/expert_synthesizer.py +70 -70
- tapps_agents/experts/governance.py +197 -197
- tapps_agents/experts/history_logger.py +312 -312
- tapps_agents/experts/knowledge/README.md +180 -180
- tapps_agents/experts/knowledge/accessibility/accessible-forms.md +331 -331
- tapps_agents/experts/knowledge/accessibility/aria-patterns.md +344 -344
- tapps_agents/experts/knowledge/accessibility/color-contrast.md +285 -285
- tapps_agents/experts/knowledge/accessibility/keyboard-navigation.md +332 -332
- tapps_agents/experts/knowledge/accessibility/screen-readers.md +282 -282
- tapps_agents/experts/knowledge/accessibility/semantic-html.md +355 -355
- tapps_agents/experts/knowledge/accessibility/testing-accessibility.md +369 -369
- tapps_agents/experts/knowledge/accessibility/wcag-2.1.md +296 -296
- tapps_agents/experts/knowledge/accessibility/wcag-2.2.md +211 -211
- tapps_agents/experts/knowledge/agent-learning/best-practices.md +715 -715
- tapps_agents/experts/knowledge/agent-learning/pattern-extraction.md +282 -282
- tapps_agents/experts/knowledge/agent-learning/prompt-optimization.md +320 -320
- tapps_agents/experts/knowledge/ai-frameworks/model-optimization.md +90 -90
- tapps_agents/experts/knowledge/ai-frameworks/openvino-patterns.md +260 -260
- tapps_agents/experts/knowledge/api-design-integration/api-gateway-patterns.md +309 -309
- tapps_agents/experts/knowledge/api-design-integration/api-security-patterns.md +521 -521
- tapps_agents/experts/knowledge/api-design-integration/api-versioning.md +421 -421
- tapps_agents/experts/knowledge/api-design-integration/async-protocol-patterns.md +61 -61
- tapps_agents/experts/knowledge/api-design-integration/contract-testing.md +221 -221
- tapps_agents/experts/knowledge/api-design-integration/external-api-integration.md +489 -489
- tapps_agents/experts/knowledge/api-design-integration/fastapi-patterns.md +360 -360
- tapps_agents/experts/knowledge/api-design-integration/fastapi-testing.md +262 -262
- tapps_agents/experts/knowledge/api-design-integration/graphql-patterns.md +582 -582
- tapps_agents/experts/knowledge/api-design-integration/grpc-best-practices.md +499 -499
- tapps_agents/experts/knowledge/api-design-integration/mqtt-patterns.md +455 -455
- tapps_agents/experts/knowledge/api-design-integration/rate-limiting.md +507 -507
- tapps_agents/experts/knowledge/api-design-integration/restful-api-design.md +618 -618
- tapps_agents/experts/knowledge/api-design-integration/websocket-patterns.md +480 -480
- tapps_agents/experts/knowledge/cloud-infrastructure/cloud-native-patterns.md +175 -175
- tapps_agents/experts/knowledge/cloud-infrastructure/container-health-checks.md +261 -261
- tapps_agents/experts/knowledge/cloud-infrastructure/containerization.md +222 -222
- tapps_agents/experts/knowledge/cloud-infrastructure/cost-optimization.md +122 -122
- tapps_agents/experts/knowledge/cloud-infrastructure/disaster-recovery.md +153 -153
- tapps_agents/experts/knowledge/cloud-infrastructure/dockerfile-patterns.md +285 -285
- tapps_agents/experts/knowledge/cloud-infrastructure/infrastructure-as-code.md +187 -187
- tapps_agents/experts/knowledge/cloud-infrastructure/kubernetes-patterns.md +253 -253
- tapps_agents/experts/knowledge/cloud-infrastructure/multi-cloud-strategies.md +155 -155
- tapps_agents/experts/knowledge/cloud-infrastructure/serverless-architecture.md +200 -200
- tapps_agents/experts/knowledge/code-quality-analysis/README.md +16 -16
- tapps_agents/experts/knowledge/code-quality-analysis/code-metrics.md +137 -137
- tapps_agents/experts/knowledge/code-quality-analysis/complexity-analysis.md +181 -181
- tapps_agents/experts/knowledge/code-quality-analysis/technical-debt-patterns.md +191 -191
- tapps_agents/experts/knowledge/data-privacy-compliance/anonymization.md +313 -313
- tapps_agents/experts/knowledge/data-privacy-compliance/ccpa.md +255 -255
- tapps_agents/experts/knowledge/data-privacy-compliance/consent-management.md +282 -282
- tapps_agents/experts/knowledge/data-privacy-compliance/data-minimization.md +275 -275
- tapps_agents/experts/knowledge/data-privacy-compliance/data-retention.md +297 -297
- tapps_agents/experts/knowledge/data-privacy-compliance/data-subject-rights.md +383 -383
- tapps_agents/experts/knowledge/data-privacy-compliance/encryption-privacy.md +285 -285
- tapps_agents/experts/knowledge/data-privacy-compliance/gdpr.md +344 -344
- tapps_agents/experts/knowledge/data-privacy-compliance/hipaa.md +385 -385
- tapps_agents/experts/knowledge/data-privacy-compliance/privacy-by-design.md +280 -280
- tapps_agents/experts/knowledge/database-data-management/acid-vs-cap.md +164 -164
- tapps_agents/experts/knowledge/database-data-management/backup-and-recovery.md +182 -182
- tapps_agents/experts/knowledge/database-data-management/data-modeling.md +172 -172
- tapps_agents/experts/knowledge/database-data-management/database-design.md +187 -187
- tapps_agents/experts/knowledge/database-data-management/flux-query-optimization.md +342 -342
- tapps_agents/experts/knowledge/database-data-management/influxdb-connection-patterns.md +432 -432
- tapps_agents/experts/knowledge/database-data-management/influxdb-patterns.md +442 -442
- tapps_agents/experts/knowledge/database-data-management/migration-strategies.md +216 -216
- tapps_agents/experts/knowledge/database-data-management/nosql-patterns.md +259 -259
- tapps_agents/experts/knowledge/database-data-management/scalability-patterns.md +184 -184
- tapps_agents/experts/knowledge/database-data-management/sql-optimization.md +175 -175
- tapps_agents/experts/knowledge/database-data-management/time-series-modeling.md +444 -444
- tapps_agents/experts/knowledge/development-workflow/README.md +16 -16
- tapps_agents/experts/knowledge/development-workflow/automation-best-practices.md +216 -216
- tapps_agents/experts/knowledge/development-workflow/build-strategies.md +198 -198
- tapps_agents/experts/knowledge/development-workflow/deployment-patterns.md +205 -205
- tapps_agents/experts/knowledge/development-workflow/git-workflows.md +205 -205
- tapps_agents/experts/knowledge/documentation-knowledge-management/README.md +16 -16
- tapps_agents/experts/knowledge/documentation-knowledge-management/api-documentation-patterns.md +231 -231
- tapps_agents/experts/knowledge/documentation-knowledge-management/documentation-standards.md +191 -191
- tapps_agents/experts/knowledge/documentation-knowledge-management/knowledge-management.md +171 -171
- tapps_agents/experts/knowledge/documentation-knowledge-management/technical-writing-guide.md +192 -192
- tapps_agents/experts/knowledge/observability-monitoring/alerting-patterns.md +461 -461
- tapps_agents/experts/knowledge/observability-monitoring/apm-tools.md +459 -459
- tapps_agents/experts/knowledge/observability-monitoring/distributed-tracing.md +367 -367
- tapps_agents/experts/knowledge/observability-monitoring/logging-strategies.md +478 -478
- tapps_agents/experts/knowledge/observability-monitoring/metrics-and-monitoring.md +510 -510
- tapps_agents/experts/knowledge/observability-monitoring/observability-best-practices.md +492 -492
- tapps_agents/experts/knowledge/observability-monitoring/open-telemetry.md +573 -573
- tapps_agents/experts/knowledge/observability-monitoring/slo-sli-sla.md +419 -419
- tapps_agents/experts/knowledge/performance/anti-patterns.md +284 -284
- tapps_agents/experts/knowledge/performance/api-performance.md +256 -256
- tapps_agents/experts/knowledge/performance/caching.md +327 -327
- tapps_agents/experts/knowledge/performance/database-performance.md +252 -252
- tapps_agents/experts/knowledge/performance/optimization-patterns.md +327 -327
- tapps_agents/experts/knowledge/performance/profiling.md +297 -297
- tapps_agents/experts/knowledge/performance/resource-management.md +293 -293
- tapps_agents/experts/knowledge/performance/scalability.md +306 -306
- tapps_agents/experts/knowledge/security/owasp-top10.md +209 -209
- tapps_agents/experts/knowledge/security/secure-coding-practices.md +207 -207
- tapps_agents/experts/knowledge/security/threat-modeling.md +220 -220
- tapps_agents/experts/knowledge/security/vulnerability-patterns.md +342 -342
- tapps_agents/experts/knowledge/software-architecture/docker-compose-patterns.md +314 -314
- tapps_agents/experts/knowledge/software-architecture/microservices-patterns.md +379 -379
- tapps_agents/experts/knowledge/software-architecture/service-communication.md +316 -316
- tapps_agents/experts/knowledge/testing/best-practices.md +310 -310
- tapps_agents/experts/knowledge/testing/coverage-analysis.md +293 -293
- tapps_agents/experts/knowledge/testing/mocking.md +256 -256
- tapps_agents/experts/knowledge/testing/test-automation.md +276 -276
- tapps_agents/experts/knowledge/testing/test-data.md +271 -271
- tapps_agents/experts/knowledge/testing/test-design-patterns.md +280 -280
- tapps_agents/experts/knowledge/testing/test-maintenance.md +236 -236
- tapps_agents/experts/knowledge/testing/test-strategies.md +311 -311
- tapps_agents/experts/knowledge/user-experience/information-architecture.md +325 -325
- tapps_agents/experts/knowledge/user-experience/interaction-design.md +363 -363
- tapps_agents/experts/knowledge/user-experience/prototyping.md +293 -293
- tapps_agents/experts/knowledge/user-experience/usability-heuristics.md +337 -337
- tapps_agents/experts/knowledge/user-experience/usability-testing.md +311 -311
- tapps_agents/experts/knowledge/user-experience/user-journeys.md +296 -296
- tapps_agents/experts/knowledge/user-experience/user-research.md +373 -373
- tapps_agents/experts/knowledge/user-experience/ux-principles.md +340 -340
- tapps_agents/experts/knowledge_freshness.py +321 -321
- tapps_agents/experts/knowledge_ingestion.py +438 -438
- tapps_agents/experts/knowledge_need_detector.py +93 -93
- tapps_agents/experts/knowledge_validator.py +382 -382
- tapps_agents/experts/observability.py +440 -440
- tapps_agents/experts/passive_notifier.py +238 -238
- tapps_agents/experts/proactive_orchestrator.py +32 -32
- tapps_agents/experts/rag_chunker.py +205 -205
- tapps_agents/experts/rag_embedder.py +152 -152
- tapps_agents/experts/rag_evaluation.py +299 -299
- tapps_agents/experts/rag_index.py +303 -303
- tapps_agents/experts/rag_metrics.py +293 -293
- tapps_agents/experts/rag_safety.py +263 -263
- tapps_agents/experts/report_generator.py +296 -296
- tapps_agents/experts/setup_wizard.py +441 -441
- tapps_agents/experts/simple_rag.py +431 -431
- tapps_agents/experts/vector_rag.py +354 -354
- tapps_agents/experts/weight_distributor.py +304 -304
- tapps_agents/health/__init__.py +24 -24
- tapps_agents/health/base.py +75 -75
- tapps_agents/health/checks/__init__.py +22 -22
- tapps_agents/health/checks/automation.py +127 -127
- tapps_agents/health/checks/context7_cache.py +210 -210
- tapps_agents/health/checks/environment.py +116 -116
- tapps_agents/health/checks/execution.py +170 -170
- tapps_agents/health/checks/knowledge_base.py +187 -187
- tapps_agents/health/checks/outcomes.py +324 -324
- tapps_agents/health/collector.py +280 -280
- tapps_agents/health/dashboard.py +137 -137
- tapps_agents/health/metrics.py +151 -151
- tapps_agents/health/orchestrator.py +271 -271
- tapps_agents/health/registry.py +166 -166
- tapps_agents/hooks/__init__.py +33 -33
- tapps_agents/hooks/config.py +140 -140
- tapps_agents/hooks/events.py +135 -135
- tapps_agents/hooks/executor.py +128 -128
- tapps_agents/hooks/manager.py +143 -143
- tapps_agents/integration/__init__.py +8 -8
- tapps_agents/integration/service_integrator.py +121 -121
- tapps_agents/integrations/__init__.py +10 -10
- tapps_agents/integrations/clawdbot.py +525 -525
- tapps_agents/integrations/memory_bridge.py +356 -356
- tapps_agents/mcp/__init__.py +18 -18
- tapps_agents/mcp/gateway.py +112 -112
- tapps_agents/mcp/servers/__init__.py +13 -13
- tapps_agents/mcp/servers/analysis.py +204 -204
- tapps_agents/mcp/servers/context7.py +198 -198
- tapps_agents/mcp/servers/filesystem.py +218 -218
- tapps_agents/mcp/servers/git.py +201 -201
- tapps_agents/mcp/tool_registry.py +115 -115
- tapps_agents/quality/__init__.py +54 -54
- tapps_agents/quality/coverage_analyzer.py +379 -379
- tapps_agents/quality/enforcement.py +82 -82
- tapps_agents/quality/gates/__init__.py +37 -37
- tapps_agents/quality/gates/approval_gate.py +255 -255
- tapps_agents/quality/gates/base.py +84 -84
- tapps_agents/quality/gates/exceptions.py +43 -43
- tapps_agents/quality/gates/policy_gate.py +195 -195
- tapps_agents/quality/gates/registry.py +239 -239
- tapps_agents/quality/gates/security_gate.py +156 -156
- tapps_agents/quality/quality_gates.py +369 -369
- tapps_agents/quality/secret_scanner.py +335 -335
- tapps_agents/session/__init__.py +19 -19
- tapps_agents/session/manager.py +256 -256
- tapps_agents/simple_mode/__init__.py +66 -66
- tapps_agents/simple_mode/agent_contracts.py +357 -357
- tapps_agents/simple_mode/beads_hooks.py +151 -151
- tapps_agents/simple_mode/code_snippet_handler.py +382 -382
- tapps_agents/simple_mode/documentation_manager.py +395 -395
- tapps_agents/simple_mode/documentation_reader.py +187 -187
- tapps_agents/simple_mode/file_inference.py +292 -292
- tapps_agents/simple_mode/framework_change_detector.py +268 -268
- tapps_agents/simple_mode/intent_parser.py +510 -510
- tapps_agents/simple_mode/learning_progression.py +358 -358
- tapps_agents/simple_mode/nl_handler.py +700 -700
- tapps_agents/simple_mode/onboarding.py +253 -253
- tapps_agents/simple_mode/orchestrators/__init__.py +38 -38
- tapps_agents/simple_mode/orchestrators/base.py +185 -185
- tapps_agents/simple_mode/orchestrators/breakdown_orchestrator.py +49 -49
- tapps_agents/simple_mode/orchestrators/brownfield_orchestrator.py +135 -135
- tapps_agents/simple_mode/orchestrators/build_orchestrator.py +2700 -2667
- tapps_agents/simple_mode/orchestrators/deliverable_checklist.py +349 -349
- tapps_agents/simple_mode/orchestrators/enhance_orchestrator.py +53 -53
- tapps_agents/simple_mode/orchestrators/epic_orchestrator.py +122 -122
- tapps_agents/simple_mode/orchestrators/explore_orchestrator.py +184 -184
- tapps_agents/simple_mode/orchestrators/fix_orchestrator.py +723 -723
- tapps_agents/simple_mode/orchestrators/plan_analysis_orchestrator.py +206 -206
- tapps_agents/simple_mode/orchestrators/pr_orchestrator.py +237 -237
- tapps_agents/simple_mode/orchestrators/refactor_orchestrator.py +222 -222
- tapps_agents/simple_mode/orchestrators/requirements_tracer.py +262 -262
- tapps_agents/simple_mode/orchestrators/resume_orchestrator.py +210 -210
- tapps_agents/simple_mode/orchestrators/review_orchestrator.py +161 -161
- tapps_agents/simple_mode/orchestrators/test_orchestrator.py +82 -82
- tapps_agents/simple_mode/output_aggregator.py +340 -340
- tapps_agents/simple_mode/result_formatters.py +598 -598
- tapps_agents/simple_mode/step_dependencies.py +382 -382
- tapps_agents/simple_mode/step_results.py +276 -276
- tapps_agents/simple_mode/streaming.py +388 -388
- tapps_agents/simple_mode/variations.py +129 -129
- tapps_agents/simple_mode/visual_feedback.py +238 -238
- tapps_agents/simple_mode/zero_config.py +274 -274
- tapps_agents/suggestions/__init__.py +8 -8
- tapps_agents/suggestions/inline_suggester.py +52 -52
- tapps_agents/templates/__init__.py +8 -8
- tapps_agents/templates/microservice_generator.py +274 -274
- tapps_agents/utils/env_validator.py +291 -291
- tapps_agents/workflow/__init__.py +171 -171
- tapps_agents/workflow/acceptance_verifier.py +132 -132
- tapps_agents/workflow/agent_handlers/__init__.py +41 -41
- tapps_agents/workflow/agent_handlers/analyst_handler.py +75 -75
- tapps_agents/workflow/agent_handlers/architect_handler.py +107 -107
- tapps_agents/workflow/agent_handlers/base.py +84 -84
- tapps_agents/workflow/agent_handlers/debugger_handler.py +100 -100
- tapps_agents/workflow/agent_handlers/designer_handler.py +110 -110
- tapps_agents/workflow/agent_handlers/documenter_handler.py +94 -94
- tapps_agents/workflow/agent_handlers/implementer_handler.py +235 -235
- tapps_agents/workflow/agent_handlers/ops_handler.py +62 -62
- tapps_agents/workflow/agent_handlers/orchestrator_handler.py +43 -43
- tapps_agents/workflow/agent_handlers/planner_handler.py +98 -98
- tapps_agents/workflow/agent_handlers/registry.py +119 -119
- tapps_agents/workflow/agent_handlers/reviewer_handler.py +119 -119
- tapps_agents/workflow/agent_handlers/tester_handler.py +69 -69
- tapps_agents/workflow/analytics_accessor.py +337 -337
- tapps_agents/workflow/analytics_alerts.py +416 -416
- tapps_agents/workflow/analytics_dashboard_cursor.py +281 -281
- tapps_agents/workflow/analytics_dual_write.py +103 -103
- tapps_agents/workflow/analytics_integration.py +119 -119
- tapps_agents/workflow/analytics_query_parser.py +278 -278
- tapps_agents/workflow/analytics_visualizer.py +259 -259
- tapps_agents/workflow/artifact_helper.py +204 -204
- tapps_agents/workflow/audit_logger.py +263 -263
- tapps_agents/workflow/auto_execution_config.py +340 -340
- tapps_agents/workflow/auto_progression.py +586 -586
- tapps_agents/workflow/branch_cleanup.py +349 -349
- tapps_agents/workflow/checkpoint.py +256 -256
- tapps_agents/workflow/checkpoint_manager.py +178 -178
- tapps_agents/workflow/code_artifact.py +179 -179
- tapps_agents/workflow/common_enums.py +96 -96
- tapps_agents/workflow/confirmation_handler.py +130 -130
- tapps_agents/workflow/context_analyzer.py +222 -222
- tapps_agents/workflow/context_artifact.py +230 -230
- tapps_agents/workflow/cursor_chat.py +94 -94
- tapps_agents/workflow/cursor_executor.py +2337 -2196
- tapps_agents/workflow/cursor_skill_helper.py +516 -516
- tapps_agents/workflow/dependency_resolver.py +244 -244
- tapps_agents/workflow/design_artifact.py +156 -156
- tapps_agents/workflow/detector.py +751 -751
- tapps_agents/workflow/direct_execution_fallback.py +301 -301
- tapps_agents/workflow/docs_artifact.py +168 -168
- tapps_agents/workflow/enforcer.py +389 -389
- tapps_agents/workflow/enhancement_artifact.py +142 -142
- tapps_agents/workflow/error_recovery.py +806 -806
- tapps_agents/workflow/event_bus.py +183 -183
- tapps_agents/workflow/event_log.py +612 -612
- tapps_agents/workflow/events.py +63 -63
- tapps_agents/workflow/exceptions.py +43 -43
- tapps_agents/workflow/execution_graph.py +498 -498
- tapps_agents/workflow/execution_plan.py +126 -126
- tapps_agents/workflow/file_utils.py +186 -186
- tapps_agents/workflow/gate_evaluator.py +182 -182
- tapps_agents/workflow/gate_integration.py +200 -200
- tapps_agents/workflow/graph_visualizer.py +130 -130
- tapps_agents/workflow/health_checker.py +206 -206
- tapps_agents/workflow/logging_helper.py +243 -243
- tapps_agents/workflow/manifest.py +582 -582
- tapps_agents/workflow/marker_writer.py +250 -250
- tapps_agents/workflow/message_formatter.py +188 -188
- tapps_agents/workflow/messaging.py +325 -325
- tapps_agents/workflow/metadata_models.py +91 -91
- tapps_agents/workflow/metrics_integration.py +226 -226
- tapps_agents/workflow/migration_utils.py +116 -116
- tapps_agents/workflow/models.py +148 -111
- tapps_agents/workflow/nlp_config.py +198 -198
- tapps_agents/workflow/nlp_error_handler.py +207 -207
- tapps_agents/workflow/nlp_executor.py +163 -163
- tapps_agents/workflow/nlp_parser.py +528 -528
- tapps_agents/workflow/observability_dashboard.py +451 -451
- tapps_agents/workflow/observer.py +170 -170
- tapps_agents/workflow/ops_artifact.py +257 -257
- tapps_agents/workflow/output_passing.py +214 -214
- tapps_agents/workflow/parallel_executor.py +463 -463
- tapps_agents/workflow/planning_artifact.py +179 -179
- tapps_agents/workflow/preset_loader.py +285 -285
- tapps_agents/workflow/preset_recommender.py +270 -270
- tapps_agents/workflow/progress_logger.py +145 -145
- tapps_agents/workflow/progress_manager.py +303 -303
- tapps_agents/workflow/progress_monitor.py +186 -186
- tapps_agents/workflow/progress_updates.py +423 -423
- tapps_agents/workflow/quality_artifact.py +158 -158
- tapps_agents/workflow/quality_loopback.py +101 -101
- tapps_agents/workflow/recommender.py +387 -387
- tapps_agents/workflow/remediation_loop.py +166 -166
- tapps_agents/workflow/result_aggregator.py +300 -300
- tapps_agents/workflow/review_artifact.py +185 -185
- tapps_agents/workflow/schema_validator.py +522 -522
- tapps_agents/workflow/session_handoff.py +178 -178
- tapps_agents/workflow/skill_invoker.py +648 -648
- tapps_agents/workflow/state_manager.py +756 -756
- tapps_agents/workflow/state_persistence_config.py +331 -331
- tapps_agents/workflow/status_monitor.py +449 -449
- tapps_agents/workflow/step_checkpoint.py +314 -314
- tapps_agents/workflow/step_details.py +201 -201
- tapps_agents/workflow/story_models.py +147 -147
- tapps_agents/workflow/streaming.py +416 -416
- tapps_agents/workflow/suggestion_engine.py +552 -552
- tapps_agents/workflow/testing_artifact.py +186 -186
- tapps_agents/workflow/timeline.py +158 -158
- tapps_agents/workflow/token_integration.py +209 -209
- tapps_agents/workflow/validation.py +217 -217
- tapps_agents/workflow/visual_feedback.py +391 -391
- tapps_agents/workflow/workflow_chain.py +95 -95
- tapps_agents/workflow/workflow_summary.py +219 -219
- tapps_agents/workflow/worktree_manager.py +724 -724
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/METADATA +672 -672
- tapps_agents-3.6.0.dist-info/RECORD +758 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/licenses/LICENSE +22 -22
- tapps_agents/health/checks/outcomes.backup_20260204_064058.py +0 -324
- tapps_agents/health/checks/outcomes.backup_20260204_064256.py +0 -324
- tapps_agents/health/checks/outcomes.backup_20260204_064600.py +0 -324
- tapps_agents-3.5.40.dist-info/RECORD +0 -760
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/WHEEL +0 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/entry_points.txt +0 -0
- {tapps_agents-3.5.40.dist-info → tapps_agents-3.6.0.dist-info}/top_level.txt +0 -0
|
@@ -1,322 +1,322 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Centralized path validation for agent file operations.
|
|
3
|
-
|
|
4
|
-
Implements root-based path validation to prevent directory traversal
|
|
5
|
-
and ensure all file operations occur within allowed boundaries.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class PathValidationError(ValueError):
|
|
14
|
-
"""Raised when path validation fails."""
|
|
15
|
-
|
|
16
|
-
pass
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def assert_write_allowed(
|
|
20
|
-
path: str | Path,
|
|
21
|
-
project_root: str | Path,
|
|
22
|
-
allowed_paths_write: list[str] | None = None,
|
|
23
|
-
) -> None:
|
|
24
|
-
"""
|
|
25
|
-
Assert that a write to `path` is allowed by the path allowlist (plan 2.2).
|
|
26
|
-
|
|
27
|
-
When allowed_paths_write is empty or None: path must be under project_root.
|
|
28
|
-
When non-empty: path must be under project_root and the first component
|
|
29
|
-
of the relative path must be one of the allowed prefixes
|
|
30
|
-
(e.g. src, tests, docs, .tapps-agents).
|
|
31
|
-
|
|
32
|
-
Call from implementer agent and artifact writers before writing.
|
|
33
|
-
|
|
34
|
-
Args:
|
|
35
|
-
path: File or dir path to write to
|
|
36
|
-
project_root: Project root directory
|
|
37
|
-
allowed_paths_write: Allowed prefix dirs, or None/[] for “only under project_root”
|
|
38
|
-
|
|
39
|
-
Raises:
|
|
40
|
-
PathValidationError: If the path is not allowed
|
|
41
|
-
"""
|
|
42
|
-
path = Path(path).resolve()
|
|
43
|
-
project_root = Path(project_root).resolve()
|
|
44
|
-
try:
|
|
45
|
-
rel = path.relative_to(project_root)
|
|
46
|
-
except ValueError:
|
|
47
|
-
raise PathValidationError(
|
|
48
|
-
f"Write path {path} is not under project root {project_root}"
|
|
49
|
-
) from None
|
|
50
|
-
# Under project root is enough when no allowlist
|
|
51
|
-
if not allowed_paths_write:
|
|
52
|
-
return
|
|
53
|
-
parts = rel.parts
|
|
54
|
-
if not parts:
|
|
55
|
-
return # writing project root itself
|
|
56
|
-
first = parts[0]
|
|
57
|
-
if first in allowed_paths_write:
|
|
58
|
-
return
|
|
59
|
-
raise PathValidationError(
|
|
60
|
-
f"Write path {path} is not under an allowed prefix. "
|
|
61
|
-
f"Allowed: {allowed_paths_write}. First component: {first}"
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class PathValidator:
|
|
66
|
-
"""
|
|
67
|
-
Validates file paths against allowed roots.
|
|
68
|
-
|
|
69
|
-
Allowed roots:
|
|
70
|
-
- Project root (directory containing .tapps-agents/ or current working directory)
|
|
71
|
-
- .tapps-agents/ directory
|
|
72
|
-
- Test temporary directories (pytest)
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
def __init__(self, project_root: Path | None = None):
|
|
76
|
-
"""
|
|
77
|
-
Initialize path validator.
|
|
78
|
-
|
|
79
|
-
Args:
|
|
80
|
-
project_root: Project root directory. If None, auto-detects from .tapps-agents/
|
|
81
|
-
"""
|
|
82
|
-
if project_root is None:
|
|
83
|
-
project_root = self._detect_project_root()
|
|
84
|
-
|
|
85
|
-
self.project_root = project_root.resolve()
|
|
86
|
-
self.tapps_agents_dir = project_root / ".tapps-agents"
|
|
87
|
-
|
|
88
|
-
@staticmethod
|
|
89
|
-
def _detect_project_root() -> Path:
|
|
90
|
-
"""
|
|
91
|
-
Detect project root by looking for .tapps-agents/ directory.
|
|
92
|
-
|
|
93
|
-
Returns:
|
|
94
|
-
Project root Path (current directory if .tapps-agents/ not found)
|
|
95
|
-
"""
|
|
96
|
-
current = Path.cwd()
|
|
97
|
-
for parent in [current] + list(current.parents):
|
|
98
|
-
if (parent / ".tapps-agents").exists():
|
|
99
|
-
return parent
|
|
100
|
-
return current
|
|
101
|
-
|
|
102
|
-
def _is_within_allowed_root(self, resolved_path: Path) -> bool:
|
|
103
|
-
"""
|
|
104
|
-
Check if resolved path is within an allowed root.
|
|
105
|
-
|
|
106
|
-
Args:
|
|
107
|
-
resolved_path: Resolved, absolute path
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
True if path is within allowed roots
|
|
111
|
-
"""
|
|
112
|
-
# Check if within project root
|
|
113
|
-
try:
|
|
114
|
-
resolved_path.relative_to(self.project_root)
|
|
115
|
-
return True
|
|
116
|
-
except ValueError:
|
|
117
|
-
pass
|
|
118
|
-
|
|
119
|
-
# Check if within .tapps-agents/
|
|
120
|
-
if self.tapps_agents_dir.exists():
|
|
121
|
-
try:
|
|
122
|
-
resolved_path.relative_to(self.tapps_agents_dir.resolve())
|
|
123
|
-
return True
|
|
124
|
-
except ValueError:
|
|
125
|
-
pass
|
|
126
|
-
|
|
127
|
-
return False
|
|
128
|
-
|
|
129
|
-
def _is_test_path(self, resolved_path: Path) -> bool:
|
|
130
|
-
"""
|
|
131
|
-
Check if path is a legitimate test temporary path.
|
|
132
|
-
|
|
133
|
-
Args:
|
|
134
|
-
resolved_path: Resolved, absolute path
|
|
135
|
-
|
|
136
|
-
Returns:
|
|
137
|
-
True if path is a test temporary path
|
|
138
|
-
"""
|
|
139
|
-
import tempfile
|
|
140
|
-
|
|
141
|
-
path_str = str(resolved_path)
|
|
142
|
-
|
|
143
|
-
# Check for pytest temporary directory patterns
|
|
144
|
-
# Pattern 1: pytest-of-<username>/pytest-<number>/ (pytest tmp_path fixture)
|
|
145
|
-
if "pytest-of-" in path_str or "pytest-" in path_str:
|
|
146
|
-
# Also check if it's in a temp directory to be safe
|
|
147
|
-
temp_dir = Path(tempfile.gettempdir())
|
|
148
|
-
try:
|
|
149
|
-
resolved_path.relative_to(temp_dir)
|
|
150
|
-
return True
|
|
151
|
-
except ValueError:
|
|
152
|
-
pass
|
|
153
|
-
|
|
154
|
-
# Pattern 2: Explicit tmp_path in path (legacy check)
|
|
155
|
-
if "pytest" in path_str and "tmp_path" in path_str:
|
|
156
|
-
return True
|
|
157
|
-
|
|
158
|
-
return False
|
|
159
|
-
|
|
160
|
-
def _check_traversal_patterns(self, file_path: Path) -> None:
|
|
161
|
-
"""
|
|
162
|
-
Check for path traversal patterns in the input path.
|
|
163
|
-
|
|
164
|
-
Args:
|
|
165
|
-
file_path: Path to check
|
|
166
|
-
|
|
167
|
-
Raises:
|
|
168
|
-
PathValidationError: If traversal patterns detected
|
|
169
|
-
"""
|
|
170
|
-
path_str = str(file_path)
|
|
171
|
-
|
|
172
|
-
# Check for basic traversal sequences
|
|
173
|
-
if ".." in path_str:
|
|
174
|
-
# Allow if it's part of a legitimate path that resolves correctly
|
|
175
|
-
# (e.g., "a/../b" resolves to "b")
|
|
176
|
-
resolved = file_path.resolve()
|
|
177
|
-
# If resolved path doesn't exist or is suspicious, block it
|
|
178
|
-
if not resolved.exists() or not self._is_within_allowed_root(resolved):
|
|
179
|
-
raise PathValidationError(
|
|
180
|
-
f"Path traversal detected: {file_path}. "
|
|
181
|
-
f"Resolved to: {resolved}"
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
# Check for URL-encoded traversal attempts
|
|
185
|
-
suspicious_patterns = ["%2e%2e", "%2f", "%5c"]
|
|
186
|
-
if any(pattern in path_str.lower() for pattern in suspicious_patterns):
|
|
187
|
-
raise PathValidationError(f"Suspicious path pattern detected: {file_path}")
|
|
188
|
-
|
|
189
|
-
def validate_path(
|
|
190
|
-
self,
|
|
191
|
-
file_path: Path,
|
|
192
|
-
must_exist: bool = True,
|
|
193
|
-
max_file_size: int | None = 10 * 1024 * 1024,
|
|
194
|
-
allow_write: bool = True,
|
|
195
|
-
) -> Path:
|
|
196
|
-
"""
|
|
197
|
-
Validate a file path against allowed roots and security rules.
|
|
198
|
-
|
|
199
|
-
Args:
|
|
200
|
-
file_path: Path to validate (can be relative or absolute)
|
|
201
|
-
must_exist: If True, file must exist (default: True)
|
|
202
|
-
max_file_size: Maximum file size in bytes (default: 10MB, None to disable)
|
|
203
|
-
allow_write: If False, only validates read access (default: True)
|
|
204
|
-
|
|
205
|
-
Returns:
|
|
206
|
-
Resolved Path object
|
|
207
|
-
|
|
208
|
-
Raises:
|
|
209
|
-
PathValidationError: If path validation fails
|
|
210
|
-
FileNotFoundError: If must_exist=True and file doesn't exist
|
|
211
|
-
"""
|
|
212
|
-
# Convert to Path if string
|
|
213
|
-
if isinstance(file_path, str):
|
|
214
|
-
file_path = Path(file_path)
|
|
215
|
-
|
|
216
|
-
# Resolve to absolute, canonical path
|
|
217
|
-
try:
|
|
218
|
-
resolved_path = file_path.resolve()
|
|
219
|
-
except (OSError, RuntimeError) as e:
|
|
220
|
-
raise PathValidationError(f"Cannot resolve path {file_path}: {e}") from e
|
|
221
|
-
|
|
222
|
-
# Check for traversal patterns in original path
|
|
223
|
-
self._check_traversal_patterns(file_path)
|
|
224
|
-
|
|
225
|
-
# Allow test paths
|
|
226
|
-
if self._is_test_path(resolved_path):
|
|
227
|
-
# Still check existence and size if required
|
|
228
|
-
if must_exist and not resolved_path.exists():
|
|
229
|
-
raise FileNotFoundError(f"File not found: {file_path}")
|
|
230
|
-
if max_file_size and resolved_path.exists():
|
|
231
|
-
file_size = resolved_path.stat().st_size
|
|
232
|
-
if file_size > max_file_size:
|
|
233
|
-
raise PathValidationError(
|
|
234
|
-
f"File too large: {file_size} bytes (max {max_file_size} bytes)"
|
|
235
|
-
)
|
|
236
|
-
return resolved_path
|
|
237
|
-
|
|
238
|
-
# Check if within allowed roots
|
|
239
|
-
if not self._is_within_allowed_root(resolved_path):
|
|
240
|
-
raise PathValidationError(
|
|
241
|
-
f"Path outside allowed roots: {resolved_path}. "
|
|
242
|
-
f"Allowed roots: {self.project_root}, {self.tapps_agents_dir}"
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
# Check file existence
|
|
246
|
-
if must_exist and not resolved_path.exists():
|
|
247
|
-
raise FileNotFoundError(f"File not found: {file_path}")
|
|
248
|
-
|
|
249
|
-
# Check file size (only for existing files)
|
|
250
|
-
if max_file_size and resolved_path.exists() and resolved_path.is_file():
|
|
251
|
-
file_size = resolved_path.stat().st_size
|
|
252
|
-
if file_size > max_file_size:
|
|
253
|
-
raise PathValidationError(
|
|
254
|
-
f"File too large: {file_size} bytes (max {max_file_size} bytes)"
|
|
255
|
-
)
|
|
256
|
-
|
|
257
|
-
return resolved_path
|
|
258
|
-
|
|
259
|
-
def validate_write_path(self, file_path: Path) -> Path:
|
|
260
|
-
"""
|
|
261
|
-
Validate a path for write operations.
|
|
262
|
-
|
|
263
|
-
Args:
|
|
264
|
-
file_path: Path to validate
|
|
265
|
-
|
|
266
|
-
Returns:
|
|
267
|
-
Resolved Path object
|
|
268
|
-
|
|
269
|
-
Raises:
|
|
270
|
-
PathValidationError: If path validation fails
|
|
271
|
-
"""
|
|
272
|
-
return self.validate_path(
|
|
273
|
-
file_path, must_exist=False, allow_write=True, max_file_size=None
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
def validate_read_path(
|
|
277
|
-
self, file_path: Path, max_file_size: int | None = 10 * 1024 * 1024
|
|
278
|
-
) -> Path:
|
|
279
|
-
"""
|
|
280
|
-
Validate a path for read operations.
|
|
281
|
-
|
|
282
|
-
Args:
|
|
283
|
-
file_path: Path to validate
|
|
284
|
-
max_file_size: Maximum file size in bytes (default: 10MB)
|
|
285
|
-
|
|
286
|
-
Returns:
|
|
287
|
-
Resolved Path object
|
|
288
|
-
|
|
289
|
-
Raises:
|
|
290
|
-
PathValidationError: If path validation fails
|
|
291
|
-
FileNotFoundError: If file doesn't exist
|
|
292
|
-
"""
|
|
293
|
-
return self.validate_path(
|
|
294
|
-
file_path, must_exist=True, allow_write=False, max_file_size=max_file_size
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
# Global validator instance (lazy initialization)
|
|
299
|
-
_global_validator: PathValidator | None = None
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
def get_path_validator(project_root: Path | None = None) -> PathValidator:
|
|
303
|
-
"""
|
|
304
|
-
Get or create global path validator instance.
|
|
305
|
-
|
|
306
|
-
Args:
|
|
307
|
-
project_root: Project root directory (only used on first call)
|
|
308
|
-
|
|
309
|
-
Returns:
|
|
310
|
-
PathValidator instance
|
|
311
|
-
"""
|
|
312
|
-
global _global_validator
|
|
313
|
-
if _global_validator is None:
|
|
314
|
-
_global_validator = PathValidator(project_root)
|
|
315
|
-
return _global_validator
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
def reset_path_validator():
|
|
319
|
-
"""Reset global path validator (useful for testing)."""
|
|
320
|
-
global _global_validator
|
|
321
|
-
_global_validator = None
|
|
322
|
-
|
|
1
|
+
"""
|
|
2
|
+
Centralized path validation for agent file operations.
|
|
3
|
+
|
|
4
|
+
Implements root-based path validation to prevent directory traversal
|
|
5
|
+
and ensure all file operations occur within allowed boundaries.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PathValidationError(ValueError):
|
|
14
|
+
"""Raised when path validation fails."""
|
|
15
|
+
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def assert_write_allowed(
|
|
20
|
+
path: str | Path,
|
|
21
|
+
project_root: str | Path,
|
|
22
|
+
allowed_paths_write: list[str] | None = None,
|
|
23
|
+
) -> None:
|
|
24
|
+
"""
|
|
25
|
+
Assert that a write to `path` is allowed by the path allowlist (plan 2.2).
|
|
26
|
+
|
|
27
|
+
When allowed_paths_write is empty or None: path must be under project_root.
|
|
28
|
+
When non-empty: path must be under project_root and the first component
|
|
29
|
+
of the relative path must be one of the allowed prefixes
|
|
30
|
+
(e.g. src, tests, docs, .tapps-agents).
|
|
31
|
+
|
|
32
|
+
Call from implementer agent and artifact writers before writing.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
path: File or dir path to write to
|
|
36
|
+
project_root: Project root directory
|
|
37
|
+
allowed_paths_write: Allowed prefix dirs, or None/[] for “only under project_root”
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
PathValidationError: If the path is not allowed
|
|
41
|
+
"""
|
|
42
|
+
path = Path(path).resolve()
|
|
43
|
+
project_root = Path(project_root).resolve()
|
|
44
|
+
try:
|
|
45
|
+
rel = path.relative_to(project_root)
|
|
46
|
+
except ValueError:
|
|
47
|
+
raise PathValidationError(
|
|
48
|
+
f"Write path {path} is not under project root {project_root}"
|
|
49
|
+
) from None
|
|
50
|
+
# Under project root is enough when no allowlist
|
|
51
|
+
if not allowed_paths_write:
|
|
52
|
+
return
|
|
53
|
+
parts = rel.parts
|
|
54
|
+
if not parts:
|
|
55
|
+
return # writing project root itself
|
|
56
|
+
first = parts[0]
|
|
57
|
+
if first in allowed_paths_write:
|
|
58
|
+
return
|
|
59
|
+
raise PathValidationError(
|
|
60
|
+
f"Write path {path} is not under an allowed prefix. "
|
|
61
|
+
f"Allowed: {allowed_paths_write}. First component: {first}"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class PathValidator:
|
|
66
|
+
"""
|
|
67
|
+
Validates file paths against allowed roots.
|
|
68
|
+
|
|
69
|
+
Allowed roots:
|
|
70
|
+
- Project root (directory containing .tapps-agents/ or current working directory)
|
|
71
|
+
- .tapps-agents/ directory
|
|
72
|
+
- Test temporary directories (pytest)
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self, project_root: Path | None = None):
|
|
76
|
+
"""
|
|
77
|
+
Initialize path validator.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
project_root: Project root directory. If None, auto-detects from .tapps-agents/
|
|
81
|
+
"""
|
|
82
|
+
if project_root is None:
|
|
83
|
+
project_root = self._detect_project_root()
|
|
84
|
+
|
|
85
|
+
self.project_root = project_root.resolve()
|
|
86
|
+
self.tapps_agents_dir = project_root / ".tapps-agents"
|
|
87
|
+
|
|
88
|
+
@staticmethod
|
|
89
|
+
def _detect_project_root() -> Path:
|
|
90
|
+
"""
|
|
91
|
+
Detect project root by looking for .tapps-agents/ directory.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Project root Path (current directory if .tapps-agents/ not found)
|
|
95
|
+
"""
|
|
96
|
+
current = Path.cwd()
|
|
97
|
+
for parent in [current] + list(current.parents):
|
|
98
|
+
if (parent / ".tapps-agents").exists():
|
|
99
|
+
return parent
|
|
100
|
+
return current
|
|
101
|
+
|
|
102
|
+
def _is_within_allowed_root(self, resolved_path: Path) -> bool:
|
|
103
|
+
"""
|
|
104
|
+
Check if resolved path is within an allowed root.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
resolved_path: Resolved, absolute path
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
True if path is within allowed roots
|
|
111
|
+
"""
|
|
112
|
+
# Check if within project root
|
|
113
|
+
try:
|
|
114
|
+
resolved_path.relative_to(self.project_root)
|
|
115
|
+
return True
|
|
116
|
+
except ValueError:
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
# Check if within .tapps-agents/
|
|
120
|
+
if self.tapps_agents_dir.exists():
|
|
121
|
+
try:
|
|
122
|
+
resolved_path.relative_to(self.tapps_agents_dir.resolve())
|
|
123
|
+
return True
|
|
124
|
+
except ValueError:
|
|
125
|
+
pass
|
|
126
|
+
|
|
127
|
+
return False
|
|
128
|
+
|
|
129
|
+
def _is_test_path(self, resolved_path: Path) -> bool:
|
|
130
|
+
"""
|
|
131
|
+
Check if path is a legitimate test temporary path.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
resolved_path: Resolved, absolute path
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
True if path is a test temporary path
|
|
138
|
+
"""
|
|
139
|
+
import tempfile
|
|
140
|
+
|
|
141
|
+
path_str = str(resolved_path)
|
|
142
|
+
|
|
143
|
+
# Check for pytest temporary directory patterns
|
|
144
|
+
# Pattern 1: pytest-of-<username>/pytest-<number>/ (pytest tmp_path fixture)
|
|
145
|
+
if "pytest-of-" in path_str or "pytest-" in path_str:
|
|
146
|
+
# Also check if it's in a temp directory to be safe
|
|
147
|
+
temp_dir = Path(tempfile.gettempdir())
|
|
148
|
+
try:
|
|
149
|
+
resolved_path.relative_to(temp_dir)
|
|
150
|
+
return True
|
|
151
|
+
except ValueError:
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
# Pattern 2: Explicit tmp_path in path (legacy check)
|
|
155
|
+
if "pytest" in path_str and "tmp_path" in path_str:
|
|
156
|
+
return True
|
|
157
|
+
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
def _check_traversal_patterns(self, file_path: Path) -> None:
|
|
161
|
+
"""
|
|
162
|
+
Check for path traversal patterns in the input path.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
file_path: Path to check
|
|
166
|
+
|
|
167
|
+
Raises:
|
|
168
|
+
PathValidationError: If traversal patterns detected
|
|
169
|
+
"""
|
|
170
|
+
path_str = str(file_path)
|
|
171
|
+
|
|
172
|
+
# Check for basic traversal sequences
|
|
173
|
+
if ".." in path_str:
|
|
174
|
+
# Allow if it's part of a legitimate path that resolves correctly
|
|
175
|
+
# (e.g., "a/../b" resolves to "b")
|
|
176
|
+
resolved = file_path.resolve()
|
|
177
|
+
# If resolved path doesn't exist or is suspicious, block it
|
|
178
|
+
if not resolved.exists() or not self._is_within_allowed_root(resolved):
|
|
179
|
+
raise PathValidationError(
|
|
180
|
+
f"Path traversal detected: {file_path}. "
|
|
181
|
+
f"Resolved to: {resolved}"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Check for URL-encoded traversal attempts
|
|
185
|
+
suspicious_patterns = ["%2e%2e", "%2f", "%5c"]
|
|
186
|
+
if any(pattern in path_str.lower() for pattern in suspicious_patterns):
|
|
187
|
+
raise PathValidationError(f"Suspicious path pattern detected: {file_path}")
|
|
188
|
+
|
|
189
|
+
def validate_path(
|
|
190
|
+
self,
|
|
191
|
+
file_path: Path,
|
|
192
|
+
must_exist: bool = True,
|
|
193
|
+
max_file_size: int | None = 10 * 1024 * 1024,
|
|
194
|
+
allow_write: bool = True,
|
|
195
|
+
) -> Path:
|
|
196
|
+
"""
|
|
197
|
+
Validate a file path against allowed roots and security rules.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
file_path: Path to validate (can be relative or absolute)
|
|
201
|
+
must_exist: If True, file must exist (default: True)
|
|
202
|
+
max_file_size: Maximum file size in bytes (default: 10MB, None to disable)
|
|
203
|
+
allow_write: If False, only validates read access (default: True)
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Resolved Path object
|
|
207
|
+
|
|
208
|
+
Raises:
|
|
209
|
+
PathValidationError: If path validation fails
|
|
210
|
+
FileNotFoundError: If must_exist=True and file doesn't exist
|
|
211
|
+
"""
|
|
212
|
+
# Convert to Path if string
|
|
213
|
+
if isinstance(file_path, str):
|
|
214
|
+
file_path = Path(file_path)
|
|
215
|
+
|
|
216
|
+
# Resolve to absolute, canonical path
|
|
217
|
+
try:
|
|
218
|
+
resolved_path = file_path.resolve()
|
|
219
|
+
except (OSError, RuntimeError) as e:
|
|
220
|
+
raise PathValidationError(f"Cannot resolve path {file_path}: {e}") from e
|
|
221
|
+
|
|
222
|
+
# Check for traversal patterns in original path
|
|
223
|
+
self._check_traversal_patterns(file_path)
|
|
224
|
+
|
|
225
|
+
# Allow test paths
|
|
226
|
+
if self._is_test_path(resolved_path):
|
|
227
|
+
# Still check existence and size if required
|
|
228
|
+
if must_exist and not resolved_path.exists():
|
|
229
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
230
|
+
if max_file_size and resolved_path.exists():
|
|
231
|
+
file_size = resolved_path.stat().st_size
|
|
232
|
+
if file_size > max_file_size:
|
|
233
|
+
raise PathValidationError(
|
|
234
|
+
f"File too large: {file_size} bytes (max {max_file_size} bytes)"
|
|
235
|
+
)
|
|
236
|
+
return resolved_path
|
|
237
|
+
|
|
238
|
+
# Check if within allowed roots
|
|
239
|
+
if not self._is_within_allowed_root(resolved_path):
|
|
240
|
+
raise PathValidationError(
|
|
241
|
+
f"Path outside allowed roots: {resolved_path}. "
|
|
242
|
+
f"Allowed roots: {self.project_root}, {self.tapps_agents_dir}"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Check file existence
|
|
246
|
+
if must_exist and not resolved_path.exists():
|
|
247
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
248
|
+
|
|
249
|
+
# Check file size (only for existing files)
|
|
250
|
+
if max_file_size and resolved_path.exists() and resolved_path.is_file():
|
|
251
|
+
file_size = resolved_path.stat().st_size
|
|
252
|
+
if file_size > max_file_size:
|
|
253
|
+
raise PathValidationError(
|
|
254
|
+
f"File too large: {file_size} bytes (max {max_file_size} bytes)"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
return resolved_path
|
|
258
|
+
|
|
259
|
+
def validate_write_path(self, file_path: Path) -> Path:
|
|
260
|
+
"""
|
|
261
|
+
Validate a path for write operations.
|
|
262
|
+
|
|
263
|
+
Args:
|
|
264
|
+
file_path: Path to validate
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Resolved Path object
|
|
268
|
+
|
|
269
|
+
Raises:
|
|
270
|
+
PathValidationError: If path validation fails
|
|
271
|
+
"""
|
|
272
|
+
return self.validate_path(
|
|
273
|
+
file_path, must_exist=False, allow_write=True, max_file_size=None
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
def validate_read_path(
|
|
277
|
+
self, file_path: Path, max_file_size: int | None = 10 * 1024 * 1024
|
|
278
|
+
) -> Path:
|
|
279
|
+
"""
|
|
280
|
+
Validate a path for read operations.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
file_path: Path to validate
|
|
284
|
+
max_file_size: Maximum file size in bytes (default: 10MB)
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
Resolved Path object
|
|
288
|
+
|
|
289
|
+
Raises:
|
|
290
|
+
PathValidationError: If path validation fails
|
|
291
|
+
FileNotFoundError: If file doesn't exist
|
|
292
|
+
"""
|
|
293
|
+
return self.validate_path(
|
|
294
|
+
file_path, must_exist=True, allow_write=False, max_file_size=max_file_size
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
# Global validator instance (lazy initialization)
|
|
299
|
+
_global_validator: PathValidator | None = None
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def get_path_validator(project_root: Path | None = None) -> PathValidator:
|
|
303
|
+
"""
|
|
304
|
+
Get or create global path validator instance.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
project_root: Project root directory (only used on first call)
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
PathValidator instance
|
|
311
|
+
"""
|
|
312
|
+
global _global_validator
|
|
313
|
+
if _global_validator is None:
|
|
314
|
+
_global_validator = PathValidator(project_root)
|
|
315
|
+
return _global_validator
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def reset_path_validator():
|
|
319
|
+
"""Reset global path validator (useful for testing)."""
|
|
320
|
+
global _global_validator
|
|
321
|
+
_global_validator = None
|
|
322
|
+
|