claudecode-omc 5.11.0 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/manifest.json +3 -3
- package/bundled/upstream/anthropic-skills/.omc-source/bundle.json +2 -2
- package/bundled/upstream/anthropic-skills/.omc-source/provenance.json +394 -390
- package/bundled/upstream/anthropic-skills/skills/claude-api/SKILL.md +60 -29
- package/bundled/upstream/anthropic-skills/skills/claude-api/csharp/claude-api.md +46 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/curl/examples.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/curl/managed-agents.md +3 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/go/claude-api.md +23 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/java/claude-api.md +32 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/php/claude-api.md +27 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/README.md +123 -7
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/batches.md +13 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/files-api.md +7 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/streaming.md +18 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/managed-agents/README.md +9 -7
- package/bundled/upstream/anthropic-skills/skills/claude-api/ruby/claude-api.md +27 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/agent-design.md +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/anthropic-cli.md +246 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/claude-platform-on-aws.md +59 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/error-codes.md +24 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/live-sources.md +8 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-api-reference.md +48 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-client-patterns.md +3 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-core.md +15 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-environments.md +10 -6
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-events.md +25 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-onboarding.md +48 -18
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-overview.md +8 -5
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-scheduled-deployments.md +144 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +2 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-tools.md +46 -9
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/model-migration.md +259 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/models.md +17 -9
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/prompt-caching.md +55 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/token-counting.md +56 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/tool-use-concepts.md +22 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/README.md +45 -6
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/streaming.md +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/managed-agents/README.md +10 -12
- package/bundled/upstream/anthropic-skills/skills/frontend-design/SKILL.md +39 -26
- package/bundled/upstream/ecc/.omc-source/bundle.json +2 -2
- package/bundled/upstream/ecc/.omc-source/manifests/.claude-plugin/marketplace.json +2 -2
- package/bundled/upstream/ecc/.omc-source/provenance.json +602 -550
- package/bundled/upstream/ecc/agents/agent-evaluator.md +206 -0
- package/bundled/upstream/ecc/agents/performance-optimizer.md +9 -9
- package/bundled/upstream/ecc/agents/php-reviewer.md +109 -0
- package/bundled/upstream/ecc/agents/spec-miner.md +217 -0
- package/bundled/upstream/ecc/agents/vue-reviewer.md +206 -0
- package/bundled/upstream/ecc/commands/cost-report.md +58 -84
- package/bundled/upstream/ecc/commands/epic-claim.md +26 -0
- package/bundled/upstream/ecc/commands/epic-decompose.md +23 -0
- package/bundled/upstream/ecc/commands/epic-publish.md +23 -0
- package/bundled/upstream/ecc/commands/epic-review.md +23 -0
- package/bundled/upstream/ecc/commands/epic-sync.md +23 -0
- package/bundled/upstream/ecc/commands/epic-unblock.md +22 -0
- package/bundled/upstream/ecc/commands/epic-validate.md +22 -0
- package/bundled/upstream/ecc/commands/instinct-status.md +8 -8
- package/bundled/upstream/ecc/commands/multi-backend.md +2 -0
- package/bundled/upstream/ecc/commands/multi-execute.md +2 -0
- package/bundled/upstream/ecc/commands/multi-frontend.md +2 -0
- package/bundled/upstream/ecc/commands/multi-plan.md +2 -0
- package/bundled/upstream/ecc/commands/multi-workflow.md +2 -0
- package/bundled/upstream/ecc/commands/orch-add-feature.md +36 -0
- package/bundled/upstream/ecc/commands/orch-build-mvp.md +36 -0
- package/bundled/upstream/ecc/commands/orch-change-feature.md +38 -0
- package/bundled/upstream/ecc/commands/orch-fix-defect.md +38 -0
- package/bundled/upstream/ecc/commands/orch-refine-code.md +39 -0
- package/bundled/upstream/ecc/commands/quality-gate.md +34 -16
- package/bundled/upstream/ecc/commands/vue-review.md +174 -0
- package/bundled/upstream/ecc/skills/accessibility/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agent-architecture-audit/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agent-eval/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agent-harness-construction/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agent-introspection-debugging/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agent-payment-x402/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agent-self-evaluation/SKILL.md +182 -0
- package/bundled/upstream/ecc/skills/agent-self-evaluation/examples/high-score-example.md +87 -0
- package/bundled/upstream/ecc/skills/agent-self-evaluation/examples/low-score-example.md +86 -0
- package/bundled/upstream/ecc/skills/agent-self-evaluation/references/evaluation-criteria.md +71 -0
- package/bundled/upstream/ecc/skills/agent-self-evaluation/references/hook-integration.md +64 -0
- package/bundled/upstream/ecc/skills/agent-self-evaluation/scripts/evaluate.py +408 -0
- package/bundled/upstream/ecc/skills/agent-self-evaluation/templates/evaluation-report.md +86 -0
- package/bundled/upstream/ecc/skills/agent-sort/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agentic-engineering/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/agentic-os/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ai-first-engineering/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ai-regression-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/android-clean-architecture/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/angular-developer/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/api-connector-builder/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/api-design/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/architecture-decision-records/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/article-writing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/automation-audit-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/autonomous-agent-harness/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/autonomous-loops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/backend-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/benchmark/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/benchmark-methodology/SKILL.md +190 -0
- package/bundled/upstream/ecc/skills/benchmark-optimization-loop/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/blender-motion-state-inspection/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/blueprint/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/brand-discovery/SKILL.md +145 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/10_purpose-why.md +40 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/20_positioning.md +44 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/30_audience-niche.md +52 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/40_personality-archetype.md +57 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/50_voice-tone.md +59 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/60_narrative-story.md +50 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/70_founder-tension.md +49 -0
- package/bundled/upstream/ecc/skills/brand-discovery/references/90_SYNTHESIS.md +133 -0
- package/bundled/upstream/ecc/skills/brand-voice/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/browser-qa/SKILL.md +22 -4
- package/bundled/upstream/ecc/skills/bun-runtime/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/canary-watch/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/carrier-relationship-management/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/cisco-ios-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ck/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/claude-devfleet/SKILL.md +11 -2
- package/bundled/upstream/ecc/skills/click-path-audit/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/clickhouse-io/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/code-tour/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/codebase-onboarding/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/codehealth-mcp/SKILL.md +167 -0
- package/bundled/upstream/ecc/skills/coding-standards/SKILL.md +4 -2
- package/bundled/upstream/ecc/skills/competitive-platform-analysis/SKILL.md +214 -0
- package/bundled/upstream/ecc/skills/competitive-report-structure/SKILL.md +162 -0
- package/bundled/upstream/ecc/skills/compose-multiplatform-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/config-gc/SKILL.md +120 -0
- package/bundled/upstream/ecc/skills/configure-ecc/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/connections-optimizer/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/content-engine/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/content-hash-cache-pattern/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/context-budget/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/continuous-agent-loop/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/continuous-learning/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/continuous-learning-v2/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/observer-loop.sh +14 -1
- package/bundled/upstream/ecc/skills/continuous-learning-v2/hooks/observe.sh +31 -7
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/instinct-cli.py +90 -2
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/test_parse_instinct.py +27 -0
- package/bundled/upstream/ecc/skills/cost-aware-llm-pipeline/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/cost-tracking/SKILL.md +58 -108
- package/bundled/upstream/ecc/skills/council/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/cpp-coding-standards/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/cpp-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/crosspost/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/csharp-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/customer-billing-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/customs-trade-compliance/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/dart-flutter-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/dashboard-builder/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/data-scraper-agent/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/data-throughput-accelerator/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/database-migrations/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/deep-research/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/defi-amm-security/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/deployment-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/design-system/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/django-celery/SKILL.md +3 -2
- package/bundled/upstream/ecc/skills/django-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/django-security/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/django-tdd/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/django-verification/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/dmux-workflows/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/docker-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/documentation-lookup/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/dotnet-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/dynamic-workflow-mode/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/e2e-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ecc-guide/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ecc-tools-cost-audit/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/email-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/energy-procurement/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/enterprise-agent-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/error-handling/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/eval-harness/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/evm-token-decimals/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/exa-search/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/fal-ai-media/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/fastapi-patterns/SKILL.md +375 -188
- package/bundled/upstream/ecc/skills/finance-billing-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/flox-environments/SKILL.md +3 -2
- package/bundled/upstream/ecc/skills/flutter-dart-code-review/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/frontend-a11y/SKILL.md +3 -3
- package/bundled/upstream/ecc/skills/frontend-design-direction/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/frontend-patterns/SKILL.md +23 -8
- package/bundled/upstream/ecc/skills/frontend-slides/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/frontend-slides/scripts/export-pdf.sh +1 -1
- package/bundled/upstream/ecc/skills/fsharp-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/gan-style-harness/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/gateguard/SKILL.md +9 -1
- package/bundled/upstream/ecc/skills/generating-python-installer/SKILL.md +820 -0
- package/bundled/upstream/ecc/skills/git-workflow/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/github-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/golang-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/golang-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/google-workspace-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/healthcare-cdss-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/healthcare-emr-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/healthcare-eval-harness/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/healthcare-phi-compliance/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/hermes-imports/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/hexagonal-architecture/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/hipaa-compliance/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/homelab-network-readiness/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/homelab-network-setup/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/homelab-pihole-dns/SKILL.md +10 -9
- package/bundled/upstream/ecc/skills/homelab-vlan-segmentation/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/homelab-wireguard-vpn/SKILL.md +4 -3
- package/bundled/upstream/ecc/skills/inherit-legacy-style/SKILL.md +157 -0
- package/bundled/upstream/ecc/skills/intent-driven-development/SKILL.md +360 -0
- package/bundled/upstream/ecc/skills/inventory-demand-planning/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/investor-materials/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/investor-outreach/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ios-icon-gen/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/iterative-retrieval/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ito-basket-compare/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ito-data-atlas-agent/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ito-market-intelligence/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ito-trade-planner/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/java-coding-standards/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/jira-integration/SKILL.md +17 -7
- package/bundled/upstream/ecc/skills/jpa-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/knowledge-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/kotlin-coroutines-flows/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/kotlin-exposed-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/kotlin-ktor-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/kotlin-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/kotlin-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/kubernetes-patterns/SKILL.md +756 -0
- package/bundled/upstream/ecc/skills/laravel-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/laravel-plugin-discovery/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/laravel-security/SKILL.md +826 -163
- package/bundled/upstream/ecc/skills/laravel-tdd/SKILL.md +541 -149
- package/bundled/upstream/ecc/skills/laravel-verification/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/latency-critical-systems/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/lead-intelligence/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/llm-trading-agent-security/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/logistics-exception-management/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/make-interfaces-feel-better/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/manim-video/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/market-research/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/marketing-campaign/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/mcp-server-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/messages-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ml-adoption-playbook/SKILL.md +57 -0
- package/bundled/upstream/ecc/skills/mle-workflow/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/motion-patterns/SKILL.md +1 -2
- package/bundled/upstream/ecc/skills/motion-ui/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/mysql-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/nanoclaw-repl/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/nestjs-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/netmiko-ssh-automation/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/network-bgp-diagnostics/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/network-config-validation/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/network-interface-health/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/nextjs-turbopack/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/nodejs-keccak256/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/nutrient-document-processing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/nuxt4-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/openclaw-persona-forge/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/opensource-pipeline/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/orch-add-feature/SKILL.md +45 -0
- package/bundled/upstream/ecc/skills/orch-build-mvp/SKILL.md +49 -0
- package/bundled/upstream/ecc/skills/orch-change-feature/SKILL.md +43 -0
- package/bundled/upstream/ecc/skills/orch-fix-defect/SKILL.md +43 -0
- package/bundled/upstream/ecc/skills/orch-pipeline/SKILL.md +121 -0
- package/bundled/upstream/ecc/skills/orch-refine-code/SKILL.md +44 -0
- package/bundled/upstream/ecc/skills/parallel-execution-optimizer/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/perl-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/perl-security/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/perl-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/plan-orchestrate/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/plankton-code-quality/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/postgres-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/prediction-market-oracle-research/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/prediction-market-risk-review/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/prisma-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/product-capability/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/product-lens/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/production-audit/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/production-scheduling/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/project-flow-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/prompt-optimizer/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/python-patterns/SKILL.md +4 -3
- package/bundled/upstream/ecc/skills/python-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/pytorch-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/quality-nonconformance/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/quarkus-patterns/SKILL.md +51 -50
- package/bundled/upstream/ecc/skills/quarkus-security/SKILL.md +25 -24
- package/bundled/upstream/ecc/skills/quarkus-tdd/SKILL.md +73 -72
- package/bundled/upstream/ecc/skills/quarkus-verification/SKILL.md +8 -7
- package/bundled/upstream/ecc/skills/ralphinho-rfc-pipeline/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/react-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/react-performance/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/react-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/recsys-pipeline-architect/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/recursive-decision-ledger/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/redis-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/regex-vs-llm-structured-text/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/repo-scan/SKILL.md +64 -63
- package/bundled/upstream/ecc/skills/research-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/returns-reverse-logistics/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/rules-distill/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/rust-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/rust-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/safety-guard/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/santa-method/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/scientific-db-pubmed-database/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/scientific-db-uspto-database/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/scientific-pkg-gget/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/scientific-thinking-literature-review/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/scientific-thinking-scholar-evaluation/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/search-first/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/security-bounty-hunter/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/security-review/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/security-scan/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/seo/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/skill-comply/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/skill-comply/scripts/runner.py +8 -0
- package/bundled/upstream/ecc/skills/skill-scout/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/skill-stocktake/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/social-graph-ranker/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/social-publisher/SKILL.md +17 -2
- package/bundled/upstream/ecc/skills/springboot-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/springboot-security/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/springboot-tdd/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/springboot-verification/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/strategic-compact/SKILL.md +10 -5
- package/bundled/upstream/ecc/skills/swift-actor-persistence/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/swift-protocol-di-testing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/taste/SKILL.md +264 -0
- package/bundled/upstream/ecc/skills/taste/references/genre-taxonomy.md +87 -0
- package/bundled/upstream/ecc/skills/tdd-workflow/SKILL.md +64 -1
- package/bundled/upstream/ecc/skills/team-agent-orchestration/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/team-builder/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/terminal-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/tinystruct-patterns/SKILL.md +77 -1
- package/bundled/upstream/ecc/skills/token-budget-advisor/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ui-demo/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/ui-to-vue/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/uncloud/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/unified-notifications-ops/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/verification-loop/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/video-editing/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/videodb/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/vite-patterns/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/vue-patterns/SKILL.md +471 -0
- package/bundled/upstream/ecc/skills/windows-desktop-e2e/SKILL.md +9 -8
- package/bundled/upstream/ecc/skills/workspace-surface-audit/SKILL.md +2 -1
- package/bundled/upstream/ecc/skills/x-api/SKILL.md +2 -1
- package/bundled/upstream/impeccable/.omc-source/bundle.json +2 -2
- package/bundled/upstream/impeccable/.omc-source/provenance.json +30 -25
- package/bundled/upstream/impeccable/skills/impeccable/SKILL.md +2 -2
- package/bundled/upstream/impeccable/skills/impeccable/reference/hooks.md +10 -8
- package/bundled/upstream/impeccable/skills/impeccable/reference/live.md +1 -1
- package/bundled/upstream/impeccable/skills/impeccable/scripts/context.mjs +707 -26
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/browser/injected/index.mjs +202 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/cli/main.mjs +57 -11
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/design-system.mjs +750 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +231 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/detect-antipatterns.mjs +7 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +29 -4
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +20 -4
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +2 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +27 -1
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/registry/antipatterns.mjs +29 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/hook-admin.mjs +135 -48
- package/bundled/upstream/impeccable/skills/impeccable/scripts/hook-before-edit.mjs +5 -2
- package/bundled/upstream/impeccable/skills/impeccable/scripts/hook-lib.mjs +375 -29
- package/bundled/upstream/impeccable/skills/impeccable/scripts/lib/design-parser.mjs +8 -1
- package/bundled/upstream/impeccable/skills/impeccable/scripts/lib/impeccable-config.mjs +638 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/lib/impeccable-paths.mjs +37 -35
- package/bundled/upstream/impeccable/skills/impeccable/scripts/lib/target-args.mjs +42 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/live-browser.js +159 -72
- package/bundled/upstream/impeccable/skills/impeccable/scripts/live-poll.mjs +16 -11
- package/bundled/upstream/impeccable/skills/impeccable/scripts/live-server.mjs +9 -8
- package/bundled/upstream/impeccable/skills/impeccable/scripts/live-target.mjs +30 -0
- package/bundled/upstream/impeccable/skills/impeccable/scripts/live-wrap.mjs +1 -1
- package/bundled/upstream/impeccable/skills/impeccable/scripts/live.mjs +72 -21
- package/bundled/upstream/oh-my-claudecode/.omc-source/bundle.json +2 -2
- package/bundled/upstream/oh-my-claudecode/.omc-source/provenance.json +103 -103
- package/bundled/upstream/oh-my-claudecode/agents/analyst.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/architect.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/code-reviewer.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/critic.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/debugger.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/security-reviewer.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/tracer.md +6 -0
- package/bundled/upstream/oh-my-claudecode/agents/verifier.md +7 -0
- package/bundled/upstream/oh-my-claudecode/hooks/hooks.json +9 -2
- package/bundled/upstream/oh-my-claudecode/skills/ask/SKILL.md +15 -4
- package/bundled/upstream/oh-my-claudecode/skills/autopilot/SKILL.md +30 -1
- package/bundled/upstream/oh-my-claudecode/skills/cancel/SKILL.md +29 -35
- package/bundled/upstream/oh-my-claudecode/skills/ccg/SKILL.md +20 -9
- package/bundled/upstream/oh-my-claudecode/skills/configure-notifications/SKILL.md +2 -2
- package/bundled/upstream/oh-my-claudecode/skills/omc-reference/SKILL.md +6 -4
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/02-configure.md +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/03-integrations.md +2 -1
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/04-welcome.md +2 -2
- package/bundled/upstream/oh-my-claudecode/skills/omc-teams/SKILL.md +29 -18
- package/bundled/upstream/oh-my-claudecode/skills/team/SKILL.md +127 -165
- package/bundled/upstream/superpowers/.omc-source/bundle.json +2 -2
- package/bundled/upstream/superpowers/.omc-source/provenance.json +59 -52
- package/bundled/upstream/superpowers/hooks/hooks-codex.json +16 -0
- package/bundled/upstream/superpowers/hooks/session-start +4 -12
- package/bundled/upstream/superpowers/hooks/session-start-codex +26 -0
- package/bundled/upstream/superpowers/skills/brainstorming/SKILL.md +5 -10
- package/bundled/upstream/superpowers/skills/brainstorming/scripts/frame-template.html +25 -26
- package/bundled/upstream/superpowers/skills/brainstorming/scripts/helper.js +101 -22
- package/bundled/upstream/superpowers/skills/brainstorming/scripts/server.cjs +399 -30
- package/bundled/upstream/superpowers/skills/brainstorming/scripts/start-server.sh +70 -9
- package/bundled/upstream/superpowers/skills/brainstorming/scripts/stop-server.sh +66 -2
- package/bundled/upstream/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +1 -1
- package/bundled/upstream/superpowers/skills/brainstorming/visual-companion.md +33 -22
- package/bundled/upstream/superpowers/skills/dispatching-parallel-agents/SKILL.md +9 -6
- package/bundled/upstream/superpowers/skills/executing-plans/SKILL.md +2 -2
- package/bundled/upstream/superpowers/skills/finishing-a-development-branch/SKILL.md +2 -12
- package/bundled/upstream/superpowers/skills/receiving-code-review/SKILL.md +2 -2
- package/bundled/upstream/superpowers/skills/requesting-code-review/SKILL.md +2 -2
- package/bundled/upstream/superpowers/skills/requesting-code-review/code-reviewer.md +15 -11
- package/bundled/upstream/superpowers/skills/subagent-driven-development/SKILL.md +206 -67
- package/bundled/upstream/superpowers/skills/subagent-driven-development/implementer-prompt.md +30 -4
- package/bundled/upstream/superpowers/skills/subagent-driven-development/scripts/review-package +44 -0
- package/bundled/upstream/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +22 -0
- package/bundled/upstream/superpowers/skills/subagent-driven-development/scripts/task-brief +40 -0
- package/bundled/upstream/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +188 -0
- package/bundled/upstream/superpowers/skills/systematic-debugging/SKILL.md +1 -1
- package/bundled/upstream/superpowers/skills/test-driven-development/SKILL.md +1 -1
- package/bundled/upstream/superpowers/skills/using-git-worktrees/SKILL.md +9 -22
- package/bundled/upstream/superpowers/skills/using-superpowers/SKILL.md +19 -15
- package/bundled/upstream/superpowers/skills/using-superpowers/references/antigravity-tools.md +96 -0
- package/bundled/upstream/superpowers/skills/using-superpowers/references/claude-code-tools.md +50 -0
- package/bundled/upstream/superpowers/skills/using-superpowers/references/codex-tools.md +25 -12
- package/bundled/upstream/superpowers/skills/using-superpowers/references/copilot-tools.md +27 -20
- package/bundled/upstream/superpowers/skills/using-superpowers/references/gemini-tools.md +44 -32
- package/bundled/upstream/superpowers/skills/using-superpowers/references/pi-tools.md +28 -0
- package/bundled/upstream/superpowers/skills/writing-plans/SKILL.md +22 -0
- package/bundled/upstream/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +1 -1
- package/bundled/upstream/superpowers/skills/writing-skills/SKILL.md +52 -18
- package/bundled/upstream/superpowers/skills/writing-skills/anthropic-best-practices.md +88 -88
- package/bundled/upstream/superpowers/skills/writing-skills/persuasion-principles.md +3 -3
- package/package.json +1 -1
- package/bundled/upstream/superpowers/skills/subagent-driven-development/code-quality-reviewer-prompt.md +0 -25
- package/bundled/upstream/superpowers/skills/subagent-driven-development/spec-reviewer-prompt.md +0 -61
|
@@ -1,285 +1,948 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: laravel-security
|
|
3
|
-
description: Laravel security best practices
|
|
4
|
-
|
|
3
|
+
description: Laravel security best practices — authentication, authorization, Eloquent safety, CSRF, XSS prevention, API security, and secure deployment configurations.
|
|
4
|
+
metadata:
|
|
5
|
+
origin: ECC
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# Laravel Security Best Practices
|
|
8
9
|
|
|
9
|
-
Comprehensive security
|
|
10
|
+
Comprehensive security guidelines for Laravel applications to protect against common vulnerabilities.
|
|
10
11
|
|
|
11
12
|
## When to Activate
|
|
12
13
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
14
|
+
- Setting up Laravel authentication and authorization (Sanctum, Passport, Jetstream, Breeze)
|
|
15
|
+
- Implementing user roles, permissions, and policies
|
|
16
|
+
- Configuring production security settings and environment variables
|
|
17
|
+
- Reviewing Laravel applications for security vulnerabilities
|
|
18
|
+
- Deploying Laravel applications to production
|
|
19
|
+
- Writing secure Eloquent queries and migrations
|
|
18
20
|
|
|
19
|
-
##
|
|
21
|
+
## Production Configuration
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
- Guards and policies enforce access control (`auth:sanctum`, `$this->authorize`, policy middleware).
|
|
23
|
-
- Form Requests validate and shape input (`UploadInvoiceRequest`) before it reaches services.
|
|
24
|
-
- Rate limiting adds abuse protection (`RateLimiter::for('login')`) alongside auth controls.
|
|
25
|
-
- Data safety comes from encrypted casts, mass-assignment guards, and signed routes (`URL::temporarySignedRoute` + `signed` middleware).
|
|
23
|
+
### Essential Production Settings
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
```php
|
|
26
|
+
// config/app.php
|
|
27
|
+
'env' => env('APP_ENV', 'production'),
|
|
28
|
+
'debug' => (bool) env('APP_DEBUG', false), // CRITICAL: Never true in production
|
|
29
|
+
'key' => env('APP_KEY'), // Must be set: php artisan key:generate
|
|
30
|
+
|
|
31
|
+
// config/session.php
|
|
32
|
+
'secure' => env('SESSION_SECURE_COOKIE', true),
|
|
33
|
+
'http_only' => true,
|
|
34
|
+
'same_site' => 'lax',
|
|
35
|
+
|
|
36
|
+
// Verify APP_KEY is set at boot
|
|
37
|
+
// bootstrap/app.php or a service provider
|
|
38
|
+
if (empty(config('app.key'))) {
|
|
39
|
+
throw new RuntimeException('APP_KEY is not set. Run: php artisan key:generate');
|
|
40
|
+
}
|
|
41
|
+
```
|
|
33
42
|
|
|
34
|
-
|
|
43
|
+
### Environment File Security
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
```bash
|
|
46
|
+
# NEVER commit .env to version control
|
|
47
|
+
# .gitignore already includes .env by default
|
|
39
48
|
|
|
40
|
-
|
|
49
|
+
# Use .env.example with placeholders instead
|
|
50
|
+
DB_PASSWORD=
|
|
51
|
+
APP_KEY=
|
|
52
|
+
SANCTUM_TOKEN_PREFIX=
|
|
41
53
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
54
|
+
# Validate required variables at boot
|
|
55
|
+
// In AppServiceProvider::boot()
|
|
56
|
+
$requiredKeys = ['app.key', 'database.connections.mysql.database', 'database.connections.mysql.username'];
|
|
57
|
+
foreach ($requiredKeys as $key) {
|
|
58
|
+
if (empty(config($key))) {
|
|
59
|
+
throw new RuntimeException("Missing required config key: {$key}");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
45
63
|
|
|
46
|
-
|
|
64
|
+
### HTTPS Enforcement
|
|
47
65
|
|
|
48
66
|
```php
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
// AppServiceProvider::boot() or middleware
|
|
68
|
+
if (app()->environment('production')) {
|
|
69
|
+
URL::forceScheme('https');
|
|
70
|
+
request()->server->set('HTTPS', 'on');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// config/app.php for trusted proxies (load balancers)
|
|
74
|
+
// Use specific IP ranges — * trusts all, allowing X-Forwarded-* spoofing
|
|
75
|
+
// AWS: '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'
|
|
76
|
+
'trusted_proxies' => ['10.0.0.0/8', '172.16.0.0/12'],
|
|
77
|
+
|
|
78
|
+
// Force HTTPS in production via middleware
|
|
79
|
+
// app/Http/Middleware/ForceHttps.php
|
|
80
|
+
public function handle($request, Closure $next)
|
|
81
|
+
{
|
|
82
|
+
if (!$request->secure() && app()->environment('production')) {
|
|
83
|
+
return redirect()->secure($request->getRequestUri());
|
|
84
|
+
}
|
|
85
|
+
return $next($request);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Authentication
|
|
90
|
+
|
|
91
|
+
### Sanctum (API Token Authentication)
|
|
51
92
|
|
|
52
|
-
|
|
53
|
-
|
|
93
|
+
```php
|
|
94
|
+
// config/sanctum.php
|
|
95
|
+
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
|
96
|
+
'%s%s',
|
|
97
|
+
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
|
98
|
+
env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : ''
|
|
99
|
+
)));
|
|
100
|
+
|
|
101
|
+
'expiration' => 60 * 24, // Token expiration in minutes (null = never)
|
|
102
|
+
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
|
|
103
|
+
|
|
104
|
+
// Issuing tokens with abilities
|
|
105
|
+
$token = $user->createToken('api-token', ['read', 'write'])->plainTextToken;
|
|
106
|
+
|
|
107
|
+
// Validate abilities on routes
|
|
108
|
+
Route::middleware('auth:sanctum')->group(function () {
|
|
109
|
+
Route::get('/orders', function () {
|
|
110
|
+
// User must have 'read' ability
|
|
111
|
+
abort_unless(Auth::user()->tokenCan('read'), 403);
|
|
112
|
+
// ...
|
|
113
|
+
})->middleware('abilities:read');
|
|
114
|
+
|
|
115
|
+
Route::post('/orders', function () {
|
|
116
|
+
// User must have 'write' ability
|
|
117
|
+
abort_unless(Auth::user()->tokenCan('write'), 403);
|
|
118
|
+
// ...
|
|
119
|
+
})->middleware('abilities:write');
|
|
54
120
|
});
|
|
55
121
|
```
|
|
56
122
|
|
|
57
|
-
|
|
123
|
+
### Password Security
|
|
58
124
|
|
|
59
|
-
|
|
60
|
-
|
|
125
|
+
```php
|
|
126
|
+
// config/hashing.php
|
|
127
|
+
// Default is bcrypt. Argon2id is stronger.
|
|
128
|
+
'bcrypt' => [
|
|
129
|
+
'rounds' => env('BCRYPT_ROUNDS', 12), // Increase for stronger hashing
|
|
130
|
+
],
|
|
131
|
+
|
|
132
|
+
'argon' => [
|
|
133
|
+
'memory' => 65536,
|
|
134
|
+
'threads' => 4,
|
|
135
|
+
'time' => 4,
|
|
136
|
+
],
|
|
137
|
+
|
|
138
|
+
// Password validation in RegisterRequest
|
|
139
|
+
public function rules(): array
|
|
140
|
+
{
|
|
141
|
+
return [
|
|
142
|
+
'password' => [
|
|
143
|
+
'required',
|
|
144
|
+
'confirmed',
|
|
145
|
+
Password::min(12)
|
|
146
|
+
->letters()
|
|
147
|
+
->mixedCase()
|
|
148
|
+
->numbers()
|
|
149
|
+
->symbols()
|
|
150
|
+
->uncompromised(), // Checks haveibeenpwned
|
|
151
|
+
],
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Rate limit login attempts
|
|
156
|
+
// App\Http\Controllers\Auth\AuthenticatedSessionController
|
|
157
|
+
protected function authenticated(Request $request, $user)
|
|
158
|
+
{
|
|
159
|
+
if ($user->wasRecentlyLockedOut()) {
|
|
160
|
+
// Notify user of suspicious login
|
|
161
|
+
$user->notify(new SuspiciousLoginNotification($request->ip()));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Session Management
|
|
61
167
|
|
|
62
168
|
```php
|
|
63
|
-
|
|
64
|
-
|
|
169
|
+
// config/session.php
|
|
170
|
+
'driver' => env('SESSION_DRIVER', 'database'), // database/redis > file
|
|
171
|
+
'lifetime' => env('SESSION_LIFETIME', 120),
|
|
172
|
+
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
|
|
173
|
+
'encrypt' => env('SESSION_ENCRYPT', false),
|
|
174
|
+
|
|
175
|
+
// Regenerate session on login
|
|
176
|
+
// App\Http\Controllers\Auth\AuthenticatedSessionController
|
|
177
|
+
public function store(LoginRequest $request): RedirectResponse
|
|
178
|
+
{
|
|
179
|
+
$request->authenticate();
|
|
180
|
+
$request->session()->regenerate(); // CRITICAL: prevents session fixation
|
|
181
|
+
return redirect()->intended(RouteServiceProvider::HOME);
|
|
182
|
+
}
|
|
65
183
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
184
|
+
// Invalidate session on logout
|
|
185
|
+
public function destroy(Request $request): RedirectResponse
|
|
186
|
+
{
|
|
187
|
+
Auth::guard('web')->logout();
|
|
188
|
+
$request->session()->invalidate();
|
|
189
|
+
$request->session()->regenerateToken();
|
|
190
|
+
return redirect('/');
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Authorization
|
|
69
195
|
|
|
70
|
-
|
|
196
|
+
### Gates
|
|
197
|
+
|
|
198
|
+
```php
|
|
199
|
+
// App\Providers\AuthServiceProvider
|
|
200
|
+
use App\Models\Post;
|
|
201
|
+
use App\Models\User;
|
|
202
|
+
use Illuminate\Support\Facades\Gate;
|
|
203
|
+
|
|
204
|
+
public function boot(): void
|
|
205
|
+
{
|
|
206
|
+
Gate::define('update-post', function (User $user, Post $post): bool {
|
|
207
|
+
return $user->id === $post->user_id;
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
Gate::define('publish-post', function (User $user): bool {
|
|
211
|
+
return $user->role === 'editor' || $user->role === 'admin';
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Using before() for super-admin override
|
|
215
|
+
Gate::before(function (User $user, string $ability): ?bool {
|
|
216
|
+
if ($user->role === 'super-admin') {
|
|
217
|
+
return true; // Grants all abilities
|
|
218
|
+
}
|
|
219
|
+
return null; // Fall through to normal checks
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Usage in controllers
|
|
224
|
+
public function update(Request $request, Post $post): RedirectResponse
|
|
225
|
+
{
|
|
226
|
+
Gate::authorize('update-post', $post);
|
|
227
|
+
// Or: $this->authorize('update-post', $post);
|
|
228
|
+
// Or: abort_unless(Auth::user()->can('update-post', $post), 403);
|
|
229
|
+
// ...
|
|
230
|
+
}
|
|
71
231
|
```
|
|
72
232
|
|
|
73
|
-
|
|
233
|
+
### Policies
|
|
234
|
+
|
|
235
|
+
```php
|
|
236
|
+
// App\Policies\PostPolicy
|
|
237
|
+
class PostPolicy
|
|
238
|
+
{
|
|
239
|
+
use HandlesAuthorization;
|
|
240
|
+
|
|
241
|
+
public function viewAny(?User $user): bool
|
|
242
|
+
{
|
|
243
|
+
return true; // Public listing
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
public function view(?User $user, Post $post): bool
|
|
247
|
+
{
|
|
248
|
+
return $post->is_published || ($user && $user->id === $post->user_id);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
public function create(User $user): bool
|
|
252
|
+
{
|
|
253
|
+
return $user->hasVerifiedEmail(); // Must verify email first
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
public function update(User $user, Post $post): bool
|
|
257
|
+
{
|
|
258
|
+
return $user->id === $post->user_id;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
public function delete(User $user, Post $post): bool
|
|
262
|
+
{
|
|
263
|
+
return $user->id === $post->user_id && $post->created_at->diffInDays(now()) <= 30;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
public function restore(User $user, Post $post): bool
|
|
267
|
+
{
|
|
268
|
+
return $user->role === 'admin';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
public function forceDelete(User $user, Post $post): bool
|
|
272
|
+
{
|
|
273
|
+
return $user->role === 'super-admin';
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Register in AuthServiceProvider
|
|
278
|
+
protected $policies = [
|
|
279
|
+
Post::class => PostPolicy::class,
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
// Controller usage
|
|
283
|
+
public function show(Post $post): View
|
|
284
|
+
{
|
|
285
|
+
$this->authorize('view', $post);
|
|
286
|
+
return view('posts.show', compact('post'));
|
|
287
|
+
}
|
|
74
288
|
|
|
75
|
-
|
|
76
|
-
|
|
289
|
+
// Blade usage
|
|
290
|
+
@can('update', $post)
|
|
291
|
+
<a href="{{ route('posts.edit', $post) }}">Edit</a>
|
|
292
|
+
@endcan
|
|
293
|
+
|
|
294
|
+
@cannot('update', $post)
|
|
295
|
+
<span>You cannot edit this post</span>
|
|
296
|
+
@endcannot
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Middleware Authorization
|
|
77
300
|
|
|
78
301
|
```php
|
|
79
|
-
|
|
302
|
+
// Using middleware in routes
|
|
303
|
+
Route::put('/posts/{post}', [PostController::class, 'update'])
|
|
304
|
+
->middleware('can:update,post');
|
|
305
|
+
|
|
306
|
+
Route::get('/posts/create', [PostController::class, 'create'])
|
|
307
|
+
->middleware('can:create,App\Models\Post');
|
|
308
|
+
|
|
309
|
+
// Custom authorization middleware
|
|
310
|
+
// app/Http/Middleware/CheckRole.php
|
|
311
|
+
class CheckRole
|
|
312
|
+
{
|
|
313
|
+
public function handle(Request $request, Closure $next, string $role): mixed
|
|
314
|
+
{
|
|
315
|
+
if (!$request->user() || $request->user()->role !== $role) {
|
|
316
|
+
abort(403, 'Unauthorized. This area requires role: ' . $role);
|
|
317
|
+
}
|
|
318
|
+
return $next($request);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Register in Kernel
|
|
323
|
+
protected $routeMiddleware = [
|
|
324
|
+
'role' => \App\Http\Middleware\CheckRole::class,
|
|
325
|
+
];
|
|
326
|
+
|
|
327
|
+
// Route usage
|
|
328
|
+
Route::middleware(['auth', 'role:admin'])->group(function () {
|
|
329
|
+
Route::get('/admin', [AdminController::class, 'index']);
|
|
330
|
+
});
|
|
80
331
|
```
|
|
81
332
|
|
|
82
|
-
|
|
333
|
+
## Eloquent Security
|
|
334
|
+
|
|
335
|
+
### Mass Assignment Protection
|
|
83
336
|
|
|
84
337
|
```php
|
|
85
|
-
|
|
338
|
+
// BAD: $guarded = [] allows ALL columns to be mass-assigned
|
|
339
|
+
// NEVER use $guarded = [] in production
|
|
86
340
|
|
|
87
|
-
|
|
88
|
-
|
|
341
|
+
// GOOD: Whitelist fillable attributes
|
|
342
|
+
final class User extends Authenticatable
|
|
343
|
+
{
|
|
344
|
+
protected $fillable = [
|
|
345
|
+
'name',
|
|
346
|
+
'email',
|
|
347
|
+
'phone',
|
|
348
|
+
'avatar',
|
|
349
|
+
];
|
|
350
|
+
// NEVER add 'role', 'is_admin', 'is_verified' here
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// GOOD: Explicitly control which fields can be filled in requests
|
|
354
|
+
public function store(StoreUserRequest $request): RedirectResponse
|
|
355
|
+
{
|
|
356
|
+
$user = User::create($request->safe()->only([
|
|
357
|
+
'name', 'email', 'phone', 'avatar'
|
|
358
|
+
]));
|
|
359
|
+
// $request->safe() uses validated data only
|
|
360
|
+
// $request->only() is NOT safe on its own without validation rules
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// BAD: Creating a user with request data directly
|
|
364
|
+
User::create($request->all()); // VULNERABLE to mass assignment!
|
|
365
|
+
|
|
366
|
+
// BETTER: Use DTOs for creation
|
|
367
|
+
$user = User::create($request->validated()); // Only validated fields
|
|
89
368
|
```
|
|
90
369
|
|
|
91
|
-
|
|
370
|
+
### SQL Injection Prevention
|
|
371
|
+
|
|
372
|
+
```php
|
|
373
|
+
// GOOD: Eloquent automatically parameterizes queries
|
|
374
|
+
User::where('email', $userInput)->first();
|
|
375
|
+
User::whereRaw('email = ?', [$userInput])->first();
|
|
92
376
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
377
|
+
// GOOD: Query Builder also parameterizes
|
|
378
|
+
DB::table('users')->where('email', $userInput)->first();
|
|
379
|
+
DB::select('SELECT * FROM users WHERE email = ?', [$userInput]);
|
|
96
380
|
|
|
97
|
-
|
|
381
|
+
// BAD: Raw string interpolation
|
|
382
|
+
DB::select("SELECT * FROM users WHERE email = '{$userInput}'"); // VULNERABLE!
|
|
383
|
+
User::whereRaw("email = '{$userInput}'")->first(); // VULNERABLE!
|
|
98
384
|
|
|
99
|
-
|
|
100
|
-
|
|
385
|
+
// BAD: whereRaw/orderByRaw with unescaped input
|
|
386
|
+
User::orderByRaw($userInput); // VULNERABLE!
|
|
387
|
+
User::groupByRaw($userInput); // VULNERABLE!
|
|
101
388
|
|
|
102
|
-
|
|
389
|
+
// BAD: DB::statement with concatenation
|
|
390
|
+
DB::statement("INSERT INTO users (email) VALUES ('{$userInput}')"); // VULNERABLE!
|
|
391
|
+
```
|
|
103
392
|
|
|
104
|
-
|
|
105
|
-
- Avoid raw SQL unless strictly necessary
|
|
393
|
+
### Attribute Casting
|
|
106
394
|
|
|
107
395
|
```php
|
|
108
|
-
|
|
396
|
+
final class User extends Authenticatable
|
|
397
|
+
{
|
|
398
|
+
protected $casts = [
|
|
399
|
+
'email_verified_at' => 'datetime',
|
|
400
|
+
'is_admin' => 'boolean', // Cast to boolean prevents string injection
|
|
401
|
+
'settings' => 'array', // Automatically json_encode/json_decode
|
|
402
|
+
'metadata' => 'encrypted:array', // Laravel 11+ encrypted casting
|
|
403
|
+
'password' => 'hashed', // Laravel 10+ auto-hashes on set
|
|
404
|
+
];
|
|
405
|
+
}
|
|
109
406
|
```
|
|
110
407
|
|
|
111
|
-
|
|
408
|
+
### Model Security
|
|
409
|
+
|
|
410
|
+
```php
|
|
411
|
+
final class User extends Authenticatable
|
|
412
|
+
{
|
|
413
|
+
// Hide sensitive attributes from JSON/API responses
|
|
414
|
+
protected $hidden = [
|
|
415
|
+
'password',
|
|
416
|
+
'remember_token',
|
|
417
|
+
'two_factor_secret',
|
|
418
|
+
'two_factor_recovery_codes',
|
|
419
|
+
];
|
|
420
|
+
|
|
421
|
+
// Append only safe computed attributes
|
|
422
|
+
protected $appends = ['full_name']; // safe
|
|
423
|
+
// NEVER append sensitive computed data
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
final class Post extends Model
|
|
427
|
+
{
|
|
428
|
+
// Global scope to filter soft deleted records
|
|
429
|
+
use SoftDeletes;
|
|
112
430
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
431
|
+
// Prevent N+1 by restricting lazy loading (optional strict mode)
|
|
432
|
+
// AppServiceProvider::boot()
|
|
433
|
+
// Model::preventLazyLoading(!app()->isProduction());
|
|
434
|
+
}
|
|
435
|
+
```
|
|
116
436
|
|
|
117
437
|
## CSRF Protection
|
|
118
438
|
|
|
119
|
-
|
|
120
|
-
|
|
439
|
+
### Default Protection
|
|
440
|
+
|
|
441
|
+
```php
|
|
442
|
+
// Laravel CSRF is enabled by default via VerifyCsrfToken middleware
|
|
443
|
+
// app/Http/Kernel.php (protected $middlewareGroups['web'])
|
|
444
|
+
|
|
445
|
+
// All POST/PUT/PATCH/DELETE forms must include @csrf
|
|
446
|
+
<form method="POST" action="/posts">
|
|
447
|
+
@csrf
|
|
448
|
+
<input type="text" name="title">
|
|
449
|
+
<button type="submit">Create</button>
|
|
450
|
+
</form>
|
|
451
|
+
```
|
|
121
452
|
|
|
122
|
-
|
|
453
|
+
### Excluding Routes (Carefully)
|
|
123
454
|
|
|
124
455
|
```php
|
|
125
|
-
//
|
|
126
|
-
|
|
456
|
+
// app/Http/Middleware/VerifyCsrfToken.php
|
|
457
|
+
class VerifyCsrfToken extends Middleware
|
|
458
|
+
{
|
|
459
|
+
// Only exclude routes that have external CSRF protection (webhooks, etc.)
|
|
460
|
+
protected $except = [
|
|
461
|
+
'stripe/*', // Stripe webhooks use their own signature verification
|
|
462
|
+
// Avoid blanket 'api/*' — stateful Sanctum routes need CSRF.
|
|
463
|
+
// Exclude only specific stateless webhook/endpoint routes.
|
|
464
|
+
];
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### CSRF with JavaScript
|
|
469
|
+
|
|
470
|
+
```html
|
|
471
|
+
<meta name="csrf-token" content="{{ csrf_token() }}">
|
|
472
|
+
|
|
473
|
+
<script>
|
|
474
|
+
// Axios example (Laravel ships with Axios)
|
|
475
|
+
axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector(
|
|
476
|
+
'meta[name="csrf-token"]'
|
|
477
|
+
).getAttribute('content');
|
|
478
|
+
|
|
479
|
+
// Fetch example
|
|
480
|
+
fetch('/posts', {
|
|
481
|
+
method: 'POST',
|
|
482
|
+
headers: {
|
|
483
|
+
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
484
|
+
'Content-Type': 'application/json',
|
|
485
|
+
},
|
|
486
|
+
body: JSON.stringify(data),
|
|
487
|
+
});
|
|
488
|
+
</script>
|
|
127
489
|
```
|
|
128
490
|
|
|
129
|
-
##
|
|
491
|
+
## XSS Prevention
|
|
492
|
+
|
|
493
|
+
### Blade Templating Security
|
|
494
|
+
|
|
495
|
+
```blade
|
|
496
|
+
{{-- SAFE: Auto-escaped by Blade --}}
|
|
497
|
+
{{ $userInput }}
|
|
498
|
+
|
|
499
|
+
{{-- DANGEROUS: Raw output — NEVER use with user input --}}
|
|
500
|
+
{!! $userInput !!}
|
|
501
|
+
|
|
502
|
+
{{-- SAFE: Only use {!! !!} with trusted content you control --}}
|
|
503
|
+
{!! $trustedHtmlFromYourServer !!}
|
|
504
|
+
|
|
505
|
+
{{-- GOOD: Use specific escaping directives --}}
|
|
506
|
+
@js($data) {{-- JSON encode for JavaScript --}}
|
|
507
|
+
@json($data) {{-- JSON encode in templates --}}
|
|
508
|
+
|
|
509
|
+
{{-- BAD: Direct user input in raw HTML --}}
|
|
510
|
+
<div>{!! $user->bio !!}</div> {{-- VULNERABLE if user provides bio --}}
|
|
511
|
+
```
|
|
130
512
|
|
|
131
|
-
|
|
132
|
-
- Store uploads outside the public path when possible
|
|
133
|
-
- Scan files for malware if required
|
|
513
|
+
### Safe HTML Handling
|
|
134
514
|
|
|
135
515
|
```php
|
|
136
|
-
|
|
516
|
+
// When you must allow some HTML, use a whitelist approach
|
|
517
|
+
use HTMLPurifier; // Requires: composer require ezyang/htmlpurifier
|
|
518
|
+
|
|
519
|
+
public function sanitizeHtml(string $dirty): string
|
|
520
|
+
{
|
|
521
|
+
$config = \HTMLPurifier_Config::createDefault();
|
|
522
|
+
$config->set('HTML.Allowed', 'p,b,i,a[href],ul,ol,li,br');
|
|
523
|
+
$config->set('URI.AllowedSchemes', ['http', 'https', 'mailto']);
|
|
524
|
+
$purifier = new \HTMLPurifier($config);
|
|
525
|
+
return $purifier->purify($dirty);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// In blade:
|
|
529
|
+
<div>{!! $sanitizedContent !!}</div> {{-- Safe after purification --}}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### JavaScript Context Escaping
|
|
533
|
+
|
|
534
|
+
```blade
|
|
535
|
+
{{-- SAFE: Blade @js escapes for JavaScript context --}}
|
|
536
|
+
<script>
|
|
537
|
+
const user = @js($user); // JSON + escaped for JS context
|
|
538
|
+
const settings = @json($settings); // Direct JSON encode
|
|
539
|
+
</script>
|
|
540
|
+
|
|
541
|
+
{{-- DANGEROUS: Manual JSON in JS context --}}
|
|
542
|
+
<script>
|
|
543
|
+
const user = {{ json_encode($user) }}; // NOT escaped for JS!
|
|
544
|
+
</script>
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### HTTP Headers for XSS Protection
|
|
548
|
+
|
|
549
|
+
```php
|
|
550
|
+
// App\Http\Middleware\SecurityHeaders.php
|
|
551
|
+
class SecurityHeaders
|
|
552
|
+
{
|
|
553
|
+
public function handle(Request $request, Closure $next): mixed
|
|
554
|
+
{
|
|
555
|
+
$response = $next($request);
|
|
556
|
+
|
|
557
|
+
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
|
558
|
+
$response->headers->set('X-Frame-Options', 'DENY');
|
|
559
|
+
$response->headers->set('X-XSS-Protection', '1; mode=block');
|
|
560
|
+
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
|
561
|
+
$response->headers->set(
|
|
562
|
+
'Content-Security-Policy',
|
|
563
|
+
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'"
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
return $response;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Register in kernel
|
|
571
|
+
protected $middleware = [
|
|
572
|
+
\App\Http\Middleware\SecurityHeaders::class,
|
|
573
|
+
];
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## Input Validation
|
|
577
|
+
|
|
578
|
+
### Form Request Validation
|
|
579
|
+
|
|
580
|
+
```php
|
|
581
|
+
final class StorePostRequest extends FormRequest
|
|
137
582
|
{
|
|
138
583
|
public function authorize(): bool
|
|
139
584
|
{
|
|
140
|
-
return
|
|
585
|
+
return $this->user()?->can('create', Post::class) ?? false;
|
|
141
586
|
}
|
|
142
587
|
|
|
143
588
|
public function rules(): array
|
|
144
589
|
{
|
|
145
590
|
return [
|
|
146
|
-
'
|
|
591
|
+
'title' => ['required', 'string', 'max:255', 'sanitize_html'],
|
|
592
|
+
'content' => ['required', 'string', 'max:10000'],
|
|
593
|
+
'image' => [
|
|
594
|
+
'required',
|
|
595
|
+
'image',
|
|
596
|
+
'mimes:jpg,jpeg,png,gif,webp', // Whitelist specific types
|
|
597
|
+
'max:2048', // 2MB max
|
|
598
|
+
],
|
|
599
|
+
'tags' => ['array'],
|
|
600
|
+
'tags.*' => ['integer', 'exists:tags,id'],
|
|
147
601
|
];
|
|
148
602
|
}
|
|
603
|
+
|
|
604
|
+
public function messages(): array
|
|
605
|
+
{
|
|
606
|
+
return [
|
|
607
|
+
'title.max' => 'Post title must not exceed 255 characters.',
|
|
608
|
+
'image.max' => 'Image must be under 2MB.',
|
|
609
|
+
];
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Sanitize input after validation
|
|
613
|
+
public function validated($key = null, $default = null): mixed
|
|
614
|
+
{
|
|
615
|
+
$validated = parent::validated();
|
|
616
|
+
$validated['title'] = strip_tags($validated['title']);
|
|
617
|
+
return $key ? ($validated[$key] ?? $default) : $validated;
|
|
618
|
+
}
|
|
149
619
|
}
|
|
150
620
|
```
|
|
151
621
|
|
|
622
|
+
### Custom Validation Rules
|
|
623
|
+
|
|
152
624
|
```php
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
)
|
|
625
|
+
// app/Rules/StrongPassword.php
|
|
626
|
+
class StrongPassword implements Rule
|
|
627
|
+
{
|
|
628
|
+
public function passes($attribute, $value): bool
|
|
629
|
+
{
|
|
630
|
+
return preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&#^()_\-+=])[A-Za-z\d@$!%*?&#^()_\-+=]{12,}$/', $value);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
public function message(): string
|
|
634
|
+
{
|
|
635
|
+
return 'The :attribute must be at least 12 characters with uppercase, lowercase, number, and symbol.';
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// app/Rules/NotBlacklistedDomain.php
|
|
640
|
+
class NotBlacklistedDomain implements Rule
|
|
641
|
+
{
|
|
642
|
+
private array $blacklisted = ['mailinator.com', 'guerrillamail.com'];
|
|
643
|
+
|
|
644
|
+
public function passes($attribute, $value): bool
|
|
645
|
+
{
|
|
646
|
+
$domain = substr(strrchr($value, '@'), 1);
|
|
647
|
+
return !in_array(strtolower($domain), $this->blacklisted);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
public function message(): string
|
|
651
|
+
{
|
|
652
|
+
return 'Email from disposable domains is not allowed.';
|
|
653
|
+
}
|
|
654
|
+
}
|
|
157
655
|
```
|
|
158
656
|
|
|
159
|
-
##
|
|
657
|
+
## API Security
|
|
160
658
|
|
|
161
|
-
|
|
162
|
-
- Use stricter limits for login, password reset, and OTP
|
|
659
|
+
### Rate Limiting
|
|
163
660
|
|
|
164
661
|
```php
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
662
|
+
// App/Providers/RouteServiceProvider
|
|
663
|
+
protected function configureRateLimiting(): void
|
|
664
|
+
{
|
|
665
|
+
RateLimiter::for('api', function (Request $request) {
|
|
666
|
+
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
RateLimiter::for('auth', function (Request $request) {
|
|
670
|
+
return Limit::perMinute(5)->by($request->ip())
|
|
671
|
+
->response(function () {
|
|
672
|
+
return response()->json([
|
|
673
|
+
'message' => 'Too many login attempts. Try again in 1 minute.',
|
|
674
|
+
], 429);
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
RateLimiter::for('uploads', function (Request $request) {
|
|
679
|
+
return Limit::perHour(10)->by($request->user()?->id ?? $request->ip())
|
|
680
|
+
->response(function () {
|
|
681
|
+
return response()->json([
|
|
682
|
+
'message' => 'Upload limit reached. Try again later.',
|
|
683
|
+
], 429);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
}
|
|
168
687
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Limit::perMinute(5)->by(strtolower((string) $request->input('email'))),
|
|
173
|
-
];
|
|
688
|
+
// Route usage
|
|
689
|
+
Route::middleware(['auth:sanctum', 'throttle:api'])->group(function () {
|
|
690
|
+
Route::apiResource('posts', PostController::class);
|
|
174
691
|
});
|
|
692
|
+
|
|
693
|
+
Route::post('/login', [AuthController::class, 'login'])
|
|
694
|
+
->middleware('throttle:auth');
|
|
175
695
|
```
|
|
176
696
|
|
|
177
|
-
|
|
697
|
+
### API Authentication — Sanctum vs Passport
|
|
178
698
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
699
|
+
```php
|
|
700
|
+
// Sanctum (recommended for most apps — simple, first-party, SPA)
|
|
701
|
+
// config/sanctum.php
|
|
702
|
+
'expiration' => 60 * 24, // Tokens expire after 24 hours
|
|
703
|
+
'model' => User::class,
|
|
704
|
+
|
|
705
|
+
// Issuing scoped tokens
|
|
706
|
+
$token = $user->createToken('client-name', [
|
|
707
|
+
'posts:read',
|
|
708
|
+
'posts:write',
|
|
709
|
+
])->plainTextToken;
|
|
710
|
+
|
|
711
|
+
// Middleware scoping
|
|
712
|
+
Route::middleware('auth:sanctum')->group(function () {
|
|
713
|
+
Route::get('/posts', [PostController::class, 'index'])
|
|
714
|
+
->middleware('abilities:posts:read');
|
|
715
|
+
|
|
716
|
+
Route::post('/posts', [PostController::class, 'store'])
|
|
717
|
+
->middleware('abilities:posts:write');
|
|
718
|
+
});
|
|
182
719
|
|
|
183
|
-
|
|
720
|
+
// Passport (OAuth2 — for third-party clients or complex auth flows)
|
|
721
|
+
// Install: composer require laravel/passport
|
|
722
|
+
Passport::tokensExpireIn(now()->addDays(15));
|
|
723
|
+
Passport::refreshTokensExpireIn(now()->addDays(30));
|
|
724
|
+
Passport::personalAccessTokensExpireIn(now()->addMonths(6));
|
|
725
|
+
```
|
|
184
726
|
|
|
185
|
-
|
|
727
|
+
### CORS Configuration
|
|
186
728
|
|
|
187
729
|
```php
|
|
188
|
-
|
|
189
|
-
|
|
730
|
+
// config/cors.php
|
|
731
|
+
return [
|
|
732
|
+
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
|
733
|
+
'allowed_methods' => ['*'],
|
|
734
|
+
'allowed_origins' => explode(',', env('CORS_ALLOWED_ORIGINS', '')), // Whitelist specific origins
|
|
735
|
+
'allowed_origins_patterns' => [],
|
|
736
|
+
'allowed_headers' => ['*'],
|
|
737
|
+
'exposed_headers' => ['X-Total-Count', 'X-Pagination-Page'],
|
|
738
|
+
'max_age' => 0,
|
|
739
|
+
'supports_credentials' => true, // Required for Sanctum SPA auth
|
|
190
740
|
];
|
|
741
|
+
|
|
742
|
+
// NEVER: Allow all origins in production unless absolutely necessary
|
|
743
|
+
// 'allowed_origins' => ['*'], // Only for truly public APIs
|
|
191
744
|
```
|
|
192
745
|
|
|
193
|
-
## Security
|
|
746
|
+
## File Upload Security
|
|
194
747
|
|
|
195
|
-
|
|
196
|
-
- Use trusted proxy configuration to enforce HTTPS redirects
|
|
748
|
+
### Validation
|
|
197
749
|
|
|
198
|
-
|
|
750
|
+
```php
|
|
751
|
+
public function rules(): array
|
|
752
|
+
{
|
|
753
|
+
return [
|
|
754
|
+
'document' => [
|
|
755
|
+
'required',
|
|
756
|
+
'file',
|
|
757
|
+
'mimes:pdf,doc,docx,xls,xlsx', // Whitelist specific MIME types
|
|
758
|
+
'max:10240', // 10MB
|
|
759
|
+
'extensions:pdf,doc,docx,xls,xlsx', // Verify extension matches MIME
|
|
760
|
+
],
|
|
761
|
+
'avatar' => [
|
|
762
|
+
'nullable',
|
|
763
|
+
'image', // Ensures it's a valid image
|
|
764
|
+
'mimes:jpg,jpeg,png,webp',
|
|
765
|
+
'max:2048',
|
|
766
|
+
'dimensions:min_width=100,min_height=100,max_width=2000,max_height=2000',
|
|
767
|
+
],
|
|
768
|
+
];
|
|
769
|
+
}
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
### Secure Storage
|
|
199
773
|
|
|
200
774
|
```php
|
|
201
|
-
|
|
202
|
-
|
|
775
|
+
// Store files outside public directory
|
|
776
|
+
$path = $request->file('document')->store('documents', 'local');
|
|
777
|
+
// Never use 'public' disk for sensitive documents
|
|
778
|
+
|
|
779
|
+
// Use signed URLs for temporary file access
|
|
780
|
+
use Illuminate\Support\Facades\Storage;
|
|
203
781
|
|
|
204
|
-
|
|
782
|
+
public function download(Request $request, string $path)
|
|
205
783
|
{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
$response = $next($request);
|
|
784
|
+
// Generate temporary signed URL (expires in 15 minutes)
|
|
785
|
+
$url = Storage::temporaryUrl($path, now()->addMinutes(15));
|
|
209
786
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
'Strict-Transport-Security' => 'max-age=31536000', // add includeSubDomains/preload only when all subdomains are HTTPS
|
|
213
|
-
'X-Frame-Options' => 'DENY',
|
|
214
|
-
'X-Content-Type-Options' => 'nosniff',
|
|
215
|
-
'Referrer-Policy' => 'no-referrer',
|
|
216
|
-
]);
|
|
787
|
+
// Validate user has permission
|
|
788
|
+
$this->authorize('download', $path);
|
|
217
789
|
|
|
218
|
-
|
|
219
|
-
}
|
|
790
|
+
return redirect($url);
|
|
220
791
|
}
|
|
792
|
+
|
|
793
|
+
// Storage configuration for cloud with encryption
|
|
794
|
+
// config/filesystems.php
|
|
795
|
+
's3' => [
|
|
796
|
+
'driver' => 's3',
|
|
797
|
+
'key' => env('AWS_ACCESS_KEY_ID'),
|
|
798
|
+
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
|
799
|
+
'region' => env('AWS_DEFAULT_REGION'),
|
|
800
|
+
'bucket' => env('AWS_BUCKET'),
|
|
801
|
+
'url' => env('AWS_URL'),
|
|
802
|
+
'endpoint' => env('AWS_ENDPOINT'),
|
|
803
|
+
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
|
804
|
+
'throw' => false,
|
|
805
|
+
'server_side_encryption' => 'AES256', // Encrypt at rest
|
|
806
|
+
],
|
|
221
807
|
```
|
|
222
808
|
|
|
223
|
-
##
|
|
809
|
+
## Dependencies and Secrets
|
|
224
810
|
|
|
225
|
-
|
|
226
|
-
- Avoid wildcard origins for authenticated routes
|
|
811
|
+
### Composer Security
|
|
227
812
|
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
'supports_credentials' => true,
|
|
242
|
-
];
|
|
813
|
+
```bash
|
|
814
|
+
# Always audit dependencies in CI
|
|
815
|
+
composer audit
|
|
816
|
+
|
|
817
|
+
# Pin major versions in composer.json
|
|
818
|
+
"laravel/framework": "^11.0",
|
|
819
|
+
"spatie/laravel-permission": "^6.0"
|
|
820
|
+
|
|
821
|
+
# Check for abandoned packages
|
|
822
|
+
composer why-not
|
|
823
|
+
|
|
824
|
+
# Keep lock file in version control (it pins exact versions)
|
|
825
|
+
# Run `composer update` deliberately, never in CI/CD
|
|
243
826
|
```
|
|
244
827
|
|
|
245
|
-
|
|
828
|
+
### Secret Management
|
|
246
829
|
|
|
247
|
-
|
|
248
|
-
|
|
830
|
+
```bash
|
|
831
|
+
# .env file (NEVER commit)
|
|
832
|
+
# .gitignore includes .env by default
|
|
249
833
|
|
|
250
|
-
|
|
251
|
-
|
|
834
|
+
APP_KEY=base64:abc123...
|
|
835
|
+
DB_PASSWORD=secure_password
|
|
836
|
+
STRIPE_KEY=sk_live_...
|
|
837
|
+
SANCTUM_TOKEN_PREFIX=myapp_
|
|
252
838
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
]
|
|
839
|
+
# For production: Use a secret manager
|
|
840
|
+
# Deploy with: env $(aws secretsmanager get-secret-value --secret-id prod/db | jq ...) php artisan serve
|
|
841
|
+
|
|
842
|
+
# Validate secrets at boot (AppServiceProvider::boot)
|
|
843
|
+
$secrets = ['services.stripe.key', 'services.stripe.webhook_secret'];
|
|
844
|
+
foreach ($secrets as $key) {
|
|
845
|
+
if (empty(config($key))) {
|
|
846
|
+
Log::critical("Missing secret: {$key}");
|
|
847
|
+
}
|
|
848
|
+
}
|
|
258
849
|
```
|
|
259
850
|
|
|
260
|
-
##
|
|
851
|
+
## Queue Security
|
|
261
852
|
|
|
262
|
-
|
|
263
|
-
|
|
853
|
+
```php
|
|
854
|
+
// Define a named rate limiter (typically in AppServiceProvider::boot())
|
|
855
|
+
RateLimiter::for('payments', fn () => Limit::perMinute(5));
|
|
856
|
+
```
|
|
264
857
|
|
|
265
|
-
|
|
858
|
+
```php
|
|
859
|
+
// Encrypt sensitive job data by implementing the interface
|
|
860
|
+
final class ProcessPaymentJob implements ShouldQueue, ShouldBeEncrypted
|
|
861
|
+
{
|
|
862
|
+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
266
863
|
|
|
267
|
-
|
|
864
|
+
public function __construct(
|
|
865
|
+
private readonly string $paymentIntentId, // Public IDs are fine
|
|
866
|
+
private readonly string $cardFingerprint, // Encrypted via ShouldBeEncrypted
|
|
867
|
+
) {}
|
|
268
868
|
|
|
269
|
-
|
|
270
|
-
|
|
869
|
+
public function handle(): void
|
|
870
|
+
{
|
|
871
|
+
// Process payment
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// Limit retries and delay between attempts
|
|
875
|
+
public function retryUntil(): Carbon
|
|
876
|
+
{
|
|
877
|
+
return now()->addMinutes(5);
|
|
878
|
+
}
|
|
271
879
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
)
|
|
880
|
+
// Rate limit how many jobs of this type can run
|
|
881
|
+
public function middleware(): array
|
|
882
|
+
{
|
|
883
|
+
return [
|
|
884
|
+
new RateLimited('payments'),
|
|
885
|
+
];
|
|
886
|
+
}
|
|
887
|
+
}
|
|
277
888
|
```
|
|
278
889
|
|
|
890
|
+
## Logging Security Events
|
|
891
|
+
|
|
279
892
|
```php
|
|
280
|
-
|
|
893
|
+
// config/logging.php
|
|
894
|
+
'channels' => [
|
|
895
|
+
'security' => [
|
|
896
|
+
'driver' => 'single',
|
|
897
|
+
'path' => storage_path('logs/security.log'),
|
|
898
|
+
'level' => 'warning',
|
|
899
|
+
],
|
|
900
|
+
],
|
|
281
901
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
902
|
+
// Audit log helper
|
|
903
|
+
final class SecurityLogger
|
|
904
|
+
{
|
|
905
|
+
public static function log(string $event, array $context = []): void
|
|
906
|
+
{
|
|
907
|
+
Log::channel('security')->warning($event, array_merge([
|
|
908
|
+
'user_id' => Auth::id(),
|
|
909
|
+
'ip' => request()->ip(),
|
|
910
|
+
'user_agent' => request()->userAgent(),
|
|
911
|
+
'url' => request()->fullUrl(),
|
|
912
|
+
'timestamp' => now()->toIso8601String(),
|
|
913
|
+
], $context));
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// Usage
|
|
918
|
+
SecurityLogger::log('failed_login_attempt', ['email' => $email]);
|
|
919
|
+
SecurityLogger::log('password_change');
|
|
920
|
+
SecurityLogger::log('role_change', ['target_user' => $targetId, 'new_role' => 'admin']);
|
|
921
|
+
SecurityLogger::log('suspicious_activity', ['reason' => 'multiple_attempts_from_different_ips']);
|
|
285
922
|
```
|
|
923
|
+
|
|
924
|
+
## Quick Security Checklist
|
|
925
|
+
|
|
926
|
+
| Check | Description |
|
|
927
|
+
|-------|-------------|
|
|
928
|
+
| `APP_DEBUG=false` | Never run with debug enabled in production |
|
|
929
|
+
| `APP_KEY` set | Always run `php artisan key:generate` |
|
|
930
|
+
| HTTPS enforced | Force HTTPS in production via middleware or proxy |
|
|
931
|
+
| `$fillable` whitelisted | Never use `$guarded = []` |
|
|
932
|
+
| CSRF active | `@csrf` on all state-changing forms |
|
|
933
|
+
| Sanctum/Passport configured | API authentication with token abilities/scopes |
|
|
934
|
+
| Rate limiting applied | Throttle API and auth endpoints |
|
|
935
|
+
| Input validation | FormRequest with specific rules, never `$request->all()` |
|
|
936
|
+
| File upload restrictions | Validate MIME types, size, dimensions |
|
|
937
|
+
| `composer audit` in CI | Check dependencies for known vulnerabilities |
|
|
938
|
+
| `password_hash` / `password_verify` | Use Laravel's built-in hashing (bcrypt/Argon2) |
|
|
939
|
+
| Session regeneration on login | Call `$request->session()->regenerate()` |
|
|
940
|
+
| Security headers middleware | CSP, X-Frame-Options, X-Content-Type-Options |
|
|
941
|
+
| Logged security events | Audit log for auth failures, role changes, suspicious activity |
|
|
942
|
+
| `.env` not committed | Verify `.gitignore` includes `.env` |
|
|
943
|
+
|
|
944
|
+
## Related Skills
|
|
945
|
+
|
|
946
|
+
- `laravel-patterns` — Laravel architecture, routing, Eloquent, and API patterns
|
|
947
|
+
- `backend-patterns` — General backend API and database patterns
|
|
948
|
+
- `laravel-tdd` — Laravel testing with PHPUnit and Pest
|