tapps-agents 3.6.0__py3-none-any.whl → 3.6.1__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/service_discovery.py +534 -534
- 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/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 -227
- tapps_agents/cli/commands/tester.py +191 -191
- 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/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/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.backup_20260204_064058.py +324 -0
- tapps_agents/health/checks/outcomes.backup_20260204_064256.py +324 -0
- tapps_agents/health/checks/outcomes.backup_20260204_064600.py +324 -0
- 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/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/resources/__init__.py +5 -0
- tapps_agents/resources/claude/__init__.py +1 -0
- tapps_agents/resources/claude/commands/README.md +156 -0
- tapps_agents/resources/claude/commands/__init__.py +1 -0
- tapps_agents/resources/claude/commands/build-fix.md +22 -0
- tapps_agents/resources/claude/commands/build.md +77 -0
- tapps_agents/resources/claude/commands/debug.md +53 -0
- tapps_agents/resources/claude/commands/design.md +68 -0
- tapps_agents/resources/claude/commands/docs.md +53 -0
- tapps_agents/resources/claude/commands/e2e.md +22 -0
- tapps_agents/resources/claude/commands/fix.md +54 -0
- tapps_agents/resources/claude/commands/implement.md +53 -0
- tapps_agents/resources/claude/commands/improve.md +53 -0
- tapps_agents/resources/claude/commands/library-docs.md +64 -0
- tapps_agents/resources/claude/commands/lint.md +52 -0
- tapps_agents/resources/claude/commands/plan.md +65 -0
- tapps_agents/resources/claude/commands/refactor-clean.md +21 -0
- tapps_agents/resources/claude/commands/refactor.md +55 -0
- tapps_agents/resources/claude/commands/review.md +67 -0
- tapps_agents/resources/claude/commands/score.md +60 -0
- tapps_agents/resources/claude/commands/security-review.md +22 -0
- tapps_agents/resources/claude/commands/security-scan.md +54 -0
- tapps_agents/resources/claude/commands/tdd.md +24 -0
- tapps_agents/resources/claude/commands/test-coverage.md +21 -0
- tapps_agents/resources/claude/commands/test.md +54 -0
- tapps_agents/resources/claude/commands/update-codemaps.md +20 -0
- tapps_agents/resources/claude/commands/update-docs.md +21 -0
- tapps_agents/resources/claude/skills/__init__.py +1 -0
- tapps_agents/resources/claude/skills/analyst/SKILL.md +272 -0
- tapps_agents/resources/claude/skills/analyst/__init__.py +1 -0
- tapps_agents/resources/claude/skills/architect/SKILL.md +282 -0
- tapps_agents/resources/claude/skills/architect/__init__.py +1 -0
- tapps_agents/resources/claude/skills/backend-patterns/SKILL.md +30 -0
- tapps_agents/resources/claude/skills/backend-patterns/__init__.py +1 -0
- tapps_agents/resources/claude/skills/coding-standards/SKILL.md +29 -0
- tapps_agents/resources/claude/skills/coding-standards/__init__.py +1 -0
- tapps_agents/resources/claude/skills/debugger/SKILL.md +203 -0
- tapps_agents/resources/claude/skills/debugger/__init__.py +1 -0
- tapps_agents/resources/claude/skills/designer/SKILL.md +243 -0
- tapps_agents/resources/claude/skills/designer/__init__.py +1 -0
- tapps_agents/resources/claude/skills/documenter/SKILL.md +252 -0
- tapps_agents/resources/claude/skills/documenter/__init__.py +1 -0
- tapps_agents/resources/claude/skills/enhancer/SKILL.md +307 -0
- tapps_agents/resources/claude/skills/enhancer/__init__.py +1 -0
- tapps_agents/resources/claude/skills/evaluator/SKILL.md +204 -0
- tapps_agents/resources/claude/skills/evaluator/__init__.py +1 -0
- tapps_agents/resources/claude/skills/frontend-patterns/SKILL.md +29 -0
- tapps_agents/resources/claude/skills/frontend-patterns/__init__.py +1 -0
- tapps_agents/resources/claude/skills/implementer/SKILL.md +188 -0
- tapps_agents/resources/claude/skills/implementer/__init__.py +1 -0
- tapps_agents/resources/claude/skills/improver/SKILL.md +218 -0
- tapps_agents/resources/claude/skills/improver/__init__.py +1 -0
- tapps_agents/resources/claude/skills/ops/SKILL.md +281 -0
- tapps_agents/resources/claude/skills/ops/__init__.py +1 -0
- tapps_agents/resources/claude/skills/orchestrator/SKILL.md +390 -0
- tapps_agents/resources/claude/skills/orchestrator/__init__.py +1 -0
- tapps_agents/resources/claude/skills/planner/SKILL.md +254 -0
- tapps_agents/resources/claude/skills/planner/__init__.py +1 -0
- tapps_agents/resources/claude/skills/reviewer/SKILL.md +434 -0
- tapps_agents/resources/claude/skills/reviewer/__init__.py +1 -0
- tapps_agents/resources/claude/skills/security-review/SKILL.md +31 -0
- tapps_agents/resources/claude/skills/security-review/__init__.py +1 -0
- tapps_agents/resources/claude/skills/simple-mode/SKILL.md +695 -0
- tapps_agents/resources/claude/skills/simple-mode/__init__.py +1 -0
- tapps_agents/resources/claude/skills/tester/SKILL.md +219 -0
- tapps_agents/resources/claude/skills/tester/__init__.py +1 -0
- tapps_agents/resources/cursor/.cursorignore +35 -0
- tapps_agents/resources/cursor/__init__.py +1 -0
- tapps_agents/resources/cursor/commands/__init__.py +1 -0
- tapps_agents/resources/cursor/commands/build-fix.md +11 -0
- tapps_agents/resources/cursor/commands/build.md +11 -0
- tapps_agents/resources/cursor/commands/e2e.md +11 -0
- tapps_agents/resources/cursor/commands/fix.md +11 -0
- tapps_agents/resources/cursor/commands/refactor-clean.md +11 -0
- tapps_agents/resources/cursor/commands/review.md +11 -0
- tapps_agents/resources/cursor/commands/security-review.md +11 -0
- tapps_agents/resources/cursor/commands/tdd.md +11 -0
- tapps_agents/resources/cursor/commands/test-coverage.md +11 -0
- tapps_agents/resources/cursor/commands/test.md +11 -0
- tapps_agents/resources/cursor/commands/update-codemaps.md +10 -0
- tapps_agents/resources/cursor/commands/update-docs.md +11 -0
- tapps_agents/resources/cursor/rules/__init__.py +1 -0
- tapps_agents/resources/cursor/rules/agent-capabilities.mdc +687 -0
- tapps_agents/resources/cursor/rules/coding-style.mdc +31 -0
- tapps_agents/resources/cursor/rules/command-reference.mdc +2081 -0
- tapps_agents/resources/cursor/rules/cursor-mode-usage.mdc +125 -0
- tapps_agents/resources/cursor/rules/git-workflow.mdc +29 -0
- tapps_agents/resources/cursor/rules/performance.mdc +29 -0
- tapps_agents/resources/cursor/rules/project-context.mdc +163 -0
- tapps_agents/resources/cursor/rules/project-profiling.mdc +197 -0
- tapps_agents/resources/cursor/rules/quick-reference.mdc +630 -0
- tapps_agents/resources/cursor/rules/security.mdc +32 -0
- tapps_agents/resources/cursor/rules/simple-mode.mdc +500 -0
- tapps_agents/resources/cursor/rules/testing.mdc +31 -0
- tapps_agents/resources/cursor/rules/when-to-use.mdc +156 -0
- tapps_agents/resources/cursor/rules/workflow-presets.mdc +179 -0
- tapps_agents/resources/customizations/__init__.py +1 -0
- tapps_agents/resources/customizations/example-custom.yaml +83 -0
- tapps_agents/resources/hooks/__init__.py +1 -0
- tapps_agents/resources/hooks/templates/README.md +5 -0
- tapps_agents/resources/hooks/templates/__init__.py +1 -0
- tapps_agents/resources/hooks/templates/add-project-context.yaml +8 -0
- tapps_agents/resources/hooks/templates/auto-format-js.yaml +10 -0
- tapps_agents/resources/hooks/templates/auto-format-python.yaml +10 -0
- tapps_agents/resources/hooks/templates/git-commit-check.yaml +7 -0
- tapps_agents/resources/hooks/templates/notify-on-complete.yaml +8 -0
- tapps_agents/resources/hooks/templates/quality-gate.yaml +8 -0
- tapps_agents/resources/hooks/templates/security-scan-on-edit.yaml +10 -0
- tapps_agents/resources/hooks/templates/session-end-log.yaml +7 -0
- tapps_agents/resources/hooks/templates/show-beads-ready.yaml +8 -0
- tapps_agents/resources/hooks/templates/test-on-edit.yaml +10 -0
- tapps_agents/resources/hooks/templates/update-docs-on-complete.yaml +8 -0
- tapps_agents/resources/hooks/templates/user-prompt-log.yaml +7 -0
- tapps_agents/resources/scripts/__init__.py +1 -0
- tapps_agents/resources/scripts/set_bd_path.ps1 +51 -0
- tapps_agents/resources/workflows/__init__.py +1 -0
- tapps_agents/resources/workflows/presets/__init__.py +1 -0
- tapps_agents/resources/workflows/presets/brownfield-analysis.yaml +235 -0
- tapps_agents/resources/workflows/presets/fix.yaml +78 -0
- tapps_agents/resources/workflows/presets/full-sdlc.yaml +122 -0
- tapps_agents/resources/workflows/presets/quality.yaml +82 -0
- tapps_agents/resources/workflows/presets/rapid-dev.yaml +84 -0
- 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/breakdown_orchestrator.py +49 -49
- tapps_agents/simple_mode/orchestrators/brownfield_orchestrator.py +135 -135
- 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/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_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/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 -148
- 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.6.0.dist-info → tapps_agents-3.6.1.dist-info}/METADATA +672 -672
- tapps_agents-3.6.1.dist-info/RECORD +883 -0
- {tapps_agents-3.6.0.dist-info → tapps_agents-3.6.1.dist-info}/licenses/LICENSE +22 -22
- tapps_agents-3.6.0.dist-info/RECORD +0 -758
- {tapps_agents-3.6.0.dist-info → tapps_agents-3.6.1.dist-info}/WHEEL +0 -0
- {tapps_agents-3.6.0.dist-info → tapps_agents-3.6.1.dist-info}/entry_points.txt +0 -0
- {tapps_agents-3.6.0.dist-info → tapps_agents-3.6.1.dist-info}/top_level.txt +0 -0
|
@@ -1,521 +1,521 @@
|
|
|
1
|
-
# API Security Patterns
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
API security protects APIs from unauthorized access, data breaches, and attacks. It involves authentication, authorization, encryption, input validation, and threat protection.
|
|
6
|
-
|
|
7
|
-
## Authentication Patterns
|
|
8
|
-
|
|
9
|
-
### 1. API Keys
|
|
10
|
-
|
|
11
|
-
**Simple but Limited:**
|
|
12
|
-
```python
|
|
13
|
-
API_KEY_HEADER = 'X-API-Key'
|
|
14
|
-
|
|
15
|
-
def authenticate_api_key(request):
|
|
16
|
-
api_key = request.headers.get(API_KEY_HEADER)
|
|
17
|
-
if not api_key:
|
|
18
|
-
return None
|
|
19
|
-
|
|
20
|
-
key_record = db.get_api_key(api_key)
|
|
21
|
-
if not key_record or not key_record.is_active:
|
|
22
|
-
return None
|
|
23
|
-
|
|
24
|
-
return key_record.user
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Best Practices:**
|
|
28
|
-
- Store hashed keys
|
|
29
|
-
- Rotate regularly
|
|
30
|
-
- Scope permissions
|
|
31
|
-
- Rate limit per key
|
|
32
|
-
|
|
33
|
-
### 2. OAuth 2.0
|
|
34
|
-
|
|
35
|
-
**Authorization Code Flow:**
|
|
36
|
-
```
|
|
37
|
-
Client → Authorization Server → User Consent → Authorization Code
|
|
38
|
-
Client → Exchange Code → Access Token
|
|
39
|
-
Client → API (with Access Token)
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Implementation:**
|
|
43
|
-
```python
|
|
44
|
-
from authlib.integrations.flask_client import OAuth
|
|
45
|
-
|
|
46
|
-
oauth = OAuth(app)
|
|
47
|
-
oauth.register(
|
|
48
|
-
name='google',
|
|
49
|
-
client_id=CLIENT_ID,
|
|
50
|
-
client_secret=CLIENT_SECRET,
|
|
51
|
-
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
|
|
52
|
-
client_kwargs={'scope': 'openid email profile'}
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
@app.route('/login')
|
|
56
|
-
def login():
|
|
57
|
-
return oauth.google.authorize_redirect(redirect_uri=url_for('callback', _external=True))
|
|
58
|
-
|
|
59
|
-
@app.route('/callback')
|
|
60
|
-
def callback():
|
|
61
|
-
token = oauth.google.authorize_access_token()
|
|
62
|
-
user_info = token['userinfo']
|
|
63
|
-
return user_info
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
**Refresh-Token Flow:**
|
|
67
|
-
|
|
68
|
-
**Use Case:** Long-lived API access without user re-authentication
|
|
69
|
-
|
|
70
|
-
**Pattern:**
|
|
71
|
-
```
|
|
72
|
-
Client → Exchange refresh_token → Access Token
|
|
73
|
-
Client → API (with Access Token)
|
|
74
|
-
Client → Refresh before expiry → New Access Token
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
**Implementation:**
|
|
78
|
-
```python
|
|
79
|
-
import os
|
|
80
|
-
import time
|
|
81
|
-
from typing import Any
|
|
82
|
-
|
|
83
|
-
import requests
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class OAuth2RefreshTokenClient:
|
|
87
|
-
"""
|
|
88
|
-
OAuth2 client using refresh-token flow for long-lived API access.
|
|
89
|
-
|
|
90
|
-
This pattern is used by many SaaS APIs that require
|
|
91
|
-
long-term access without user re-authentication.
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
def __init__(
|
|
95
|
-
self,
|
|
96
|
-
client_id: str,
|
|
97
|
-
client_secret: str,
|
|
98
|
-
refresh_token: str,
|
|
99
|
-
token_url: str,
|
|
100
|
-
api_base_url: str | None = None,
|
|
101
|
-
timeout_s: int = 30,
|
|
102
|
-
):
|
|
103
|
-
self.client_id = client_id
|
|
104
|
-
self.client_secret = client_secret
|
|
105
|
-
self.refresh_token = refresh_token
|
|
106
|
-
self.token_url = token_url
|
|
107
|
-
self.api_base_url = api_base_url.rstrip("/") if api_base_url else None
|
|
108
|
-
self.timeout_s = timeout_s
|
|
109
|
-
|
|
110
|
-
self._access_token: str | None = None
|
|
111
|
-
self._access_token_expiry_epoch: float = 0.0 # unix epoch seconds
|
|
112
|
-
|
|
113
|
-
def _refresh_access_token(self) -> str:
|
|
114
|
-
"""
|
|
115
|
-
Exchange refresh_token for access_token.
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
The new access token string.
|
|
119
|
-
|
|
120
|
-
Raises:
|
|
121
|
-
RuntimeError: If the token response is missing access_token.
|
|
122
|
-
requests.RequestException: If the token refresh request fails.
|
|
123
|
-
"""
|
|
124
|
-
resp = requests.post(
|
|
125
|
-
self.token_url,
|
|
126
|
-
data={
|
|
127
|
-
"refresh_token": self.refresh_token,
|
|
128
|
-
"client_id": self.client_id,
|
|
129
|
-
"client_secret": self.client_secret,
|
|
130
|
-
"grant_type": "refresh_token",
|
|
131
|
-
},
|
|
132
|
-
timeout=self.timeout_s,
|
|
133
|
-
)
|
|
134
|
-
resp.raise_for_status()
|
|
135
|
-
payload = resp.json()
|
|
136
|
-
|
|
137
|
-
if "access_token" not in payload:
|
|
138
|
-
raise RuntimeError("Token response missing access_token")
|
|
139
|
-
|
|
140
|
-
access_token = payload["access_token"]
|
|
141
|
-
|
|
142
|
-
# Some providers use expires_in_sec, others use expires_in (handle both)
|
|
143
|
-
expires_in = payload.get("expires_in_sec", payload.get("expires_in", 3600))
|
|
144
|
-
|
|
145
|
-
# Refresh proactively (e.g. 60 seconds before expiry) to avoid race conditions
|
|
146
|
-
self._access_token_expiry_epoch = time.time() + int(expires_in) - 60
|
|
147
|
-
self._access_token = access_token
|
|
148
|
-
return access_token
|
|
149
|
-
|
|
150
|
-
def _get_access_token(self) -> str:
|
|
151
|
-
"""
|
|
152
|
-
Get valid access token, refreshing if necessary.
|
|
153
|
-
|
|
154
|
-
Returns:
|
|
155
|
-
Valid access token string.
|
|
156
|
-
"""
|
|
157
|
-
if self._access_token and time.time() < self._access_token_expiry_epoch:
|
|
158
|
-
return self._access_token
|
|
159
|
-
return self._refresh_access_token()
|
|
160
|
-
|
|
161
|
-
def _headers(self) -> dict[str, str]:
|
|
162
|
-
"""
|
|
163
|
-
Get HTTP headers for authenticated requests.
|
|
164
|
-
|
|
165
|
-
Returns:
|
|
166
|
-
Dictionary with Authorization and Accept headers.
|
|
167
|
-
"""
|
|
168
|
-
token = self._get_access_token()
|
|
169
|
-
return {
|
|
170
|
-
"Authorization": f"Bearer {token}", # Standard OAuth2 header
|
|
171
|
-
"Accept": "application/json",
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
def get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
175
|
-
"""
|
|
176
|
-
Make authenticated GET request.
|
|
177
|
-
|
|
178
|
-
Args:
|
|
179
|
-
path: API endpoint path
|
|
180
|
-
params: Optional query parameters
|
|
181
|
-
|
|
182
|
-
Returns:
|
|
183
|
-
JSON response as dictionary
|
|
184
|
-
"""
|
|
185
|
-
if not self.api_base_url:
|
|
186
|
-
raise ValueError("api_base_url not set")
|
|
187
|
-
|
|
188
|
-
url = f"{self.api_base_url}/{path.lstrip('/')}"
|
|
189
|
-
resp = requests.get(
|
|
190
|
-
url,
|
|
191
|
-
headers=self._headers(),
|
|
192
|
-
params=params,
|
|
193
|
-
timeout=self.timeout_s,
|
|
194
|
-
)
|
|
195
|
-
resp.raise_for_status()
|
|
196
|
-
return resp.json()
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
**Best Practices:**
|
|
200
|
-
- **Refresh proactively:** Refresh tokens 60 seconds before expiry to avoid race conditions
|
|
201
|
-
- **Handle both expiry formats:** Some providers use `expires_in_sec`, others use `expires_in` (handle both field names)
|
|
202
|
-
- **Cache access tokens:** Store tokens until near expiry to reduce API calls
|
|
203
|
-
- **Secure storage:** Use environment variables or secret managers for refresh tokens (never hardcode)
|
|
204
|
-
- **Error handling:** Handle token refresh failures gracefully (retry, exponential backoff)
|
|
205
|
-
- **Multi-region support:** Some providers have different endpoints for different data centers/regions
|
|
206
|
-
|
|
207
|
-
**Example Usage:**
|
|
208
|
-
```python
|
|
209
|
-
# Prefer environment variables for secrets
|
|
210
|
-
client = OAuth2RefreshTokenClient(
|
|
211
|
-
client_id=os.environ["OAUTH_CLIENT_ID"],
|
|
212
|
-
client_secret=os.environ["OAUTH_CLIENT_SECRET"],
|
|
213
|
-
refresh_token=os.environ["OAUTH_REFRESH_TOKEN"],
|
|
214
|
-
token_url="https://api.example.com/oauth/v2/token",
|
|
215
|
-
api_base_url="https://api.example.com/v1",
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
# Token refresh happens automatically
|
|
219
|
-
status = client.get("/current_status")
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### 3. JWT (JSON Web Tokens)
|
|
223
|
-
|
|
224
|
-
**Token Structure:**
|
|
225
|
-
```json
|
|
226
|
-
{
|
|
227
|
-
"header": {
|
|
228
|
-
"alg": "HS256",
|
|
229
|
-
"typ": "JWT"
|
|
230
|
-
},
|
|
231
|
-
"payload": {
|
|
232
|
-
"sub": "user123",
|
|
233
|
-
"exp": 1642233600,
|
|
234
|
-
"iat": 1642147200,
|
|
235
|
-
"roles": ["user", "admin"]
|
|
236
|
-
},
|
|
237
|
-
"signature": "..."
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**Generate Token:**
|
|
242
|
-
```python
|
|
243
|
-
import jwt
|
|
244
|
-
from datetime import datetime, timedelta
|
|
245
|
-
|
|
246
|
-
def generate_token(user):
|
|
247
|
-
payload = {
|
|
248
|
-
'sub': user.id,
|
|
249
|
-
'exp': datetime.utcnow() + timedelta(hours=1),
|
|
250
|
-
'iat': datetime.utcnow(),
|
|
251
|
-
'roles': user.roles
|
|
252
|
-
}
|
|
253
|
-
return jwt.encode(payload, SECRET_KEY, algorithm='HS256')
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
**Validate Token:**
|
|
257
|
-
```python
|
|
258
|
-
def validate_token(token):
|
|
259
|
-
try:
|
|
260
|
-
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
|
|
261
|
-
return payload
|
|
262
|
-
except jwt.ExpiredSignatureError:
|
|
263
|
-
return None # Token expired
|
|
264
|
-
except jwt.InvalidTokenError:
|
|
265
|
-
return None # Invalid token
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
### 4. mTLS (Mutual TLS)
|
|
269
|
-
|
|
270
|
-
**Both client and server authenticate:**
|
|
271
|
-
```python
|
|
272
|
-
import ssl
|
|
273
|
-
|
|
274
|
-
# Server
|
|
275
|
-
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
276
|
-
context.load_cert_chain('server.crt', 'server.key')
|
|
277
|
-
context.load_verify_locations('ca.crt')
|
|
278
|
-
context.verify_mode = ssl.CERT_REQUIRED
|
|
279
|
-
|
|
280
|
-
# Client
|
|
281
|
-
context = ssl.create_default_context()
|
|
282
|
-
context.load_cert_chain('client.crt', 'client.key')
|
|
283
|
-
context.load_verify_locations('ca.crt')
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### 5. Custom Authentication Headers
|
|
287
|
-
|
|
288
|
-
**Overview:** Some APIs use non-standard authentication headers instead of the standard `Authorization: Bearer <token>` format.
|
|
289
|
-
|
|
290
|
-
**Common Custom Headers:**
|
|
291
|
-
- `Authorization: Bearer <token>` (standard OAuth2)
|
|
292
|
-
- `X-API-Key: <key>` (API key authentication)
|
|
293
|
-
- `Authorization: Token <token>` (GitHub-style)
|
|
294
|
-
- `Authorization: <custom-prefix> <token>` (vendor-specific formats)
|
|
295
|
-
|
|
296
|
-
**Implementation:**
|
|
297
|
-
```python
|
|
298
|
-
def _headers(self) -> dict[str, str]:
|
|
299
|
-
"""
|
|
300
|
-
Get HTTP headers for authenticated requests.
|
|
301
|
-
|
|
302
|
-
Supports custom auth header formats based on API requirements.
|
|
303
|
-
"""
|
|
304
|
-
token = self._get_access_token()
|
|
305
|
-
|
|
306
|
-
# Custom header format (vendor-specific)
|
|
307
|
-
return {
|
|
308
|
-
"Authorization": f"CustomPrefix {token}", # Replace with API-specific format
|
|
309
|
-
"Accept": "application/json",
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
# Or standard OAuth2 format:
|
|
313
|
-
def _headers_standard(self) -> dict[str, str]:
|
|
314
|
-
"""Standard OAuth2 Bearer token format."""
|
|
315
|
-
token = self._get_access_token()
|
|
316
|
-
return {
|
|
317
|
-
"Authorization": f"Bearer {token}", # Standard OAuth2
|
|
318
|
-
"Accept": "application/json",
|
|
319
|
-
}
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
**Best Practices:**
|
|
323
|
-
- **Check API documentation:** Each API specifies its required header format
|
|
324
|
-
- **Support multiple formats:** Some clients need to support multiple APIs with different formats
|
|
325
|
-
- **Use configuration:** Make header format configurable rather than hardcoded
|
|
326
|
-
- **Document format:** Clearly document which header format your client uses
|
|
327
|
-
|
|
328
|
-
**Example: Multi-Format Support**
|
|
329
|
-
```python
|
|
330
|
-
class FlexibleOAuth2Client:
|
|
331
|
-
"""OAuth2 client that supports multiple auth header formats."""
|
|
332
|
-
|
|
333
|
-
def __init__(self, auth_header_format: str = "Bearer"):
|
|
334
|
-
"""
|
|
335
|
-
Args:
|
|
336
|
-
auth_header_format: Header format - "Bearer", "Token", "CustomPrefix", etc.
|
|
337
|
-
"""
|
|
338
|
-
self.auth_header_format = auth_header_format
|
|
339
|
-
|
|
340
|
-
def _headers(self) -> dict[str, str]:
|
|
341
|
-
token = self._get_access_token()
|
|
342
|
-
return {
|
|
343
|
-
"Authorization": f"{self.auth_header_format} {token}",
|
|
344
|
-
"Accept": "application/json",
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
# Usage:
|
|
348
|
-
custom_client = FlexibleOAuth2Client(auth_header_format="CustomPrefix")
|
|
349
|
-
github_client = FlexibleOAuth2Client(auth_header_format="Token")
|
|
350
|
-
standard_client = FlexibleOAuth2Client(auth_header_format="Bearer")
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
## Authorization Patterns
|
|
354
|
-
|
|
355
|
-
### 1. Role-Based Access Control (RBAC)
|
|
356
|
-
|
|
357
|
-
**Roles and Permissions:**
|
|
358
|
-
```python
|
|
359
|
-
ROLES = {
|
|
360
|
-
'admin': ['read', 'write', 'delete', 'manage_users'],
|
|
361
|
-
'user': ['read', 'write'],
|
|
362
|
-
'guest': ['read']
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
def check_permission(user, permission):
|
|
366
|
-
user_roles = user.roles
|
|
367
|
-
for role in user_roles:
|
|
368
|
-
if permission in ROLES.get(role, []):
|
|
369
|
-
return True
|
|
370
|
-
return False
|
|
371
|
-
|
|
372
|
-
@app.route('/api/users/<user_id>')
|
|
373
|
-
@require_permission('read')
|
|
374
|
-
def get_user(user_id):
|
|
375
|
-
return get_user_by_id(user_id)
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
### 2. Attribute-Based Access Control (ABAC)
|
|
379
|
-
|
|
380
|
-
**Fine-grained permissions:**
|
|
381
|
-
```python
|
|
382
|
-
def can_access_resource(user, resource, action):
|
|
383
|
-
# Check attributes
|
|
384
|
-
if action == 'read' and resource.owner_id == user.id:
|
|
385
|
-
return True
|
|
386
|
-
if action == 'delete' and user.role == 'admin':
|
|
387
|
-
return True
|
|
388
|
-
if resource.is_public and action == 'read':
|
|
389
|
-
return True
|
|
390
|
-
return False
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
## Input Validation
|
|
394
|
-
|
|
395
|
-
### Schema Validation
|
|
396
|
-
|
|
397
|
-
**Validate request data:**
|
|
398
|
-
```python
|
|
399
|
-
from marshmallow import Schema, fields, validate
|
|
400
|
-
|
|
401
|
-
class UserSchema(Schema):
|
|
402
|
-
name = fields.Str(required=True, validate=validate.Length(min=1, max=100))
|
|
403
|
-
email = fields.Email(required=True)
|
|
404
|
-
age = fields.Int(validate=validate.Range(min=0, max=150))
|
|
405
|
-
|
|
406
|
-
@app.route('/api/users', methods=['POST'])
|
|
407
|
-
def create_user():
|
|
408
|
-
schema = UserSchema()
|
|
409
|
-
try:
|
|
410
|
-
data = schema.load(request.json)
|
|
411
|
-
except ValidationError as err:
|
|
412
|
-
return jsonify({'errors': err.messages}), 400
|
|
413
|
-
|
|
414
|
-
user = create_user(data)
|
|
415
|
-
return jsonify(user), 201
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
### SQL Injection Prevention
|
|
419
|
-
|
|
420
|
-
**Use parameterized queries:**
|
|
421
|
-
```python
|
|
422
|
-
# Bad: SQL injection risk
|
|
423
|
-
query = f"SELECT * FROM users WHERE id = {user_id}"
|
|
424
|
-
|
|
425
|
-
# Good: Parameterized
|
|
426
|
-
query = "SELECT * FROM users WHERE id = %s"
|
|
427
|
-
cursor.execute(query, (user_id,))
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
### XSS Prevention
|
|
431
|
-
|
|
432
|
-
**Sanitize output:**
|
|
433
|
-
```python
|
|
434
|
-
from markupsafe import escape
|
|
435
|
-
|
|
436
|
-
@app.route('/api/users/<user_id>')
|
|
437
|
-
def get_user(user_id):
|
|
438
|
-
user = get_user_by_id(user_id)
|
|
439
|
-
# Escape user input in response
|
|
440
|
-
return jsonify({
|
|
441
|
-
'name': escape(user.name),
|
|
442
|
-
'bio': escape(user.bio)
|
|
443
|
-
})
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
## Encryption
|
|
447
|
-
|
|
448
|
-
### HTTPS/TLS
|
|
449
|
-
|
|
450
|
-
**Always use HTTPS:**
|
|
451
|
-
```python
|
|
452
|
-
# Force HTTPS redirect
|
|
453
|
-
@app.before_request
|
|
454
|
-
def force_https():
|
|
455
|
-
if request.headers.get('X-Forwarded-Proto') == 'http':
|
|
456
|
-
return redirect(request.url.replace('http://', 'https://'), code=301)
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
### Data Encryption at Rest
|
|
460
|
-
|
|
461
|
-
**Encrypt sensitive data:**
|
|
462
|
-
```python
|
|
463
|
-
from cryptography.fernet import Fernet
|
|
464
|
-
|
|
465
|
-
key = Fernet.generate_key()
|
|
466
|
-
cipher = Fernet(key)
|
|
467
|
-
|
|
468
|
-
def encrypt_field(value):
|
|
469
|
-
return cipher.encrypt(value.encode()).decode()
|
|
470
|
-
|
|
471
|
-
def decrypt_field(encrypted_value):
|
|
472
|
-
return cipher.decrypt(encrypted_value.encode()).decode()
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
## Security Headers
|
|
476
|
-
|
|
477
|
-
### Common Security Headers
|
|
478
|
-
|
|
479
|
-
```python
|
|
480
|
-
@app.after_request
|
|
481
|
-
def set_security_headers(response):
|
|
482
|
-
response.headers['X-Content-Type-Options'] = 'nosniff'
|
|
483
|
-
response.headers['X-Frame-Options'] = 'DENY'
|
|
484
|
-
response.headers['X-XSS-Protection'] = '1; mode=block'
|
|
485
|
-
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
|
|
486
|
-
response.headers['Content-Security-Policy'] = "default-src 'self'"
|
|
487
|
-
return response
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
## Rate Limiting
|
|
491
|
-
|
|
492
|
-
**Protect from abuse:**
|
|
493
|
-
```python
|
|
494
|
-
from flask_limiter import Limiter
|
|
495
|
-
from flask_limiter.util import get_remote_address
|
|
496
|
-
|
|
497
|
-
limiter = Limiter(
|
|
498
|
-
app,
|
|
499
|
-
key_func=get_remote_address,
|
|
500
|
-
default_limits=["200 per day", "50 per hour"]
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
@app.route('/api/users')
|
|
504
|
-
@limiter.limit("10 per minute")
|
|
505
|
-
def get_users():
|
|
506
|
-
return jsonify(users=[...])
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
## Best Practices
|
|
510
|
-
|
|
511
|
-
1. **Use HTTPS:** Always encrypt in transit
|
|
512
|
-
2. **Authenticate all requests:** No anonymous access
|
|
513
|
-
3. **Authorize properly:** Check permissions
|
|
514
|
-
4. **Validate input:** Sanitize all inputs
|
|
515
|
-
5. **Use parameterized queries:** Prevent SQL injection
|
|
516
|
-
6. **Set security headers:** X-Frame-Options, CSP, etc.
|
|
517
|
-
7. **Rate limit:** Prevent abuse
|
|
518
|
-
8. **Log security events:** Audit authentication/authorization
|
|
519
|
-
9. **Rotate secrets:** Regularly rotate keys and tokens
|
|
520
|
-
10. **Keep dependencies updated:** Patch vulnerabilities
|
|
521
|
-
|
|
1
|
+
# API Security Patterns
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
API security protects APIs from unauthorized access, data breaches, and attacks. It involves authentication, authorization, encryption, input validation, and threat protection.
|
|
6
|
+
|
|
7
|
+
## Authentication Patterns
|
|
8
|
+
|
|
9
|
+
### 1. API Keys
|
|
10
|
+
|
|
11
|
+
**Simple but Limited:**
|
|
12
|
+
```python
|
|
13
|
+
API_KEY_HEADER = 'X-API-Key'
|
|
14
|
+
|
|
15
|
+
def authenticate_api_key(request):
|
|
16
|
+
api_key = request.headers.get(API_KEY_HEADER)
|
|
17
|
+
if not api_key:
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
key_record = db.get_api_key(api_key)
|
|
21
|
+
if not key_record or not key_record.is_active:
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
return key_record.user
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Best Practices:**
|
|
28
|
+
- Store hashed keys
|
|
29
|
+
- Rotate regularly
|
|
30
|
+
- Scope permissions
|
|
31
|
+
- Rate limit per key
|
|
32
|
+
|
|
33
|
+
### 2. OAuth 2.0
|
|
34
|
+
|
|
35
|
+
**Authorization Code Flow:**
|
|
36
|
+
```
|
|
37
|
+
Client → Authorization Server → User Consent → Authorization Code
|
|
38
|
+
Client → Exchange Code → Access Token
|
|
39
|
+
Client → API (with Access Token)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Implementation:**
|
|
43
|
+
```python
|
|
44
|
+
from authlib.integrations.flask_client import OAuth
|
|
45
|
+
|
|
46
|
+
oauth = OAuth(app)
|
|
47
|
+
oauth.register(
|
|
48
|
+
name='google',
|
|
49
|
+
client_id=CLIENT_ID,
|
|
50
|
+
client_secret=CLIENT_SECRET,
|
|
51
|
+
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
|
|
52
|
+
client_kwargs={'scope': 'openid email profile'}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@app.route('/login')
|
|
56
|
+
def login():
|
|
57
|
+
return oauth.google.authorize_redirect(redirect_uri=url_for('callback', _external=True))
|
|
58
|
+
|
|
59
|
+
@app.route('/callback')
|
|
60
|
+
def callback():
|
|
61
|
+
token = oauth.google.authorize_access_token()
|
|
62
|
+
user_info = token['userinfo']
|
|
63
|
+
return user_info
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Refresh-Token Flow:**
|
|
67
|
+
|
|
68
|
+
**Use Case:** Long-lived API access without user re-authentication
|
|
69
|
+
|
|
70
|
+
**Pattern:**
|
|
71
|
+
```
|
|
72
|
+
Client → Exchange refresh_token → Access Token
|
|
73
|
+
Client → API (with Access Token)
|
|
74
|
+
Client → Refresh before expiry → New Access Token
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Implementation:**
|
|
78
|
+
```python
|
|
79
|
+
import os
|
|
80
|
+
import time
|
|
81
|
+
from typing import Any
|
|
82
|
+
|
|
83
|
+
import requests
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class OAuth2RefreshTokenClient:
|
|
87
|
+
"""
|
|
88
|
+
OAuth2 client using refresh-token flow for long-lived API access.
|
|
89
|
+
|
|
90
|
+
This pattern is used by many SaaS APIs that require
|
|
91
|
+
long-term access without user re-authentication.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
def __init__(
|
|
95
|
+
self,
|
|
96
|
+
client_id: str,
|
|
97
|
+
client_secret: str,
|
|
98
|
+
refresh_token: str,
|
|
99
|
+
token_url: str,
|
|
100
|
+
api_base_url: str | None = None,
|
|
101
|
+
timeout_s: int = 30,
|
|
102
|
+
):
|
|
103
|
+
self.client_id = client_id
|
|
104
|
+
self.client_secret = client_secret
|
|
105
|
+
self.refresh_token = refresh_token
|
|
106
|
+
self.token_url = token_url
|
|
107
|
+
self.api_base_url = api_base_url.rstrip("/") if api_base_url else None
|
|
108
|
+
self.timeout_s = timeout_s
|
|
109
|
+
|
|
110
|
+
self._access_token: str | None = None
|
|
111
|
+
self._access_token_expiry_epoch: float = 0.0 # unix epoch seconds
|
|
112
|
+
|
|
113
|
+
def _refresh_access_token(self) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Exchange refresh_token for access_token.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
The new access token string.
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
RuntimeError: If the token response is missing access_token.
|
|
122
|
+
requests.RequestException: If the token refresh request fails.
|
|
123
|
+
"""
|
|
124
|
+
resp = requests.post(
|
|
125
|
+
self.token_url,
|
|
126
|
+
data={
|
|
127
|
+
"refresh_token": self.refresh_token,
|
|
128
|
+
"client_id": self.client_id,
|
|
129
|
+
"client_secret": self.client_secret,
|
|
130
|
+
"grant_type": "refresh_token",
|
|
131
|
+
},
|
|
132
|
+
timeout=self.timeout_s,
|
|
133
|
+
)
|
|
134
|
+
resp.raise_for_status()
|
|
135
|
+
payload = resp.json()
|
|
136
|
+
|
|
137
|
+
if "access_token" not in payload:
|
|
138
|
+
raise RuntimeError("Token response missing access_token")
|
|
139
|
+
|
|
140
|
+
access_token = payload["access_token"]
|
|
141
|
+
|
|
142
|
+
# Some providers use expires_in_sec, others use expires_in (handle both)
|
|
143
|
+
expires_in = payload.get("expires_in_sec", payload.get("expires_in", 3600))
|
|
144
|
+
|
|
145
|
+
# Refresh proactively (e.g. 60 seconds before expiry) to avoid race conditions
|
|
146
|
+
self._access_token_expiry_epoch = time.time() + int(expires_in) - 60
|
|
147
|
+
self._access_token = access_token
|
|
148
|
+
return access_token
|
|
149
|
+
|
|
150
|
+
def _get_access_token(self) -> str:
|
|
151
|
+
"""
|
|
152
|
+
Get valid access token, refreshing if necessary.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Valid access token string.
|
|
156
|
+
"""
|
|
157
|
+
if self._access_token and time.time() < self._access_token_expiry_epoch:
|
|
158
|
+
return self._access_token
|
|
159
|
+
return self._refresh_access_token()
|
|
160
|
+
|
|
161
|
+
def _headers(self) -> dict[str, str]:
|
|
162
|
+
"""
|
|
163
|
+
Get HTTP headers for authenticated requests.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
Dictionary with Authorization and Accept headers.
|
|
167
|
+
"""
|
|
168
|
+
token = self._get_access_token()
|
|
169
|
+
return {
|
|
170
|
+
"Authorization": f"Bearer {token}", # Standard OAuth2 header
|
|
171
|
+
"Accept": "application/json",
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
def get(self, path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
175
|
+
"""
|
|
176
|
+
Make authenticated GET request.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
path: API endpoint path
|
|
180
|
+
params: Optional query parameters
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
JSON response as dictionary
|
|
184
|
+
"""
|
|
185
|
+
if not self.api_base_url:
|
|
186
|
+
raise ValueError("api_base_url not set")
|
|
187
|
+
|
|
188
|
+
url = f"{self.api_base_url}/{path.lstrip('/')}"
|
|
189
|
+
resp = requests.get(
|
|
190
|
+
url,
|
|
191
|
+
headers=self._headers(),
|
|
192
|
+
params=params,
|
|
193
|
+
timeout=self.timeout_s,
|
|
194
|
+
)
|
|
195
|
+
resp.raise_for_status()
|
|
196
|
+
return resp.json()
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Best Practices:**
|
|
200
|
+
- **Refresh proactively:** Refresh tokens 60 seconds before expiry to avoid race conditions
|
|
201
|
+
- **Handle both expiry formats:** Some providers use `expires_in_sec`, others use `expires_in` (handle both field names)
|
|
202
|
+
- **Cache access tokens:** Store tokens until near expiry to reduce API calls
|
|
203
|
+
- **Secure storage:** Use environment variables or secret managers for refresh tokens (never hardcode)
|
|
204
|
+
- **Error handling:** Handle token refresh failures gracefully (retry, exponential backoff)
|
|
205
|
+
- **Multi-region support:** Some providers have different endpoints for different data centers/regions
|
|
206
|
+
|
|
207
|
+
**Example Usage:**
|
|
208
|
+
```python
|
|
209
|
+
# Prefer environment variables for secrets
|
|
210
|
+
client = OAuth2RefreshTokenClient(
|
|
211
|
+
client_id=os.environ["OAUTH_CLIENT_ID"],
|
|
212
|
+
client_secret=os.environ["OAUTH_CLIENT_SECRET"],
|
|
213
|
+
refresh_token=os.environ["OAUTH_REFRESH_TOKEN"],
|
|
214
|
+
token_url="https://api.example.com/oauth/v2/token",
|
|
215
|
+
api_base_url="https://api.example.com/v1",
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# Token refresh happens automatically
|
|
219
|
+
status = client.get("/current_status")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 3. JWT (JSON Web Tokens)
|
|
223
|
+
|
|
224
|
+
**Token Structure:**
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"header": {
|
|
228
|
+
"alg": "HS256",
|
|
229
|
+
"typ": "JWT"
|
|
230
|
+
},
|
|
231
|
+
"payload": {
|
|
232
|
+
"sub": "user123",
|
|
233
|
+
"exp": 1642233600,
|
|
234
|
+
"iat": 1642147200,
|
|
235
|
+
"roles": ["user", "admin"]
|
|
236
|
+
},
|
|
237
|
+
"signature": "..."
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Generate Token:**
|
|
242
|
+
```python
|
|
243
|
+
import jwt
|
|
244
|
+
from datetime import datetime, timedelta
|
|
245
|
+
|
|
246
|
+
def generate_token(user):
|
|
247
|
+
payload = {
|
|
248
|
+
'sub': user.id,
|
|
249
|
+
'exp': datetime.utcnow() + timedelta(hours=1),
|
|
250
|
+
'iat': datetime.utcnow(),
|
|
251
|
+
'roles': user.roles
|
|
252
|
+
}
|
|
253
|
+
return jwt.encode(payload, SECRET_KEY, algorithm='HS256')
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Validate Token:**
|
|
257
|
+
```python
|
|
258
|
+
def validate_token(token):
|
|
259
|
+
try:
|
|
260
|
+
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
|
|
261
|
+
return payload
|
|
262
|
+
except jwt.ExpiredSignatureError:
|
|
263
|
+
return None # Token expired
|
|
264
|
+
except jwt.InvalidTokenError:
|
|
265
|
+
return None # Invalid token
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 4. mTLS (Mutual TLS)
|
|
269
|
+
|
|
270
|
+
**Both client and server authenticate:**
|
|
271
|
+
```python
|
|
272
|
+
import ssl
|
|
273
|
+
|
|
274
|
+
# Server
|
|
275
|
+
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
|
276
|
+
context.load_cert_chain('server.crt', 'server.key')
|
|
277
|
+
context.load_verify_locations('ca.crt')
|
|
278
|
+
context.verify_mode = ssl.CERT_REQUIRED
|
|
279
|
+
|
|
280
|
+
# Client
|
|
281
|
+
context = ssl.create_default_context()
|
|
282
|
+
context.load_cert_chain('client.crt', 'client.key')
|
|
283
|
+
context.load_verify_locations('ca.crt')
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 5. Custom Authentication Headers
|
|
287
|
+
|
|
288
|
+
**Overview:** Some APIs use non-standard authentication headers instead of the standard `Authorization: Bearer <token>` format.
|
|
289
|
+
|
|
290
|
+
**Common Custom Headers:**
|
|
291
|
+
- `Authorization: Bearer <token>` (standard OAuth2)
|
|
292
|
+
- `X-API-Key: <key>` (API key authentication)
|
|
293
|
+
- `Authorization: Token <token>` (GitHub-style)
|
|
294
|
+
- `Authorization: <custom-prefix> <token>` (vendor-specific formats)
|
|
295
|
+
|
|
296
|
+
**Implementation:**
|
|
297
|
+
```python
|
|
298
|
+
def _headers(self) -> dict[str, str]:
|
|
299
|
+
"""
|
|
300
|
+
Get HTTP headers for authenticated requests.
|
|
301
|
+
|
|
302
|
+
Supports custom auth header formats based on API requirements.
|
|
303
|
+
"""
|
|
304
|
+
token = self._get_access_token()
|
|
305
|
+
|
|
306
|
+
# Custom header format (vendor-specific)
|
|
307
|
+
return {
|
|
308
|
+
"Authorization": f"CustomPrefix {token}", # Replace with API-specific format
|
|
309
|
+
"Accept": "application/json",
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
# Or standard OAuth2 format:
|
|
313
|
+
def _headers_standard(self) -> dict[str, str]:
|
|
314
|
+
"""Standard OAuth2 Bearer token format."""
|
|
315
|
+
token = self._get_access_token()
|
|
316
|
+
return {
|
|
317
|
+
"Authorization": f"Bearer {token}", # Standard OAuth2
|
|
318
|
+
"Accept": "application/json",
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Best Practices:**
|
|
323
|
+
- **Check API documentation:** Each API specifies its required header format
|
|
324
|
+
- **Support multiple formats:** Some clients need to support multiple APIs with different formats
|
|
325
|
+
- **Use configuration:** Make header format configurable rather than hardcoded
|
|
326
|
+
- **Document format:** Clearly document which header format your client uses
|
|
327
|
+
|
|
328
|
+
**Example: Multi-Format Support**
|
|
329
|
+
```python
|
|
330
|
+
class FlexibleOAuth2Client:
|
|
331
|
+
"""OAuth2 client that supports multiple auth header formats."""
|
|
332
|
+
|
|
333
|
+
def __init__(self, auth_header_format: str = "Bearer"):
|
|
334
|
+
"""
|
|
335
|
+
Args:
|
|
336
|
+
auth_header_format: Header format - "Bearer", "Token", "CustomPrefix", etc.
|
|
337
|
+
"""
|
|
338
|
+
self.auth_header_format = auth_header_format
|
|
339
|
+
|
|
340
|
+
def _headers(self) -> dict[str, str]:
|
|
341
|
+
token = self._get_access_token()
|
|
342
|
+
return {
|
|
343
|
+
"Authorization": f"{self.auth_header_format} {token}",
|
|
344
|
+
"Accept": "application/json",
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
# Usage:
|
|
348
|
+
custom_client = FlexibleOAuth2Client(auth_header_format="CustomPrefix")
|
|
349
|
+
github_client = FlexibleOAuth2Client(auth_header_format="Token")
|
|
350
|
+
standard_client = FlexibleOAuth2Client(auth_header_format="Bearer")
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Authorization Patterns
|
|
354
|
+
|
|
355
|
+
### 1. Role-Based Access Control (RBAC)
|
|
356
|
+
|
|
357
|
+
**Roles and Permissions:**
|
|
358
|
+
```python
|
|
359
|
+
ROLES = {
|
|
360
|
+
'admin': ['read', 'write', 'delete', 'manage_users'],
|
|
361
|
+
'user': ['read', 'write'],
|
|
362
|
+
'guest': ['read']
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
def check_permission(user, permission):
|
|
366
|
+
user_roles = user.roles
|
|
367
|
+
for role in user_roles:
|
|
368
|
+
if permission in ROLES.get(role, []):
|
|
369
|
+
return True
|
|
370
|
+
return False
|
|
371
|
+
|
|
372
|
+
@app.route('/api/users/<user_id>')
|
|
373
|
+
@require_permission('read')
|
|
374
|
+
def get_user(user_id):
|
|
375
|
+
return get_user_by_id(user_id)
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### 2. Attribute-Based Access Control (ABAC)
|
|
379
|
+
|
|
380
|
+
**Fine-grained permissions:**
|
|
381
|
+
```python
|
|
382
|
+
def can_access_resource(user, resource, action):
|
|
383
|
+
# Check attributes
|
|
384
|
+
if action == 'read' and resource.owner_id == user.id:
|
|
385
|
+
return True
|
|
386
|
+
if action == 'delete' and user.role == 'admin':
|
|
387
|
+
return True
|
|
388
|
+
if resource.is_public and action == 'read':
|
|
389
|
+
return True
|
|
390
|
+
return False
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## Input Validation
|
|
394
|
+
|
|
395
|
+
### Schema Validation
|
|
396
|
+
|
|
397
|
+
**Validate request data:**
|
|
398
|
+
```python
|
|
399
|
+
from marshmallow import Schema, fields, validate
|
|
400
|
+
|
|
401
|
+
class UserSchema(Schema):
|
|
402
|
+
name = fields.Str(required=True, validate=validate.Length(min=1, max=100))
|
|
403
|
+
email = fields.Email(required=True)
|
|
404
|
+
age = fields.Int(validate=validate.Range(min=0, max=150))
|
|
405
|
+
|
|
406
|
+
@app.route('/api/users', methods=['POST'])
|
|
407
|
+
def create_user():
|
|
408
|
+
schema = UserSchema()
|
|
409
|
+
try:
|
|
410
|
+
data = schema.load(request.json)
|
|
411
|
+
except ValidationError as err:
|
|
412
|
+
return jsonify({'errors': err.messages}), 400
|
|
413
|
+
|
|
414
|
+
user = create_user(data)
|
|
415
|
+
return jsonify(user), 201
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### SQL Injection Prevention
|
|
419
|
+
|
|
420
|
+
**Use parameterized queries:**
|
|
421
|
+
```python
|
|
422
|
+
# Bad: SQL injection risk
|
|
423
|
+
query = f"SELECT * FROM users WHERE id = {user_id}"
|
|
424
|
+
|
|
425
|
+
# Good: Parameterized
|
|
426
|
+
query = "SELECT * FROM users WHERE id = %s"
|
|
427
|
+
cursor.execute(query, (user_id,))
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### XSS Prevention
|
|
431
|
+
|
|
432
|
+
**Sanitize output:**
|
|
433
|
+
```python
|
|
434
|
+
from markupsafe import escape
|
|
435
|
+
|
|
436
|
+
@app.route('/api/users/<user_id>')
|
|
437
|
+
def get_user(user_id):
|
|
438
|
+
user = get_user_by_id(user_id)
|
|
439
|
+
# Escape user input in response
|
|
440
|
+
return jsonify({
|
|
441
|
+
'name': escape(user.name),
|
|
442
|
+
'bio': escape(user.bio)
|
|
443
|
+
})
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Encryption
|
|
447
|
+
|
|
448
|
+
### HTTPS/TLS
|
|
449
|
+
|
|
450
|
+
**Always use HTTPS:**
|
|
451
|
+
```python
|
|
452
|
+
# Force HTTPS redirect
|
|
453
|
+
@app.before_request
|
|
454
|
+
def force_https():
|
|
455
|
+
if request.headers.get('X-Forwarded-Proto') == 'http':
|
|
456
|
+
return redirect(request.url.replace('http://', 'https://'), code=301)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Data Encryption at Rest
|
|
460
|
+
|
|
461
|
+
**Encrypt sensitive data:**
|
|
462
|
+
```python
|
|
463
|
+
from cryptography.fernet import Fernet
|
|
464
|
+
|
|
465
|
+
key = Fernet.generate_key()
|
|
466
|
+
cipher = Fernet(key)
|
|
467
|
+
|
|
468
|
+
def encrypt_field(value):
|
|
469
|
+
return cipher.encrypt(value.encode()).decode()
|
|
470
|
+
|
|
471
|
+
def decrypt_field(encrypted_value):
|
|
472
|
+
return cipher.decrypt(encrypted_value.encode()).decode()
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Security Headers
|
|
476
|
+
|
|
477
|
+
### Common Security Headers
|
|
478
|
+
|
|
479
|
+
```python
|
|
480
|
+
@app.after_request
|
|
481
|
+
def set_security_headers(response):
|
|
482
|
+
response.headers['X-Content-Type-Options'] = 'nosniff'
|
|
483
|
+
response.headers['X-Frame-Options'] = 'DENY'
|
|
484
|
+
response.headers['X-XSS-Protection'] = '1; mode=block'
|
|
485
|
+
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
|
|
486
|
+
response.headers['Content-Security-Policy'] = "default-src 'self'"
|
|
487
|
+
return response
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
## Rate Limiting
|
|
491
|
+
|
|
492
|
+
**Protect from abuse:**
|
|
493
|
+
```python
|
|
494
|
+
from flask_limiter import Limiter
|
|
495
|
+
from flask_limiter.util import get_remote_address
|
|
496
|
+
|
|
497
|
+
limiter = Limiter(
|
|
498
|
+
app,
|
|
499
|
+
key_func=get_remote_address,
|
|
500
|
+
default_limits=["200 per day", "50 per hour"]
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
@app.route('/api/users')
|
|
504
|
+
@limiter.limit("10 per minute")
|
|
505
|
+
def get_users():
|
|
506
|
+
return jsonify(users=[...])
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
## Best Practices
|
|
510
|
+
|
|
511
|
+
1. **Use HTTPS:** Always encrypt in transit
|
|
512
|
+
2. **Authenticate all requests:** No anonymous access
|
|
513
|
+
3. **Authorize properly:** Check permissions
|
|
514
|
+
4. **Validate input:** Sanitize all inputs
|
|
515
|
+
5. **Use parameterized queries:** Prevent SQL injection
|
|
516
|
+
6. **Set security headers:** X-Frame-Options, CSP, etc.
|
|
517
|
+
7. **Rate limit:** Prevent abuse
|
|
518
|
+
8. **Log security events:** Audit authentication/authorization
|
|
519
|
+
9. **Rotate secrets:** Regularly rotate keys and tokens
|
|
520
|
+
10. **Keep dependencies updated:** Patch vulnerabilities
|
|
521
|
+
|