aios-core 2.1.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/.aios-core/.session/current-session.json +14 -0
- package/.aios-core/cli/commands/generate/index.js +222 -0
- package/.aios-core/cli/commands/manifest/index.js +46 -0
- package/.aios-core/cli/commands/manifest/regenerate.js +96 -0
- package/.aios-core/cli/commands/manifest/validate.js +66 -0
- package/.aios-core/cli/commands/mcp/add.js +234 -0
- package/.aios-core/cli/commands/mcp/index.js +76 -0
- package/.aios-core/cli/commands/mcp/link.js +217 -0
- package/.aios-core/cli/commands/mcp/setup.js +164 -0
- package/.aios-core/cli/commands/mcp/status.js +183 -0
- package/.aios-core/cli/commands/metrics/cleanup.js +91 -0
- package/.aios-core/cli/commands/metrics/index.js +65 -0
- package/.aios-core/cli/commands/metrics/record.js +154 -0
- package/.aios-core/cli/commands/metrics/seed.js +126 -0
- package/.aios-core/cli/commands/metrics/show.js +209 -0
- package/.aios-core/cli/commands/migrate/analyze.js +353 -0
- package/.aios-core/cli/commands/migrate/backup.js +352 -0
- package/.aios-core/cli/commands/migrate/execute.js +292 -0
- package/.aios-core/cli/commands/migrate/index.js +441 -0
- package/.aios-core/cli/commands/migrate/rollback.js +323 -0
- package/.aios-core/cli/commands/migrate/update-imports.js +396 -0
- package/.aios-core/cli/commands/migrate/validate.js +452 -0
- package/.aios-core/cli/commands/qa/index.js +56 -0
- package/.aios-core/cli/commands/qa/run.js +163 -0
- package/.aios-core/cli/commands/qa/status.js +195 -0
- package/.aios-core/cli/commands/workers/formatters/info-formatter.js +274 -0
- package/.aios-core/cli/commands/workers/formatters/list-table.js +265 -0
- package/.aios-core/cli/commands/workers/formatters/list-tree.js +159 -0
- package/.aios-core/cli/commands/workers/index.js +56 -0
- package/.aios-core/cli/commands/workers/info.js +194 -0
- package/.aios-core/cli/commands/workers/list.js +214 -0
- package/.aios-core/cli/commands/workers/search-filters.js +185 -0
- package/.aios-core/cli/commands/workers/search-keyword.js +310 -0
- package/.aios-core/cli/commands/workers/search-semantic.js +293 -0
- package/.aios-core/cli/commands/workers/search.js +154 -0
- package/.aios-core/cli/commands/workers/utils/pagination.js +102 -0
- package/.aios-core/cli/index.js +128 -0
- package/.aios-core/cli/utils/output-formatter-cli.js +232 -0
- package/.aios-core/cli/utils/score-calculator.js +221 -0
- package/.aios-core/core/README.md +229 -0
- package/.aios-core/core/config/config-cache.js +233 -0
- package/.aios-core/core/config/config-loader.js +277 -0
- package/.aios-core/core/data/agent-config-requirements.yaml +368 -0
- package/.aios-core/core/data/aios-kb.md +924 -0
- package/.aios-core/core/data/workflow-patterns.yaml +267 -0
- package/.aios-core/core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
- package/.aios-core/core/docs/component-creation-guide.md +458 -0
- package/.aios-core/core/docs/session-update-pattern.md +307 -0
- package/.aios-core/core/docs/template-syntax.md +267 -0
- package/.aios-core/core/docs/troubleshooting-guide.md +625 -0
- package/.aios-core/core/elicitation/agent-elicitation.js +272 -0
- package/.aios-core/core/elicitation/elicitation-engine.js +479 -0
- package/.aios-core/core/elicitation/session-manager.js +320 -0
- package/.aios-core/core/elicitation/task-elicitation.js +281 -0
- package/.aios-core/core/elicitation/workflow-elicitation.js +315 -0
- package/.aios-core/core/index.esm.js +42 -0
- package/.aios-core/core/index.js +76 -0
- package/.aios-core/core/manifest/manifest-generator.js +386 -0
- package/.aios-core/core/manifest/manifest-validator.js +429 -0
- package/.aios-core/core/mcp/config-migrator.js +340 -0
- package/.aios-core/core/mcp/global-config-manager.js +369 -0
- package/.aios-core/core/mcp/index.js +34 -0
- package/.aios-core/core/mcp/os-detector.js +188 -0
- package/.aios-core/core/mcp/symlink-manager.js +413 -0
- package/.aios-core/core/migration/migration-config.yaml +83 -0
- package/.aios-core/core/migration/module-mapping.yaml +89 -0
- package/.aios-core/core/quality-gates/base-layer.js +134 -0
- package/.aios-core/core/quality-gates/checklist-generator.js +329 -0
- package/.aios-core/core/quality-gates/focus-area-recommender.js +359 -0
- package/.aios-core/core/quality-gates/human-review-orchestrator.js +529 -0
- package/.aios-core/core/quality-gates/layer1-precommit.js +336 -0
- package/.aios-core/core/quality-gates/layer2-pr-automation.js +324 -0
- package/.aios-core/core/quality-gates/layer3-human-review.js +348 -0
- package/.aios-core/core/quality-gates/notification-manager.js +550 -0
- package/.aios-core/core/quality-gates/quality-gate-config.yaml +86 -0
- package/.aios-core/core/quality-gates/quality-gate-manager.js +601 -0
- package/.aios-core/core/registry/README.md +179 -0
- package/.aios-core/core/registry/build-registry.js +452 -0
- package/.aios-core/core/registry/registry-loader.js +330 -0
- package/.aios-core/core/registry/registry-schema.json +166 -0
- package/.aios-core/core/registry/service-registry.json +6586 -0
- package/.aios-core/core/registry/validate-registry.js +340 -0
- package/.aios-core/core/session/context-detector.js +229 -0
- package/.aios-core/core/session/context-loader.js +288 -0
- package/.aios-core/core/utils/output-formatter.js +298 -0
- package/.aios-core/core/utils/security-utils.js +333 -0
- package/.aios-core/core/utils/yaml-validator.js +419 -0
- package/.aios-core/core-config.yaml +382 -0
- package/.aios-core/data/agent-config-requirements.yaml +368 -0
- package/.aios-core/data/aios-kb.md +924 -0
- package/.aios-core/data/technical-preferences.md +4 -0
- package/.aios-core/data/workflow-patterns.yaml +267 -0
- package/.aios-core/development/README.md +142 -0
- package/.aios-core/development/agent-teams/team-all.yaml +15 -0
- package/.aios-core/development/agent-teams/team-fullstack.yaml +18 -0
- package/.aios-core/development/agent-teams/team-ide-minimal.yaml +10 -0
- package/.aios-core/development/agent-teams/team-no-ui.yaml +13 -0
- package/.aios-core/development/agent-teams/team-qa-focused.yaml +155 -0
- package/.aios-core/development/agents/aios-master.md +339 -0
- package/.aios-core/development/agents/analyst.md +195 -0
- package/.aios-core/development/agents/architect.md +359 -0
- package/.aios-core/development/agents/data-engineer.md +468 -0
- package/.aios-core/development/agents/dev.md +390 -0
- package/.aios-core/development/agents/devops.md +398 -0
- package/.aios-core/development/agents/pm.md +198 -0
- package/.aios-core/development/agents/po.md +256 -0
- package/.aios-core/development/agents/qa.md +312 -0
- package/.aios-core/development/agents/sm.md +220 -0
- package/.aios-core/development/agents/ux-design-expert.md +451 -0
- package/.aios-core/development/scripts/agent-assignment-resolver.js +231 -0
- package/.aios-core/development/scripts/agent-config-loader.js +624 -0
- package/.aios-core/development/scripts/agent-exit-hooks.js +96 -0
- package/.aios-core/development/scripts/apply-inline-greeting-all-agents.js +146 -0
- package/.aios-core/development/scripts/audit-agent-config.js +380 -0
- package/.aios-core/development/scripts/backlog-manager.js +404 -0
- package/.aios-core/development/scripts/batch-update-agents-session-context.js +95 -0
- package/.aios-core/development/scripts/decision-context.js +228 -0
- package/.aios-core/development/scripts/decision-log-generator.js +293 -0
- package/.aios-core/development/scripts/decision-log-indexer.js +284 -0
- package/.aios-core/development/scripts/decision-recorder.js +168 -0
- package/.aios-core/development/scripts/dev-context-loader.js +297 -0
- package/.aios-core/development/scripts/generate-greeting.js +160 -0
- package/.aios-core/development/scripts/greeting-builder.js +866 -0
- package/.aios-core/development/scripts/greeting-config-cli.js +85 -0
- package/.aios-core/development/scripts/greeting-preference-manager.js +145 -0
- package/.aios-core/development/scripts/migrate-task-to-v2.js +377 -0
- package/.aios-core/development/scripts/story-index-generator.js +337 -0
- package/.aios-core/development/scripts/story-manager.js +375 -0
- package/.aios-core/development/scripts/story-update-hook.js +259 -0
- package/.aios-core/development/scripts/task-identifier-resolver.js +145 -0
- package/.aios-core/development/scripts/test-greeting-system.js +142 -0
- package/.aios-core/development/scripts/validate-task-v2.js +319 -0
- package/.aios-core/development/scripts/workflow-navigator.js +214 -0
- package/.aios-core/development/tasks/add-mcp.md +319 -0
- package/.aios-core/development/tasks/advanced-elicitation.md +319 -0
- package/.aios-core/development/tasks/analyst-facilitate-brainstorming.md +342 -0
- package/.aios-core/development/tasks/analyze-framework.md +697 -0
- package/.aios-core/development/tasks/analyze-performance.md +637 -0
- package/.aios-core/development/tasks/apply-qa-fixes.md +340 -0
- package/.aios-core/development/tasks/architect-analyze-impact.md +827 -0
- package/.aios-core/development/tasks/audit-codebase.md +429 -0
- package/.aios-core/development/tasks/audit-tailwind-config.md +270 -0
- package/.aios-core/development/tasks/audit-utilities.md +358 -0
- package/.aios-core/development/tasks/bootstrap-shadcn-library.md +286 -0
- package/.aios-core/development/tasks/brownfield-create-epic.md +486 -0
- package/.aios-core/development/tasks/brownfield-create-story.md +357 -0
- package/.aios-core/development/tasks/build-component.md +478 -0
- package/.aios-core/development/tasks/calculate-roi.md +455 -0
- package/.aios-core/development/tasks/ci-cd-configuration.md +764 -0
- package/.aios-core/development/tasks/cleanup-utilities.md +670 -0
- package/.aios-core/development/tasks/collaborative-edit.md +1109 -0
- package/.aios-core/development/tasks/compose-molecule.md +284 -0
- package/.aios-core/development/tasks/consolidate-patterns.md +414 -0
- package/.aios-core/development/tasks/correct-course.md +280 -0
- package/.aios-core/development/tasks/create-agent.md +322 -0
- package/.aios-core/development/tasks/create-brownfield-story.md +727 -0
- package/.aios-core/development/tasks/create-deep-research-prompt.md +499 -0
- package/.aios-core/development/tasks/create-doc.md +316 -0
- package/.aios-core/development/tasks/create-next-story.md +774 -0
- package/.aios-core/development/tasks/create-suite.md +284 -0
- package/.aios-core/development/tasks/create-task.md +372 -0
- package/.aios-core/development/tasks/create-workflow.md +371 -0
- package/.aios-core/development/tasks/db-analyze-hotpaths.md +572 -0
- package/.aios-core/development/tasks/db-apply-migration.md +381 -0
- package/.aios-core/development/tasks/db-bootstrap.md +642 -0
- package/.aios-core/development/tasks/db-domain-modeling.md +693 -0
- package/.aios-core/development/tasks/db-dry-run.md +293 -0
- package/.aios-core/development/tasks/db-env-check.md +260 -0
- package/.aios-core/development/tasks/db-expansion-pack-integration.md +663 -0
- package/.aios-core/development/tasks/db-explain.md +631 -0
- package/.aios-core/development/tasks/db-impersonate.md +495 -0
- package/.aios-core/development/tasks/db-load-csv.md +593 -0
- package/.aios-core/development/tasks/db-policy-apply.md +653 -0
- package/.aios-core/development/tasks/db-rls-audit.md +411 -0
- package/.aios-core/development/tasks/db-rollback.md +739 -0
- package/.aios-core/development/tasks/db-run-sql.md +613 -0
- package/.aios-core/development/tasks/db-schema-audit.md +1011 -0
- package/.aios-core/development/tasks/db-seed.md +390 -0
- package/.aios-core/development/tasks/db-smoke-test.md +351 -0
- package/.aios-core/development/tasks/db-snapshot.md +569 -0
- package/.aios-core/development/tasks/db-supabase-setup.md +712 -0
- package/.aios-core/development/tasks/db-verify-order.md +515 -0
- package/.aios-core/development/tasks/deprecate-component.md +957 -0
- package/.aios-core/development/tasks/dev-apply-qa-fixes.md +318 -0
- package/.aios-core/development/tasks/dev-backlog-debt.md +469 -0
- package/.aios-core/development/tasks/dev-develop-story.md +846 -0
- package/.aios-core/development/tasks/dev-improve-code-quality.md +873 -0
- package/.aios-core/development/tasks/dev-optimize-performance.md +1034 -0
- package/.aios-core/development/tasks/dev-suggest-refactoring.md +871 -0
- package/.aios-core/development/tasks/dev-validate-next-story.md +349 -0
- package/.aios-core/development/tasks/document-project.md +553 -0
- package/.aios-core/development/tasks/environment-bootstrap.md +1311 -0
- package/.aios-core/development/tasks/execute-checklist.md +301 -0
- package/.aios-core/development/tasks/export-design-tokens-dtcg.md +274 -0
- package/.aios-core/development/tasks/extend-pattern.md +269 -0
- package/.aios-core/development/tasks/extract-tokens.md +467 -0
- package/.aios-core/development/tasks/facilitate-brainstorming-session.md +518 -0
- package/.aios-core/development/tasks/generate-ai-frontend-prompt.md +261 -0
- package/.aios-core/development/tasks/generate-documentation.md +284 -0
- package/.aios-core/development/tasks/generate-migration-strategy.md +522 -0
- package/.aios-core/development/tasks/generate-shock-report.md +501 -0
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +427 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +733 -0
- package/.aios-core/development/tasks/github-devops-repository-cleanup.md +374 -0
- package/.aios-core/development/tasks/github-devops-version-management.md +483 -0
- package/.aios-core/development/tasks/improve-self.md +823 -0
- package/.aios-core/development/tasks/index-docs.md +388 -0
- package/.aios-core/development/tasks/init-project-status.md +506 -0
- package/.aios-core/development/tasks/integrate-expansion-pack.md +314 -0
- package/.aios-core/development/tasks/kb-mode-interaction.md +284 -0
- package/.aios-core/development/tasks/learn-patterns.md +901 -0
- package/.aios-core/development/tasks/mcp-workflow.md +437 -0
- package/.aios-core/development/tasks/modify-agent.md +382 -0
- package/.aios-core/development/tasks/modify-task.md +425 -0
- package/.aios-core/development/tasks/modify-workflow.md +466 -0
- package/.aios-core/development/tasks/po-backlog-add.md +370 -0
- package/.aios-core/development/tasks/po-manage-story-backlog.md +523 -0
- package/.aios-core/development/tasks/po-pull-story-from-clickup.md +540 -0
- package/.aios-core/development/tasks/po-pull-story.md +316 -0
- package/.aios-core/development/tasks/po-stories-index.md +351 -0
- package/.aios-core/development/tasks/po-sync-story-to-clickup.md +457 -0
- package/.aios-core/development/tasks/po-sync-story.md +303 -0
- package/.aios-core/development/tasks/pr-automation.md +701 -0
- package/.aios-core/development/tasks/propose-modification.md +843 -0
- package/.aios-core/development/tasks/qa-backlog-add-followup.md +425 -0
- package/.aios-core/development/tasks/qa-gate.md +374 -0
- package/.aios-core/development/tasks/qa-generate-tests.md +1175 -0
- package/.aios-core/development/tasks/qa-nfr-assess.md +558 -0
- package/.aios-core/development/tasks/qa-review-proposal.md +1158 -0
- package/.aios-core/development/tasks/qa-review-story.md +683 -0
- package/.aios-core/development/tasks/qa-risk-profile.md +567 -0
- package/.aios-core/development/tasks/qa-run-tests.md +277 -0
- package/.aios-core/development/tasks/qa-test-design.md +388 -0
- package/.aios-core/development/tasks/qa-trace-requirements.md +477 -0
- package/.aios-core/development/tasks/release-management.md +723 -0
- package/.aios-core/development/tasks/security-audit.md +554 -0
- package/.aios-core/development/tasks/security-scan.md +790 -0
- package/.aios-core/development/tasks/setup-database.md +741 -0
- package/.aios-core/development/tasks/setup-design-system.md +462 -0
- package/.aios-core/development/tasks/setup-github.md +874 -0
- package/.aios-core/development/tasks/setup-llm-routing.md +229 -0
- package/.aios-core/development/tasks/setup-mcp-docker.md +584 -0
- package/.aios-core/development/tasks/shard-doc.md +538 -0
- package/.aios-core/development/tasks/sm-create-next-story.md +480 -0
- package/.aios-core/development/tasks/sync-documentation.md +865 -0
- package/.aios-core/development/tasks/tailwind-upgrade.md +294 -0
- package/.aios-core/development/tasks/test-as-user.md +621 -0
- package/.aios-core/development/tasks/test-validation-task.md +171 -0
- package/.aios-core/development/tasks/undo-last.md +347 -0
- package/.aios-core/development/tasks/update-manifest.md +410 -0
- package/.aios-core/development/tasks/ux-create-wireframe.md +617 -0
- package/.aios-core/development/tasks/ux-ds-scan-artifact.md +672 -0
- package/.aios-core/development/tasks/ux-user-research.md +559 -0
- package/.aios-core/development/tasks/validate-next-story.md +423 -0
- package/.aios-core/development/tasks/validate-structure.md +243 -0
- package/.aios-core/development/workflows/README.md +84 -0
- package/.aios-core/development/workflows/brownfield-fullstack.yaml +297 -0
- package/.aios-core/development/workflows/brownfield-service.yaml +187 -0
- package/.aios-core/development/workflows/brownfield-ui.yaml +197 -0
- package/.aios-core/development/workflows/greenfield-fullstack.yaml +333 -0
- package/.aios-core/development/workflows/greenfield-service.yaml +206 -0
- package/.aios-core/development/workflows/greenfield-ui.yaml +235 -0
- package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
- package/.aios-core/docs/component-creation-guide.md +458 -0
- package/.aios-core/docs/session-update-pattern.md +307 -0
- package/.aios-core/docs/standards/AGENT-PERSONALIZATION-STANDARD-V1.md +572 -0
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +185 -0
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +354 -0
- package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +1963 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +821 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +1190 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +439 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1339 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +5398 -0
- package/.aios-core/docs/standards/EXECUTOR-DECISION-TREE.md +697 -0
- package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +511 -0
- package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +556 -0
- package/.aios-core/docs/standards/STANDARDS-INDEX.md +210 -0
- package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +550 -0
- package/.aios-core/docs/standards/TASK-FORMAT-SPECIFICATION-V1.md +1414 -0
- package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +523 -0
- package/.aios-core/docs/template-syntax.md +267 -0
- package/.aios-core/docs/troubleshooting-guide.md +625 -0
- package/.aios-core/elicitation/agent-elicitation.js +272 -0
- package/.aios-core/elicitation/task-elicitation.js +281 -0
- package/.aios-core/elicitation/workflow-elicitation.js +315 -0
- package/.aios-core/index.d.ts +8 -0
- package/.aios-core/index.esm.js +16 -0
- package/.aios-core/index.js +16 -0
- package/.aios-core/infrastructure/README.md +126 -0
- package/.aios-core/infrastructure/index.js +199 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/README.md +59 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/clickup-adapter.js +345 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/github-adapter.js +392 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/jira-adapter.js +448 -0
- package/.aios-core/infrastructure/integrations/pm-adapters/local-adapter.js +175 -0
- package/.aios-core/infrastructure/scripts/_archived/final-todo-count.js +122 -0
- package/.aios-core/infrastructure/scripts/_archived/fix-yaml-formatting.js +89 -0
- package/.aios-core/infrastructure/scripts/_archived/migration-generator.js +780 -0
- package/.aios-core/infrastructure/scripts/_archived/migration-path-generator.js +950 -0
- package/.aios-core/infrastructure/scripts/_archived/phase2-entrada-saida-errors.js +425 -0
- package/.aios-core/infrastructure/scripts/_archived/phase2-spot-check.js +132 -0
- package/.aios-core/infrastructure/scripts/_archived/phase3-tools-scripts-validation.js +381 -0
- package/.aios-core/infrastructure/scripts/_archived/phase4-metadata-performance.js +203 -0
- package/.aios-core/infrastructure/scripts/_archived/test-yaml-parsing.js +24 -0
- package/.aios-core/infrastructure/scripts/_archived/verify-yaml-fix.js +51 -0
- package/.aios-core/infrastructure/scripts/aios-validator.js +294 -0
- package/.aios-core/infrastructure/scripts/approval-workflow.js +643 -0
- package/.aios-core/infrastructure/scripts/atomic-layer-classifier.js +308 -0
- package/.aios-core/infrastructure/scripts/backup-manager.js +607 -0
- package/.aios-core/infrastructure/scripts/batch-creator.js +608 -0
- package/.aios-core/infrastructure/scripts/branch-manager.js +391 -0
- package/.aios-core/infrastructure/scripts/capability-analyzer.js +535 -0
- package/.aios-core/infrastructure/scripts/clickup-helpers.js +226 -0
- package/.aios-core/infrastructure/scripts/code-quality-improver.js +1312 -0
- package/.aios-core/infrastructure/scripts/commit-message-generator.js +850 -0
- package/.aios-core/infrastructure/scripts/component-generator.js +738 -0
- package/.aios-core/infrastructure/scripts/component-metadata.js +627 -0
- package/.aios-core/infrastructure/scripts/component-search.js +277 -0
- package/.aios-core/infrastructure/scripts/config-cache.js +322 -0
- package/.aios-core/infrastructure/scripts/config-loader.js +349 -0
- package/.aios-core/infrastructure/scripts/conflict-resolver.js +675 -0
- package/.aios-core/infrastructure/scripts/coverage-analyzer.js +882 -0
- package/.aios-core/infrastructure/scripts/dependency-analyzer.js +638 -0
- package/.aios-core/infrastructure/scripts/dependency-impact-analyzer.js +703 -0
- package/.aios-core/infrastructure/scripts/diff-generator.js +129 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/brownfield-analyzer.js +501 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/config-generator.js +329 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/deployment-config-loader.js +282 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/doc-generator.js +331 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/gitignore-generator.js +313 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/index.js +74 -0
- package/.aios-core/infrastructure/scripts/documentation-integrity/mode-detector.js +358 -0
- package/.aios-core/infrastructure/scripts/documentation-synchronizer.js +1432 -0
- package/.aios-core/infrastructure/scripts/framework-analyzer.js +746 -0
- package/.aios-core/infrastructure/scripts/git-config-detector.js +293 -0
- package/.aios-core/infrastructure/scripts/git-wrapper.js +443 -0
- package/.aios-core/infrastructure/scripts/improvement-engine.js +758 -0
- package/.aios-core/infrastructure/scripts/improvement-validator.js +710 -0
- package/.aios-core/infrastructure/scripts/llm-routing/install-llm-routing.js +267 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-free.cmd +80 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-free.sh +62 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-max.cmd +26 -0
- package/.aios-core/infrastructure/scripts/llm-routing/templates/claude-max.sh +18 -0
- package/.aios-core/infrastructure/scripts/modification-risk-assessment.js +970 -0
- package/.aios-core/infrastructure/scripts/modification-validator.js +555 -0
- package/.aios-core/infrastructure/scripts/output-formatter.js +297 -0
- package/.aios-core/infrastructure/scripts/performance-analyzer.js +758 -0
- package/.aios-core/infrastructure/scripts/performance-and-error-resolver.js +258 -0
- package/.aios-core/infrastructure/scripts/performance-optimizer.js +1902 -0
- package/.aios-core/infrastructure/scripts/performance-tracker.js +452 -0
- package/.aios-core/infrastructure/scripts/pm-adapter-factory.js +181 -0
- package/.aios-core/infrastructure/scripts/pm-adapter.js +134 -0
- package/.aios-core/infrastructure/scripts/project-status-loader.js +445 -0
- package/.aios-core/infrastructure/scripts/refactoring-suggester.js +1139 -0
- package/.aios-core/infrastructure/scripts/repository-detector.js +64 -0
- package/.aios-core/infrastructure/scripts/sandbox-tester.js +618 -0
- package/.aios-core/infrastructure/scripts/security-checker.js +359 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/index.js +375 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/manifest-generator.js +410 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/naming-rules.yaml +285 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/rules/placement-rules.yaml +262 -0
- package/.aios-core/infrastructure/scripts/source-tree-guardian/validator.js +468 -0
- package/.aios-core/infrastructure/scripts/spot-check-validator.js +149 -0
- package/.aios-core/infrastructure/scripts/status-mapper.js +115 -0
- package/.aios-core/infrastructure/scripts/template-engine.js +240 -0
- package/.aios-core/infrastructure/scripts/template-validator.js +279 -0
- package/.aios-core/infrastructure/scripts/test-generator.js +844 -0
- package/.aios-core/infrastructure/scripts/test-quality-assessment.js +1081 -0
- package/.aios-core/infrastructure/scripts/test-utilities-fast.js +126 -0
- package/.aios-core/infrastructure/scripts/test-utilities.js +200 -0
- package/.aios-core/infrastructure/scripts/tool-resolver.js +360 -0
- package/.aios-core/infrastructure/scripts/transaction-manager.js +590 -0
- package/.aios-core/infrastructure/scripts/usage-analytics.js +634 -0
- package/.aios-core/infrastructure/scripts/validate-output-pattern.js +213 -0
- package/.aios-core/infrastructure/scripts/visual-impact-generator.js +1056 -0
- package/.aios-core/infrastructure/scripts/yaml-validator.js +397 -0
- package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -0
- package/.aios-core/infrastructure/templates/core-config/core-config-brownfield.tmpl.yaml +182 -0
- package/.aios-core/infrastructure/templates/core-config/core-config-greenfield.tmpl.yaml +127 -0
- package/.aios-core/infrastructure/templates/github-workflows/README.md +109 -0
- package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -0
- package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -0
- package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -0
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -0
- package/.aios-core/infrastructure/templates/project-docs/coding-standards-tmpl.md +346 -0
- package/.aios-core/infrastructure/templates/project-docs/source-tree-tmpl.md +177 -0
- package/.aios-core/infrastructure/templates/project-docs/tech-stack-tmpl.md +267 -0
- package/.aios-core/infrastructure/tests/project-status-loader.test.js +394 -0
- package/.aios-core/infrastructure/tests/regression-suite-v2.md +621 -0
- package/.aios-core/infrastructure/tests/utilities-audit-results.json +501 -0
- package/.aios-core/infrastructure/tests/validate-module.js +97 -0
- package/.aios-core/infrastructure/tools/README.md +222 -0
- package/.aios-core/infrastructure/tools/cli/github-cli.yaml +200 -0
- package/.aios-core/infrastructure/tools/cli/llm-routing.yaml +126 -0
- package/.aios-core/infrastructure/tools/cli/railway-cli.yaml +260 -0
- package/.aios-core/infrastructure/tools/cli/supabase-cli.yaml +224 -0
- package/.aios-core/infrastructure/tools/local/ffmpeg.yaml +261 -0
- package/.aios-core/infrastructure/tools/mcp/21st-dev-magic.yaml +127 -0
- package/.aios-core/infrastructure/tools/mcp/browser.yaml +103 -0
- package/.aios-core/infrastructure/tools/mcp/clickup.yaml +534 -0
- package/.aios-core/infrastructure/tools/mcp/context7.yaml +78 -0
- package/.aios-core/infrastructure/tools/mcp/desktop-commander.yaml +180 -0
- package/.aios-core/infrastructure/tools/mcp/exa.yaml +103 -0
- package/.aios-core/infrastructure/tools/mcp/google-workspace.yaml +930 -0
- package/.aios-core/infrastructure/tools/mcp/n8n.yaml +551 -0
- package/.aios-core/infrastructure/tools/mcp/supabase.yaml +808 -0
- package/.aios-core/install-manifest.yaml +347 -0
- package/.aios-core/manifests/agents.csv +1 -0
- package/.aios-core/manifests/schema/manifest-schema.json +190 -0
- package/.aios-core/manifests/tasks.csv +121 -0
- package/.aios-core/manifests/workers.csv +204 -0
- package/.aios-core/package.json +103 -0
- package/.aios-core/product/README.md +56 -0
- package/.aios-core/product/checklists/architect-checklist.md +444 -0
- package/.aios-core/product/checklists/change-checklist.md +183 -0
- package/.aios-core/product/checklists/database-design-checklist.md +119 -0
- package/.aios-core/product/checklists/dba-predeploy-checklist.md +97 -0
- package/.aios-core/product/checklists/dba-rollback-checklist.md +99 -0
- package/.aios-core/product/checklists/pm-checklist.md +376 -0
- package/.aios-core/product/checklists/po-master-checklist.md +442 -0
- package/.aios-core/product/checklists/pre-push-checklist.md +108 -0
- package/.aios-core/product/checklists/release-checklist.md +122 -0
- package/.aios-core/product/checklists/story-dod-checklist.md +102 -0
- package/.aios-core/product/checklists/story-draft-checklist.md +216 -0
- package/.aios-core/product/data/brainstorming-techniques.md +37 -0
- package/.aios-core/product/data/elicitation-methods.md +135 -0
- package/.aios-core/product/data/mode-selection-best-practices.md +471 -0
- package/.aios-core/product/data/test-levels-framework.md +149 -0
- package/.aios-core/product/data/test-priorities-matrix.md +175 -0
- package/.aios-core/product/templates/1mcp-config.yaml +225 -0
- package/.aios-core/product/templates/activation-instructions-inline-greeting.yaml +63 -0
- package/.aios-core/product/templates/activation-instructions-template.md +258 -0
- package/.aios-core/product/templates/adr.hbs +125 -0
- package/.aios-core/product/templates/agent-template.yaml +121 -0
- package/.aios-core/product/templates/architecture-tmpl.yaml +651 -0
- package/.aios-core/product/templates/brainstorming-output-tmpl.yaml +156 -0
- package/.aios-core/product/templates/brownfield-architecture-tmpl.yaml +476 -0
- package/.aios-core/product/templates/brownfield-prd-tmpl.yaml +280 -0
- package/.aios-core/product/templates/changelog-template.md +134 -0
- package/.aios-core/product/templates/command-rationalization-matrix.md +152 -0
- package/.aios-core/product/templates/competitor-analysis-tmpl.yaml +293 -0
- package/.aios-core/product/templates/component-react-tmpl.tsx +98 -0
- package/.aios-core/product/templates/dbdr.hbs +241 -0
- package/.aios-core/product/templates/design-story-tmpl.yaml +587 -0
- package/.aios-core/product/templates/ds-artifact-analysis.md +70 -0
- package/.aios-core/product/templates/engine/elicitation.js +298 -0
- package/.aios-core/product/templates/engine/index.js +308 -0
- package/.aios-core/product/templates/engine/loader.js +231 -0
- package/.aios-core/product/templates/engine/renderer.js +343 -0
- package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -0
- package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -0
- package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -0
- package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -0
- package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -0
- package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -0
- package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -0
- package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -0
- package/.aios-core/product/templates/engine/validator.js +294 -0
- package/.aios-core/product/templates/epic.hbs +212 -0
- package/.aios-core/product/templates/eslintrc-security.json +32 -0
- package/.aios-core/product/templates/front-end-architecture-tmpl.yaml +206 -0
- package/.aios-core/product/templates/front-end-spec-tmpl.yaml +349 -0
- package/.aios-core/product/templates/fullstack-architecture-tmpl.yaml +805 -0
- package/.aios-core/product/templates/github-actions-cd.yml +212 -0
- package/.aios-core/product/templates/github-actions-ci.yml +172 -0
- package/.aios-core/product/templates/github-pr-template.md +67 -0
- package/.aios-core/product/templates/gordon-mcp.yaml +140 -0
- package/.aios-core/product/templates/ide-rules/antigravity-rules.md +115 -0
- package/.aios-core/product/templates/ide-rules/claude-rules.md +221 -0
- package/.aios-core/product/templates/ide-rules/cline-rules.md +84 -0
- package/.aios-core/product/templates/ide-rules/copilot-rules.md +92 -0
- package/.aios-core/product/templates/ide-rules/cursor-rules.md +115 -0
- package/.aios-core/product/templates/ide-rules/gemini-rules.md +85 -0
- package/.aios-core/product/templates/ide-rules/roo-rules.md +86 -0
- package/.aios-core/product/templates/ide-rules/trae-rules.md +104 -0
- package/.aios-core/product/templates/ide-rules/windsurf-rules.md +80 -0
- package/.aios-core/product/templates/index-strategy-tmpl.yaml +53 -0
- package/.aios-core/product/templates/market-research-tmpl.yaml +252 -0
- package/.aios-core/product/templates/mcp-workflow.js +271 -0
- package/.aios-core/product/templates/migration-plan-tmpl.yaml +1022 -0
- package/.aios-core/product/templates/migration-strategy-tmpl.md +524 -0
- package/.aios-core/product/templates/personalized-agent-template.md +258 -0
- package/.aios-core/product/templates/personalized-checklist-template.md +340 -0
- package/.aios-core/product/templates/personalized-task-template-v2.md +905 -0
- package/.aios-core/product/templates/personalized-task-template.md +344 -0
- package/.aios-core/product/templates/personalized-template-file.yaml +322 -0
- package/.aios-core/product/templates/personalized-workflow-template.yaml +460 -0
- package/.aios-core/product/templates/pmdr.hbs +186 -0
- package/.aios-core/product/templates/prd-tmpl.yaml +202 -0
- package/.aios-core/product/templates/prd-v2.0.hbs +216 -0
- package/.aios-core/product/templates/prd.hbs +201 -0
- package/.aios-core/product/templates/project-brief-tmpl.yaml +221 -0
- package/.aios-core/product/templates/qa-gate-tmpl.yaml +240 -0
- package/.aios-core/product/templates/rls-policies-tmpl.yaml +1203 -0
- package/.aios-core/product/templates/schema-design-tmpl.yaml +428 -0
- package/.aios-core/product/templates/shock-report-tmpl.html +502 -0
- package/.aios-core/product/templates/state-persistence-tmpl.yaml +219 -0
- package/.aios-core/product/templates/story-tmpl.yaml +332 -0
- package/.aios-core/product/templates/story.hbs +263 -0
- package/.aios-core/product/templates/task-execution-report.md +495 -0
- package/.aios-core/product/templates/task-template.md +123 -0
- package/.aios-core/product/templates/task.hbs +170 -0
- package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -0
- package/.aios-core/product/templates/tmpl-migration-script.sql +91 -0
- package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -0
- package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -0
- package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -0
- package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -0
- package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -0
- package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -0
- package/.aios-core/product/templates/tmpl-seed-data.sql +140 -0
- package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -0
- package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -0
- package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -0
- package/.aios-core/product/templates/tmpl-trigger.sql +152 -0
- package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -0
- package/.aios-core/product/templates/tmpl-view.sql +177 -0
- package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -0
- package/.aios-core/product/templates/token-exports-tailwind-tmpl.js +395 -0
- package/.aios-core/product/templates/tokens-schema-tmpl.yaml +305 -0
- package/.aios-core/product/templates/workflow-template.yaml +134 -0
- package/.aios-core/quality/metrics-collector.js +572 -0
- package/.aios-core/quality/metrics-hook.js +260 -0
- package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -0
- package/.aios-core/quality/seed-metrics.js +336 -0
- package/.aios-core/scripts/README.md +354 -0
- package/.aios-core/scripts/aios-doc-template.md +325 -0
- package/.aios-core/scripts/batch-migrate-phase1.ps1 +36 -0
- package/.aios-core/scripts/batch-migrate-phase2.ps1 +88 -0
- package/.aios-core/scripts/batch-migrate-phase3.ps1 +45 -0
- package/.aios-core/scripts/command-execution-hook.js +201 -0
- package/.aios-core/scripts/context-detector.js +226 -0
- package/.aios-core/scripts/elicitation-engine.js +385 -0
- package/.aios-core/scripts/elicitation-session-manager.js +300 -0
- package/.aios-core/scripts/migrate-framework-docs.sh +300 -0
- package/.aios-core/scripts/session-context-loader.js +286 -0
- package/.aios-core/scripts/test-template-system.js +941 -0
- package/.aios-core/scripts/validate-phase1.ps1 +35 -0
- package/.aios-core/scripts/workflow-management.md +69 -0
- package/.aios-core/tasks/find-component.md.legacy +391 -0
- package/.aios-core/tasks/generate-commit-message.md.legacy +426 -0
- package/.aios-core/tasks/generate-migration.md.legacy +382 -0
- package/.aios-core/tasks/rollback-modification.md.legacy +307 -0
- package/.aios-core/tasks/update-tests.md.legacy +283 -0
- package/.aios-core/user-guide.md +1413 -0
- package/.aios-core/working-in-the-brownfield.md +361 -0
- package/.claude/CLAUDE.md +221 -0
- package/LICENSE +48 -0
- package/README.md +703 -0
- package/bin/aios-init-old.js +532 -0
- package/bin/aios-init-v4.js +390 -0
- package/bin/aios-init.backup-v1.1.4.js +352 -0
- package/bin/aios-init.js +736 -0
- package/bin/aios-minimal.js +26 -0
- package/bin/aios.js +279 -0
- package/bin/migrate-pm-config.js +219 -0
- package/bin/modules/env-config.js +436 -0
- package/bin/modules/mcp-installer.js +383 -0
- package/bin/utils/install-errors.js +339 -0
- package/bin/utils/install-transaction.js +445 -0
- package/index.d.ts +19 -0
- package/index.esm.js +21 -0
- package/index.js +94 -0
- package/package.json +161 -0
- package/packages/installer/package.json +39 -0
- package/packages/installer/src/config/configure-environment.js +312 -0
- package/packages/installer/src/config/templates/core-config-template.js +183 -0
- package/packages/installer/src/config/templates/env-template.js +127 -0
- package/packages/installer/src/config/validation/config-validator.js +243 -0
- package/packages/installer/src/detection/detect-project-type.js +81 -0
- package/packages/installer/src/wizard/wizard.js +244 -0
- package/packages/installer/tests/integration/environment-configuration.test.js +328 -0
- package/packages/installer/tests/integration/wizard-detection.test.js +349 -0
- package/packages/installer/tests/unit/config-validator.test.js +315 -0
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +401 -0
- package/packages/installer/tests/unit/env-template.test.js +185 -0
- package/src/config/ide-configs.js +189 -0
- package/src/installer/aios-core-installer.js +319 -0
- package/src/installer/dependency-installer.js +335 -0
- package/src/utils/aios-colors.js +234 -0
- package/src/wizard/feedback.js +218 -0
- package/src/wizard/ide-config-generator.js +488 -0
- package/src/wizard/ide-selector.js +84 -0
- package/src/wizard/index.js +589 -0
- package/src/wizard/questions.js +249 -0
- package/src/wizard/validation/index.js +120 -0
- package/src/wizard/validation/report-generator.js +269 -0
- package/src/wizard/validation/troubleshooting-system.js +346 -0
- package/src/wizard/validation/validators/config-validator.js +362 -0
- package/src/wizard/validation/validators/dependency-validator.js +333 -0
- package/src/wizard/validation/validators/file-structure-validator.js +181 -0
- package/src/wizard/validation/validators/mcp-health-checker.js +310 -0
- package/src/wizard/validators.js +274 -0
- package/templates/squad/LICENSE +21 -0
- package/templates/squad/README.md +37 -0
- package/templates/squad/agents/example-agent.yaml +36 -0
- package/templates/squad/package.json +19 -0
- package/templates/squad/squad.yaml +25 -0
- package/templates/squad/tasks/example-task.yaml +46 -0
- package/templates/squad/templates/example-template.md +24 -0
- package/templates/squad/tests/example-agent.test.js +53 -0
- package/templates/squad/workflows/example-workflow.yaml +54 -0
- package/tools/package-builder.js +35 -0
|
@@ -0,0 +1,1203 @@
|
|
|
1
|
+
---
|
|
2
|
+
template_name: "Supabase RLS Policies"
|
|
3
|
+
template_version: "1.0.0"
|
|
4
|
+
output_format: "markdown"
|
|
5
|
+
destination: "rls-policies.md"
|
|
6
|
+
description: "Row Level Security policies for Supabase tables"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
sections:
|
|
10
|
+
- id: overview
|
|
11
|
+
title: "RLS Overview"
|
|
12
|
+
instruction: |
|
|
13
|
+
Document the Row Level Security strategy:
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
Explain the overall security model and why RLS is being used.
|
|
17
|
+
|
|
18
|
+
## Authentication Context
|
|
19
|
+
- How users are authenticated (Supabase Auth, JWT, etc)
|
|
20
|
+
- Available auth context variables:
|
|
21
|
+
- `auth.uid()` - Current user ID
|
|
22
|
+
- `auth.jwt()` - JWT claims
|
|
23
|
+
- `auth.email()` - User email
|
|
24
|
+
- Custom claims in JWT
|
|
25
|
+
|
|
26
|
+
## Security Model
|
|
27
|
+
- Role-based access control (RBAC)
|
|
28
|
+
- Multi-tenancy approach (if applicable)
|
|
29
|
+
- Public vs authenticated vs specific role access
|
|
30
|
+
|
|
31
|
+
## Performance Considerations
|
|
32
|
+
- RLS policy performance impact
|
|
33
|
+
- Indexing strategy to support policies
|
|
34
|
+
- Caching considerations
|
|
35
|
+
|
|
36
|
+
## Testing Strategy
|
|
37
|
+
- How policies will be tested
|
|
38
|
+
- Test users and scenarios
|
|
39
|
+
elicit: true
|
|
40
|
+
|
|
41
|
+
- id: policy-patterns
|
|
42
|
+
title: "Common Policy Patterns"
|
|
43
|
+
instruction: |
|
|
44
|
+
Document reusable policy patterns used across tables:
|
|
45
|
+
|
|
46
|
+
## Pattern 1: Owner-Only Access
|
|
47
|
+
```sql
|
|
48
|
+
-- Users can only access their own records
|
|
49
|
+
(auth.uid() = user_id)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Pattern 2: Tenant-Based Access
|
|
53
|
+
```sql
|
|
54
|
+
-- Users can access records in their organization
|
|
55
|
+
(auth.uid() IN (
|
|
56
|
+
SELECT user_id FROM org_members
|
|
57
|
+
WHERE org_id = table.org_id
|
|
58
|
+
))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Pattern 3: Role-Based Access
|
|
62
|
+
```sql
|
|
63
|
+
-- Only admins can access
|
|
64
|
+
((auth.jwt() ->> 'role')::text = 'admin')
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Pattern 4: Public Read, Authenticated Write
|
|
68
|
+
```sql
|
|
69
|
+
-- SELECT: true (public read)
|
|
70
|
+
-- INSERT/UPDATE/DELETE: auth.uid() IS NOT NULL
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Pattern 5: Hierarchical Permissions
|
|
74
|
+
```sql
|
|
75
|
+
-- Access based on organizational hierarchy
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Document any other patterns specific to your application.
|
|
79
|
+
elicit: true
|
|
80
|
+
|
|
81
|
+
- id: table-policies
|
|
82
|
+
title: "Table-by-Table Policies"
|
|
83
|
+
instruction: |
|
|
84
|
+
For each table requiring RLS, document comprehensive policies:
|
|
85
|
+
|
|
86
|
+
# Table: `table_name`
|
|
87
|
+
|
|
88
|
+
## Enable RLS
|
|
89
|
+
```sql
|
|
90
|
+
ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## SELECT Policies
|
|
94
|
+
|
|
95
|
+
### Policy: `policy_name_select`
|
|
96
|
+
**Purpose**: Describe who can read what
|
|
97
|
+
|
|
98
|
+
**Policy Expression**:
|
|
99
|
+
```sql
|
|
100
|
+
CREATE POLICY "policy_name_select"
|
|
101
|
+
ON table_name
|
|
102
|
+
FOR SELECT
|
|
103
|
+
TO authenticated -- or public, anon, etc
|
|
104
|
+
USING (
|
|
105
|
+
-- Policy expression
|
|
106
|
+
auth.uid() = user_id
|
|
107
|
+
);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Rationale**: Explain the business rule
|
|
111
|
+
|
|
112
|
+
**Performance**: Any indexes needed to support this policy
|
|
113
|
+
|
|
114
|
+
## INSERT Policies
|
|
115
|
+
|
|
116
|
+
### Policy: `policy_name_insert`
|
|
117
|
+
**Purpose**: Describe who can create records
|
|
118
|
+
|
|
119
|
+
**Policy Expression**:
|
|
120
|
+
```sql
|
|
121
|
+
CREATE POLICY "policy_name_insert"
|
|
122
|
+
ON table_name
|
|
123
|
+
FOR INSERT
|
|
124
|
+
TO authenticated
|
|
125
|
+
WITH CHECK (
|
|
126
|
+
-- Policy expression
|
|
127
|
+
auth.uid() = user_id
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Validation**: What validations this ensures
|
|
132
|
+
|
|
133
|
+
## UPDATE Policies
|
|
134
|
+
|
|
135
|
+
### Policy: `policy_name_update`
|
|
136
|
+
**Purpose**: Describe who can modify records
|
|
137
|
+
|
|
138
|
+
**Policy Expression**:
|
|
139
|
+
```sql
|
|
140
|
+
CREATE POLICY "policy_name_update"
|
|
141
|
+
ON table_name
|
|
142
|
+
FOR UPDATE
|
|
143
|
+
TO authenticated
|
|
144
|
+
USING (
|
|
145
|
+
-- Who can see the record to update it
|
|
146
|
+
auth.uid() = user_id
|
|
147
|
+
)
|
|
148
|
+
WITH CHECK (
|
|
149
|
+
-- What values they can set
|
|
150
|
+
auth.uid() = user_id
|
|
151
|
+
);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Notes**: USING checks old values, WITH CHECK validates new values
|
|
155
|
+
|
|
156
|
+
## DELETE Policies
|
|
157
|
+
|
|
158
|
+
### Policy: `policy_name_delete`
|
|
159
|
+
**Purpose**: Describe who can delete records
|
|
160
|
+
|
|
161
|
+
**Policy Expression**:
|
|
162
|
+
```sql
|
|
163
|
+
CREATE POLICY "policy_name_delete"
|
|
164
|
+
ON table_name
|
|
165
|
+
FOR DELETE
|
|
166
|
+
TO authenticated
|
|
167
|
+
USING (
|
|
168
|
+
-- Who can delete
|
|
169
|
+
auth.uid() = user_id OR
|
|
170
|
+
(auth.jwt() ->> 'role')::text = 'admin'
|
|
171
|
+
);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## ALL Policies (if using combined policy)
|
|
175
|
+
|
|
176
|
+
Sometimes a single policy for all operations is clearer:
|
|
177
|
+
|
|
178
|
+
```sql
|
|
179
|
+
CREATE POLICY "policy_name_all"
|
|
180
|
+
ON table_name
|
|
181
|
+
FOR ALL
|
|
182
|
+
TO authenticated
|
|
183
|
+
USING (auth.uid() = user_id)
|
|
184
|
+
WITH CHECK (auth.uid() = user_id);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
Repeat this section for each table.
|
|
190
|
+
elicit: true
|
|
191
|
+
|
|
192
|
+
- id: public-tables
|
|
193
|
+
title: "Public Tables"
|
|
194
|
+
instruction: |
|
|
195
|
+
Document tables with public read access:
|
|
196
|
+
|
|
197
|
+
# Table: `public_table_name`
|
|
198
|
+
|
|
199
|
+
## Public Read Policy
|
|
200
|
+
```sql
|
|
201
|
+
ALTER TABLE public_table_name ENABLE ROW LEVEL SECURITY;
|
|
202
|
+
|
|
203
|
+
CREATE POLICY "public_read_policy"
|
|
204
|
+
ON public_table_name
|
|
205
|
+
FOR SELECT
|
|
206
|
+
TO anon, authenticated
|
|
207
|
+
USING (true);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Restricted Write Policy
|
|
211
|
+
```sql
|
|
212
|
+
CREATE POLICY "authenticated_write_policy"
|
|
213
|
+
ON public_table_name
|
|
214
|
+
FOR INSERT
|
|
215
|
+
TO authenticated
|
|
216
|
+
WITH CHECK (auth.uid() IS NOT NULL);
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Rationale**: Why this table is public
|
|
220
|
+
|
|
221
|
+
**Security Considerations**: What data is safe to expose
|
|
222
|
+
elicit: false
|
|
223
|
+
|
|
224
|
+
- id: service-role
|
|
225
|
+
title: "Service Role Bypass"
|
|
226
|
+
instruction: |
|
|
227
|
+
Document scenarios where service role (bypass RLS) is used:
|
|
228
|
+
|
|
229
|
+
## Service Role Usage
|
|
230
|
+
|
|
231
|
+
### Backend Operations
|
|
232
|
+
Operations that need to bypass RLS:
|
|
233
|
+
- Scheduled jobs (cron, edge functions with service key)
|
|
234
|
+
- Admin operations
|
|
235
|
+
- Data migration
|
|
236
|
+
- Analytics aggregation
|
|
237
|
+
|
|
238
|
+
### Safety Measures
|
|
239
|
+
- How service key is secured
|
|
240
|
+
- Where service role operations are logged
|
|
241
|
+
- Who has access to service key
|
|
242
|
+
|
|
243
|
+
### Alternatives
|
|
244
|
+
When possible, prefer:
|
|
245
|
+
- Security definer functions with RLS
|
|
246
|
+
- Elevated permission policies
|
|
247
|
+
- Temporary privilege escalation
|
|
248
|
+
elicit: false
|
|
249
|
+
|
|
250
|
+
- id: helper-functions
|
|
251
|
+
title: "Security Helper Functions"
|
|
252
|
+
instruction: |
|
|
253
|
+
Document PostgreSQL functions that support RLS:
|
|
254
|
+
|
|
255
|
+
## Function: `check_user_permission`
|
|
256
|
+
```sql
|
|
257
|
+
CREATE OR REPLACE FUNCTION check_user_permission(
|
|
258
|
+
user_id uuid,
|
|
259
|
+
resource_id uuid,
|
|
260
|
+
permission_type text
|
|
261
|
+
)
|
|
262
|
+
RETURNS boolean
|
|
263
|
+
LANGUAGE plpgsql
|
|
264
|
+
SECURITY DEFINER
|
|
265
|
+
AS $$
|
|
266
|
+
BEGIN
|
|
267
|
+
-- Permission checking logic
|
|
268
|
+
RETURN EXISTS (
|
|
269
|
+
SELECT 1 FROM permissions
|
|
270
|
+
WHERE user_id = $1
|
|
271
|
+
AND resource_id = $2
|
|
272
|
+
AND permission = $3
|
|
273
|
+
);
|
|
274
|
+
END;
|
|
275
|
+
$$;
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Usage in Policies**:
|
|
279
|
+
```sql
|
|
280
|
+
USING (check_user_permission(auth.uid(), id, 'read'))
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Function: `get_user_org_id`
|
|
284
|
+
```sql
|
|
285
|
+
CREATE OR REPLACE FUNCTION get_user_org_id()
|
|
286
|
+
RETURNS uuid
|
|
287
|
+
LANGUAGE sql
|
|
288
|
+
STABLE
|
|
289
|
+
AS $$
|
|
290
|
+
SELECT org_id FROM user_profiles
|
|
291
|
+
WHERE user_id = auth.uid();
|
|
292
|
+
$$;
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Usage in Policies**:
|
|
296
|
+
```sql
|
|
297
|
+
USING (org_id = get_user_org_id())
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Document all helper functions used in RLS policies.
|
|
301
|
+
elicit: false
|
|
302
|
+
|
|
303
|
+
- id: multi-tenancy
|
|
304
|
+
title: "Multi-Tenancy Implementation"
|
|
305
|
+
condition: "multi_tenant"
|
|
306
|
+
instruction: |
|
|
307
|
+
If implementing multi-tenancy with RLS:
|
|
308
|
+
|
|
309
|
+
## Tenant Isolation Strategy
|
|
310
|
+
|
|
311
|
+
### Tenant Identification
|
|
312
|
+
- How tenants are identified (org_id, team_id, etc)
|
|
313
|
+
- Where tenant ID is stored (JWT claim, database lookup)
|
|
314
|
+
|
|
315
|
+
### Tenant-Scoped Tables
|
|
316
|
+
|
|
317
|
+
For each tenant-scoped table:
|
|
318
|
+
|
|
319
|
+
```sql
|
|
320
|
+
-- Example: projects table
|
|
321
|
+
CREATE POLICY "tenant_isolation_policy"
|
|
322
|
+
ON projects
|
|
323
|
+
FOR ALL
|
|
324
|
+
TO authenticated
|
|
325
|
+
USING (
|
|
326
|
+
org_id = (auth.jwt() ->> 'org_id')::uuid
|
|
327
|
+
)
|
|
328
|
+
WITH CHECK (
|
|
329
|
+
org_id = (auth.jwt() ->> 'org_id')::uuid
|
|
330
|
+
);
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Cross-Tenant Scenarios
|
|
334
|
+
- Shared resources across tenants
|
|
335
|
+
- Super admin access
|
|
336
|
+
- Tenant-to-tenant relationships
|
|
337
|
+
|
|
338
|
+
### Performance
|
|
339
|
+
- Indexes on tenant_id columns
|
|
340
|
+
- Query patterns that leverage tenant isolation
|
|
341
|
+
elicit: true
|
|
342
|
+
|
|
343
|
+
- id: storage-policies
|
|
344
|
+
title: "Supabase Storage Policies"
|
|
345
|
+
instruction: |
|
|
346
|
+
RLS policies for Supabase Storage buckets (storage.objects table).
|
|
347
|
+
|
|
348
|
+
## Overview
|
|
349
|
+
|
|
350
|
+
Supabase Storage uses RLS on the `storage.objects` system table to control file access.
|
|
351
|
+
By default, Storage requires explicit RLS policies - no uploads allowed without policies.
|
|
352
|
+
|
|
353
|
+
## Pattern 1: User-Specific Uploads
|
|
354
|
+
|
|
355
|
+
Users can only upload files to their own folder:
|
|
356
|
+
|
|
357
|
+
```sql
|
|
358
|
+
CREATE POLICY "Users upload own avatars"
|
|
359
|
+
ON storage.objects
|
|
360
|
+
FOR INSERT
|
|
361
|
+
TO authenticated
|
|
362
|
+
WITH CHECK (
|
|
363
|
+
bucket_id = 'avatars' AND
|
|
364
|
+
(select auth.uid())::text = (storage.foldername(name))[1]
|
|
365
|
+
);
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**Folder Structure**: `avatars/{user_id}/filename.jpg`
|
|
369
|
+
|
|
370
|
+
**How it works**:
|
|
371
|
+
- `storage.foldername(name)` splits path by `/` returning array
|
|
372
|
+
- `[1]` gets first folder (user_id)
|
|
373
|
+
- Compares with authenticated user's ID
|
|
374
|
+
|
|
375
|
+
## Pattern 2: Public Read, Authenticated Write
|
|
376
|
+
|
|
377
|
+
Anyone can view files, only authenticated users can upload:
|
|
378
|
+
|
|
379
|
+
```sql
|
|
380
|
+
-- Public read
|
|
381
|
+
CREATE POLICY "Public avatars readable"
|
|
382
|
+
ON storage.objects
|
|
383
|
+
FOR SELECT
|
|
384
|
+
TO public
|
|
385
|
+
USING (bucket_id = 'avatars');
|
|
386
|
+
|
|
387
|
+
-- Authenticated write
|
|
388
|
+
CREATE POLICY "Authenticated upload avatars"
|
|
389
|
+
ON storage.objects
|
|
390
|
+
FOR INSERT
|
|
391
|
+
TO authenticated
|
|
392
|
+
WITH CHECK (bucket_id = 'avatars');
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Use case**: Public profile pictures, logos, marketing assets.
|
|
396
|
+
|
|
397
|
+
## Pattern 3: Tenant-Scoped Files
|
|
398
|
+
|
|
399
|
+
Users can only access files from their organization:
|
|
400
|
+
|
|
401
|
+
```sql
|
|
402
|
+
CREATE POLICY "Tenant file isolation"
|
|
403
|
+
ON storage.objects
|
|
404
|
+
FOR SELECT
|
|
405
|
+
TO authenticated
|
|
406
|
+
USING (
|
|
407
|
+
bucket_id = 'documents' AND
|
|
408
|
+
(storage.foldername(name))[1] = ((select auth.jwt()) ->> 'org_id')
|
|
409
|
+
);
|
|
410
|
+
|
|
411
|
+
CREATE POLICY "Tenant file uploads"
|
|
412
|
+
ON storage.objects
|
|
413
|
+
FOR INSERT
|
|
414
|
+
TO authenticated
|
|
415
|
+
WITH CHECK (
|
|
416
|
+
bucket_id = 'documents' AND
|
|
417
|
+
(storage.foldername(name))[1] = ((select auth.jwt()) ->> 'org_id')
|
|
418
|
+
);
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**Folder Structure**: `documents/{org_id}/{file_id}.pdf`
|
|
422
|
+
|
|
423
|
+
## Pattern 4: Delete Own Files
|
|
424
|
+
|
|
425
|
+
Users can delete their own files:
|
|
426
|
+
|
|
427
|
+
```sql
|
|
428
|
+
CREATE POLICY "Users delete own files"
|
|
429
|
+
ON storage.objects
|
|
430
|
+
FOR DELETE
|
|
431
|
+
TO authenticated
|
|
432
|
+
USING (
|
|
433
|
+
bucket_id = 'avatars' AND
|
|
434
|
+
(select auth.uid())::text = (storage.foldername(name))[1]
|
|
435
|
+
);
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## Pattern 5: File Overwriting (upsert)
|
|
439
|
+
|
|
440
|
+
For file overwriting via `upsert` option, grant SELECT + UPDATE:
|
|
441
|
+
|
|
442
|
+
```sql
|
|
443
|
+
-- Allow reading (required for upsert check)
|
|
444
|
+
CREATE POLICY "Users read own files"
|
|
445
|
+
ON storage.objects
|
|
446
|
+
FOR SELECT
|
|
447
|
+
TO authenticated
|
|
448
|
+
USING (
|
|
449
|
+
bucket_id = 'avatars' AND
|
|
450
|
+
(select auth.uid())::text = (storage.foldername(name))[1]
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
-- Allow updating (for upsert)
|
|
454
|
+
CREATE POLICY "Users update own files"
|
|
455
|
+
ON storage.objects
|
|
456
|
+
FOR UPDATE
|
|
457
|
+
TO authenticated
|
|
458
|
+
USING (
|
|
459
|
+
bucket_id = 'avatars' AND
|
|
460
|
+
(select auth.uid())::text = (storage.foldername(name))[1]
|
|
461
|
+
)
|
|
462
|
+
WITH CHECK (
|
|
463
|
+
bucket_id = 'avatars' AND
|
|
464
|
+
(select auth.uid())::text = (storage.foldername(name))[1]
|
|
465
|
+
);
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Bucket Configuration
|
|
469
|
+
|
|
470
|
+
Create buckets with appropriate public/private settings:
|
|
471
|
+
|
|
472
|
+
```sql
|
|
473
|
+
-- Create private bucket (requires policies)
|
|
474
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
475
|
+
VALUES ('avatars', 'avatars', false);
|
|
476
|
+
|
|
477
|
+
-- Create public bucket (files publicly accessible by URL)
|
|
478
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
479
|
+
VALUES ('public-images', 'public-images', true);
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
**Note**: Even public buckets respect RLS for uploads/deletes.
|
|
483
|
+
|
|
484
|
+
## Helper Functions
|
|
485
|
+
|
|
486
|
+
```sql
|
|
487
|
+
-- Extract user folder from path
|
|
488
|
+
CREATE OR REPLACE FUNCTION storage.user_owns_file(file_path text)
|
|
489
|
+
RETURNS boolean
|
|
490
|
+
LANGUAGE sql
|
|
491
|
+
STABLE
|
|
492
|
+
AS $$
|
|
493
|
+
SELECT (select auth.uid())::text = (storage.foldername(file_path))[1];
|
|
494
|
+
$$;
|
|
495
|
+
|
|
496
|
+
-- Usage in policy
|
|
497
|
+
CREATE POLICY "Users access own files"
|
|
498
|
+
ON storage.objects
|
|
499
|
+
FOR ALL
|
|
500
|
+
TO authenticated
|
|
501
|
+
USING (
|
|
502
|
+
bucket_id = 'private' AND
|
|
503
|
+
storage.user_owns_file(name)
|
|
504
|
+
);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Security Considerations
|
|
508
|
+
|
|
509
|
+
1. **Always validate bucket_id** in policies (prevent cross-bucket access)
|
|
510
|
+
2. **Use folder structure** for user/tenant isolation
|
|
511
|
+
3. **Set appropriate bucket public/private** settings
|
|
512
|
+
4. **Monitor storage size** per user/tenant (implement quotas)
|
|
513
|
+
5. **Validate file types** server-side (policies can't check content)
|
|
514
|
+
|
|
515
|
+
## Testing
|
|
516
|
+
|
|
517
|
+
Test storage policies with Supabase client:
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
// Test upload as user A
|
|
521
|
+
const { data, error } = await supabase.storage
|
|
522
|
+
.from('avatars')
|
|
523
|
+
.upload(`${user.id}/avatar.jpg`, file);
|
|
524
|
+
|
|
525
|
+
// Should succeed for own folder
|
|
526
|
+
expect(error).toBeNull();
|
|
527
|
+
|
|
528
|
+
// Test read as user B (should fail for user A's folder)
|
|
529
|
+
const { data: files, error: listError } = await supabase.storage
|
|
530
|
+
.from('avatars')
|
|
531
|
+
.list(`${otherUserId}/`);
|
|
532
|
+
|
|
533
|
+
// Should return empty or error
|
|
534
|
+
expect(files).toHaveLength(0);
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
## Performance
|
|
538
|
+
|
|
539
|
+
Storage policies are evaluated on every file operation.
|
|
540
|
+
|
|
541
|
+
**Optimize**:
|
|
542
|
+
- Use simple folder path checks (fast)
|
|
543
|
+
- Avoid complex JOINs in storage policies
|
|
544
|
+
- Cache JWT claims in helper functions
|
|
545
|
+
- Use indexes on bucket_id (already indexed by Supabase)
|
|
546
|
+
|
|
547
|
+
## Common Pitfalls
|
|
548
|
+
|
|
549
|
+
- **Forgetting SELECT policy** for upsert operations
|
|
550
|
+
- **Not validating bucket_id** (allows cross-bucket access)
|
|
551
|
+
- **Complex policies** (slow file operations)
|
|
552
|
+
- **Mixing public/private** bucket settings incorrectly
|
|
553
|
+
elicit: false
|
|
554
|
+
|
|
555
|
+
- id: performance-optimization
|
|
556
|
+
title: "RLS Performance Optimization"
|
|
557
|
+
instruction: |
|
|
558
|
+
Critical performance optimizations for RLS policies validated by Supabase documentation.
|
|
559
|
+
|
|
560
|
+
## 🚀 Optimization 1: Wrap Auth Functions with SELECT (94.97% faster)
|
|
561
|
+
|
|
562
|
+
**Critical Discovery** from Supabase docs: Wrapping auth functions enables query caching.
|
|
563
|
+
|
|
564
|
+
### ❌ SLOW (no caching):
|
|
565
|
+
```sql
|
|
566
|
+
CREATE POLICY "users_select"
|
|
567
|
+
ON users
|
|
568
|
+
FOR SELECT
|
|
569
|
+
TO authenticated
|
|
570
|
+
USING (auth.uid() = user_id);
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### ✅ FAST (cached, 94.97% improvement):
|
|
574
|
+
```sql
|
|
575
|
+
CREATE POLICY "users_select"
|
|
576
|
+
ON users
|
|
577
|
+
FOR SELECT
|
|
578
|
+
TO authenticated
|
|
579
|
+
USING ((select auth.uid()) = user_id);
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
**Why**: PostgreSQL caches the result of `(select auth.uid())` for the duration of the transaction,
|
|
583
|
+
avoiding repeated function calls.
|
|
584
|
+
|
|
585
|
+
**Impact**: **19x faster queries** in high-traffic scenarios.
|
|
586
|
+
|
|
587
|
+
**Apply to all auth functions**:
|
|
588
|
+
- `(select auth.uid())`
|
|
589
|
+
- `(select auth.jwt())`
|
|
590
|
+
- `(select auth.email())`
|
|
591
|
+
|
|
592
|
+
## 🚀 Optimization 2: Index Policy Columns (99.94% improvement)
|
|
593
|
+
|
|
594
|
+
**Always index columns used in policy expressions.**
|
|
595
|
+
|
|
596
|
+
```sql
|
|
597
|
+
-- Policy uses user_id
|
|
598
|
+
CREATE POLICY "user_policy" ON posts
|
|
599
|
+
USING ((select auth.uid()) = user_id);
|
|
600
|
+
|
|
601
|
+
-- Index user_id (99.94% faster)
|
|
602
|
+
CREATE INDEX idx_posts_user_id ON posts(user_id);
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Critical indexes**:
|
|
606
|
+
```sql
|
|
607
|
+
-- Tenant isolation
|
|
608
|
+
CREATE INDEX idx_table_org_id ON table_name(org_id);
|
|
609
|
+
|
|
610
|
+
-- Owner-based policies
|
|
611
|
+
CREATE INDEX idx_table_user_id ON table_name(user_id);
|
|
612
|
+
|
|
613
|
+
-- Time-based policies
|
|
614
|
+
CREATE INDEX idx_table_scheduling
|
|
615
|
+
ON table_name(publish_at, expire_at)
|
|
616
|
+
WHERE publish_at IS NOT NULL OR expire_at IS NOT NULL;
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## 🚀 Optimization 3: Filter Client-Side Explicitly
|
|
620
|
+
|
|
621
|
+
**Even with RLS policies, explicitly filter in client queries.**
|
|
622
|
+
|
|
623
|
+
```typescript
|
|
624
|
+
// ❌ Relies only on RLS
|
|
625
|
+
const { data } = await supabase
|
|
626
|
+
.from('users')
|
|
627
|
+
.select('*'); // Returns only own data due to RLS, but query planner doesn't know
|
|
628
|
+
|
|
629
|
+
// ✅ Explicit filter (helps query planner)
|
|
630
|
+
const { data } = await supabase
|
|
631
|
+
.from('users')
|
|
632
|
+
.select('*')
|
|
633
|
+
.eq('user_id', userId); // Query planner can use index
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
**Why**: Explicit filters help PostgreSQL query planner choose optimal index scan.
|
|
637
|
+
|
|
638
|
+
## 🚀 Optimization 4: Specify Roles Explicitly
|
|
639
|
+
|
|
640
|
+
```sql
|
|
641
|
+
-- ❌ Applies to all roles (unnecessary checks)
|
|
642
|
+
CREATE POLICY "policy" ON table USING (...);
|
|
643
|
+
|
|
644
|
+
-- ✅ Specific role (fewer checks)
|
|
645
|
+
CREATE POLICY "policy" ON table
|
|
646
|
+
TO authenticated -- Only authenticated users
|
|
647
|
+
USING (...);
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
**Common roles**:
|
|
651
|
+
- `TO authenticated` - Logged-in users
|
|
652
|
+
- `TO anon` - Anonymous users
|
|
653
|
+
- `TO public` - Both authenticated and anon
|
|
654
|
+
|
|
655
|
+
## 🚀 Optimization 5: Use Security Definer Functions
|
|
656
|
+
|
|
657
|
+
**Bypass RLS on join tables** with security definer functions.
|
|
658
|
+
|
|
659
|
+
```sql
|
|
660
|
+
-- ❌ Policy with JOIN (slow, 99.99% slower)
|
|
661
|
+
CREATE POLICY "team_access" ON documents
|
|
662
|
+
USING (
|
|
663
|
+
team_id IN (
|
|
664
|
+
SELECT team_id FROM user_teams
|
|
665
|
+
WHERE user_id = (select auth.uid())
|
|
666
|
+
)
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
-- ✅ Security definer function (99.99% improvement)
|
|
670
|
+
CREATE OR REPLACE FUNCTION user_team_ids()
|
|
671
|
+
RETURNS TABLE(team_id UUID)
|
|
672
|
+
LANGUAGE sql
|
|
673
|
+
STABLE
|
|
674
|
+
SECURITY DEFINER
|
|
675
|
+
AS $$
|
|
676
|
+
SELECT team_id FROM user_teams
|
|
677
|
+
WHERE user_id = auth.uid();
|
|
678
|
+
$$;
|
|
679
|
+
|
|
680
|
+
CREATE POLICY "team_access" ON documents
|
|
681
|
+
USING (team_id IN (SELECT user_team_ids()));
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**Why**: Security definer functions run with elevated privileges, bypassing RLS on join tables.
|
|
685
|
+
|
|
686
|
+
## 🚀 Optimization 6: Minimize Joins
|
|
687
|
+
|
|
688
|
+
**Avoid joining source and target tables in policies.**
|
|
689
|
+
|
|
690
|
+
```sql
|
|
691
|
+
-- ❌ JOIN in policy (slow)
|
|
692
|
+
CREATE POLICY "org_access" ON documents
|
|
693
|
+
USING (
|
|
694
|
+
EXISTS (
|
|
695
|
+
SELECT 1 FROM users
|
|
696
|
+
WHERE users.id = (select auth.uid())
|
|
697
|
+
AND users.org_id = documents.org_id
|
|
698
|
+
)
|
|
699
|
+
);
|
|
700
|
+
|
|
701
|
+
-- ✅ Use JWT claims (no JOIN)
|
|
702
|
+
CREATE POLICY "org_access" ON documents
|
|
703
|
+
USING (
|
|
704
|
+
org_id = ((select auth.jwt()) ->> 'org_id')::uuid
|
|
705
|
+
);
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**Strategy**: Store necessary claims in JWT (org_id, role, tenant_id).
|
|
709
|
+
|
|
710
|
+
## Performance Checklist
|
|
711
|
+
|
|
712
|
+
Apply to every RLS policy:
|
|
713
|
+
|
|
714
|
+
- [ ] Wrap `auth.uid()` with `(select auth.uid())`
|
|
715
|
+
- [ ] Index all columns used in USING/WITH CHECK
|
|
716
|
+
- [ ] Specify role explicitly (TO authenticated vs TO public)
|
|
717
|
+
- [ ] Use JWT claims instead of JOINs where possible
|
|
718
|
+
- [ ] Create security definer functions for complex permission checks
|
|
719
|
+
- [ ] Test query plans with EXPLAIN ANALYZE
|
|
720
|
+
- [ ] Filter client-side explicitly
|
|
721
|
+
|
|
722
|
+
## Measuring Performance
|
|
723
|
+
|
|
724
|
+
```sql
|
|
725
|
+
-- Check query plan (look for Sequential Scan vs Index Scan)
|
|
726
|
+
EXPLAIN ANALYZE
|
|
727
|
+
SELECT * FROM users WHERE user_id = 'xxx';
|
|
728
|
+
|
|
729
|
+
-- Monitor slow queries
|
|
730
|
+
SELECT
|
|
731
|
+
query,
|
|
732
|
+
calls,
|
|
733
|
+
mean_exec_time,
|
|
734
|
+
max_exec_time
|
|
735
|
+
FROM pg_stat_statements
|
|
736
|
+
WHERE query LIKE '%users%'
|
|
737
|
+
ORDER BY mean_exec_time DESC
|
|
738
|
+
LIMIT 10;
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
## Real-World Impact
|
|
742
|
+
|
|
743
|
+
**Before optimization**:
|
|
744
|
+
- Query time: 250ms
|
|
745
|
+
- Database CPU: 80%
|
|
746
|
+
- Queries/sec: 40
|
|
747
|
+
|
|
748
|
+
**After optimization** (wrapped functions + indexes):
|
|
749
|
+
- Query time: 12ms (95% improvement)
|
|
750
|
+
- Database CPU: 15%
|
|
751
|
+
- Queries/sec: 800 (20x increase)
|
|
752
|
+
elicit: false
|
|
753
|
+
|
|
754
|
+
- id: advanced-patterns
|
|
755
|
+
title: "Advanced RLS Patterns"
|
|
756
|
+
instruction: |
|
|
757
|
+
Advanced RLS patterns beyond basic owner-only and tenant isolation.
|
|
758
|
+
|
|
759
|
+
## Pattern 6: Time-Based Access (Scheduled Content)
|
|
760
|
+
|
|
761
|
+
**Use case**: Blog posts with scheduled publishing, promotions with expiration, time-limited content.
|
|
762
|
+
|
|
763
|
+
```sql
|
|
764
|
+
CREATE POLICY "scheduled_content"
|
|
765
|
+
ON posts
|
|
766
|
+
FOR SELECT
|
|
767
|
+
TO authenticated
|
|
768
|
+
USING (
|
|
769
|
+
(publish_at IS NULL OR publish_at <= NOW()) AND
|
|
770
|
+
(expire_at IS NULL OR expire_at > NOW())
|
|
771
|
+
);
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
**How it works**:
|
|
775
|
+
- `publish_at IS NULL` - No schedule, always visible
|
|
776
|
+
- `publish_at <= NOW()` - Past publish date, visible
|
|
777
|
+
- `expire_at IS NULL` - No expiration, always visible
|
|
778
|
+
- `expire_at > NOW()` - Not expired, visible
|
|
779
|
+
|
|
780
|
+
**Performance**:
|
|
781
|
+
```sql
|
|
782
|
+
-- Index for time-based queries
|
|
783
|
+
CREATE INDEX idx_posts_scheduling
|
|
784
|
+
ON posts(publish_at, expire_at)
|
|
785
|
+
WHERE publish_at IS NOT NULL OR expire_at IS NOT NULL;
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
**Client-side filtering** (helps query planner):
|
|
789
|
+
```typescript
|
|
790
|
+
const { data } = await supabase
|
|
791
|
+
.from('posts')
|
|
792
|
+
.select('*')
|
|
793
|
+
.lte('publish_at', new Date().toISOString())
|
|
794
|
+
.or('publish_at.is.null')
|
|
795
|
+
.gte('expire_at', new Date().toISOString())
|
|
796
|
+
.or('expire_at.is.null');
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
## Pattern 7: Hierarchical Organizations (Detailed)
|
|
800
|
+
|
|
801
|
+
**Use case**: Org > Team > User hierarchy with different access levels.
|
|
802
|
+
|
|
803
|
+
### Simple Hierarchy (Org-Level):
|
|
804
|
+
```sql
|
|
805
|
+
CREATE POLICY "org_hierarchy"
|
|
806
|
+
ON resources
|
|
807
|
+
FOR SELECT
|
|
808
|
+
TO authenticated
|
|
809
|
+
USING (
|
|
810
|
+
org_id IN (
|
|
811
|
+
SELECT org_id
|
|
812
|
+
FROM user_org_memberships
|
|
813
|
+
WHERE user_id = (select auth.uid())
|
|
814
|
+
)
|
|
815
|
+
);
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
**User sees resources from ALL orgs they belong to.**
|
|
819
|
+
|
|
820
|
+
### Complex Hierarchy (Org + Team):
|
|
821
|
+
```sql
|
|
822
|
+
-- Option 1: User sees resources from their teams
|
|
823
|
+
CREATE POLICY "team_hierarchy"
|
|
824
|
+
ON resources
|
|
825
|
+
FOR SELECT
|
|
826
|
+
TO authenticated
|
|
827
|
+
USING (
|
|
828
|
+
team_id IN (
|
|
829
|
+
SELECT team_id
|
|
830
|
+
FROM user_team_memberships
|
|
831
|
+
WHERE user_id = (select auth.uid())
|
|
832
|
+
)
|
|
833
|
+
);
|
|
834
|
+
|
|
835
|
+
-- Option 2: Combined (org admin sees all, team member sees team only)
|
|
836
|
+
CREATE POLICY "combined_hierarchy"
|
|
837
|
+
ON resources
|
|
838
|
+
FOR SELECT
|
|
839
|
+
TO authenticated
|
|
840
|
+
USING (
|
|
841
|
+
-- Org admin sees all resources in org
|
|
842
|
+
(
|
|
843
|
+
org_id IN (
|
|
844
|
+
SELECT org_id
|
|
845
|
+
FROM user_org_memberships
|
|
846
|
+
WHERE user_id = (select auth.uid()) AND role = 'admin'
|
|
847
|
+
)
|
|
848
|
+
)
|
|
849
|
+
OR
|
|
850
|
+
-- Team member sees only team resources
|
|
851
|
+
(
|
|
852
|
+
team_id IN (
|
|
853
|
+
SELECT team_id
|
|
854
|
+
FROM user_team_memberships
|
|
855
|
+
WHERE user_id = (select auth.uid())
|
|
856
|
+
)
|
|
857
|
+
)
|
|
858
|
+
);
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
**Performance**:
|
|
862
|
+
```sql
|
|
863
|
+
-- Indexes for hierarchy lookups
|
|
864
|
+
CREATE INDEX idx_user_org_memberships_user
|
|
865
|
+
ON user_org_memberships(user_id, org_id);
|
|
866
|
+
|
|
867
|
+
CREATE INDEX idx_user_team_memberships_user
|
|
868
|
+
ON user_team_memberships(user_id, team_id);
|
|
869
|
+
|
|
870
|
+
CREATE INDEX idx_resources_org_id ON resources(org_id);
|
|
871
|
+
CREATE INDEX idx_resources_team_id ON resources(team_id);
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
**Optimization** (security definer function):
|
|
875
|
+
```sql
|
|
876
|
+
CREATE OR REPLACE FUNCTION user_accessible_orgs()
|
|
877
|
+
RETURNS TABLE(org_id UUID)
|
|
878
|
+
LANGUAGE sql
|
|
879
|
+
STABLE
|
|
880
|
+
SECURITY DEFINER
|
|
881
|
+
AS $$
|
|
882
|
+
SELECT org_id FROM user_org_memberships
|
|
883
|
+
WHERE user_id = auth.uid();
|
|
884
|
+
$$;
|
|
885
|
+
|
|
886
|
+
CREATE POLICY "org_hierarchy_optimized"
|
|
887
|
+
ON resources
|
|
888
|
+
FOR SELECT
|
|
889
|
+
TO authenticated
|
|
890
|
+
USING (org_id IN (SELECT user_accessible_orgs()));
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
## Pattern 8: Role-Based with Custom Claims (Advanced)
|
|
894
|
+
|
|
895
|
+
**Use case**: Different permissions per role (admin, manager, analyst, user).
|
|
896
|
+
|
|
897
|
+
### Setup: Add role to JWT
|
|
898
|
+
```sql
|
|
899
|
+
CREATE OR REPLACE FUNCTION custom_access_token_hook(event jsonb)
|
|
900
|
+
RETURNS jsonb AS $$
|
|
901
|
+
DECLARE
|
|
902
|
+
claims jsonb;
|
|
903
|
+
user_role text;
|
|
904
|
+
user_org_id uuid;
|
|
905
|
+
BEGIN
|
|
906
|
+
-- Get user role and org from profiles table
|
|
907
|
+
SELECT role, org_id INTO user_role, user_org_id
|
|
908
|
+
FROM public.user_profiles
|
|
909
|
+
WHERE user_id = (event->>'user_id')::uuid;
|
|
910
|
+
|
|
911
|
+
-- Add to JWT claims
|
|
912
|
+
claims := event->'claims';
|
|
913
|
+
claims := jsonb_set(claims, '{role}', to_jsonb(user_role));
|
|
914
|
+
claims := jsonb_set(claims, '{org_id}', to_jsonb(user_org_id));
|
|
915
|
+
|
|
916
|
+
RETURN jsonb_set(event, '{claims}', claims);
|
|
917
|
+
END;
|
|
918
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
**Configure in Supabase Dashboard**: Authentication > Hooks > Custom Access Token
|
|
922
|
+
|
|
923
|
+
### Policy: Role-Based Access
|
|
924
|
+
```sql
|
|
925
|
+
-- Admin sees all
|
|
926
|
+
CREATE POLICY "admin_full_access"
|
|
927
|
+
ON sensitive_data
|
|
928
|
+
FOR ALL
|
|
929
|
+
TO authenticated
|
|
930
|
+
USING (
|
|
931
|
+
((select auth.jwt()) ->> 'role') = 'admin'
|
|
932
|
+
);
|
|
933
|
+
|
|
934
|
+
-- Manager sees org data
|
|
935
|
+
CREATE POLICY "manager_org_access"
|
|
936
|
+
ON sensitive_data
|
|
937
|
+
FOR SELECT
|
|
938
|
+
TO authenticated
|
|
939
|
+
USING (
|
|
940
|
+
((select auth.jwt()) ->> 'role') = 'manager' AND
|
|
941
|
+
org_id = ((select auth.jwt()) ->> 'org_id')::uuid
|
|
942
|
+
);
|
|
943
|
+
|
|
944
|
+
-- User sees own data only
|
|
945
|
+
CREATE POLICY "user_own_access"
|
|
946
|
+
ON sensitive_data
|
|
947
|
+
FOR SELECT
|
|
948
|
+
TO authenticated
|
|
949
|
+
USING (
|
|
950
|
+
((select auth.jwt()) ->> 'role') = 'user' AND
|
|
951
|
+
user_id = (select auth.uid())
|
|
952
|
+
);
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
### Policy: Role Hierarchy (Admin > Manager > User)
|
|
956
|
+
```sql
|
|
957
|
+
CREATE POLICY "role_hierarchy"
|
|
958
|
+
ON resources
|
|
959
|
+
FOR ALL
|
|
960
|
+
TO authenticated
|
|
961
|
+
USING (
|
|
962
|
+
CASE ((select auth.jwt()) ->> 'role')
|
|
963
|
+
WHEN 'admin' THEN true -- Admin sees everything
|
|
964
|
+
WHEN 'manager' THEN org_id = ((select auth.jwt()) ->> 'org_id')::uuid
|
|
965
|
+
ELSE user_id = (select auth.uid()) -- User sees own only
|
|
966
|
+
END
|
|
967
|
+
);
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
## Pattern 9: Multi-Factor Authentication (AAL2)
|
|
971
|
+
|
|
972
|
+
**Use case**: Sensitive operations require MFA.
|
|
973
|
+
|
|
974
|
+
```sql
|
|
975
|
+
CREATE POLICY "mfa_required_for_sensitive_ops"
|
|
976
|
+
ON sensitive_operations
|
|
977
|
+
FOR INSERT
|
|
978
|
+
TO authenticated
|
|
979
|
+
USING (
|
|
980
|
+
((select auth.jwt()) ->> 'aal') = 'aal2' -- Assurance Level 2 (MFA)
|
|
981
|
+
);
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
**AAL levels**:
|
|
985
|
+
- `aal1` - Single factor (password only)
|
|
986
|
+
- `aal2` - Multi-factor (password + OTP/biometric)
|
|
987
|
+
|
|
988
|
+
## Pattern 10: IP-Based Restrictions
|
|
989
|
+
|
|
990
|
+
**Use case**: Restrict admin operations to office IP.
|
|
991
|
+
|
|
992
|
+
```sql
|
|
993
|
+
CREATE POLICY "admin_office_only"
|
|
994
|
+
ON admin_operations
|
|
995
|
+
FOR ALL
|
|
996
|
+
TO authenticated
|
|
997
|
+
USING (
|
|
998
|
+
((select auth.jwt()) ->> 'role') = 'admin' AND
|
|
999
|
+
inet_client_addr() << '192.168.1.0/24'::inet -- Office network
|
|
1000
|
+
);
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
**Note**: `inet_client_addr()` returns client IP.
|
|
1004
|
+
|
|
1005
|
+
## Advanced Patterns Summary
|
|
1006
|
+
|
|
1007
|
+
| Pattern | Use Case | Complexity | Performance Impact |
|
|
1008
|
+
|---------|----------|------------|-------------------|
|
|
1009
|
+
| Time-based | Scheduled content | Low | Low (with index) |
|
|
1010
|
+
| Hierarchical | Org > Team > User | Medium | Medium (needs indexes) |
|
|
1011
|
+
| Role-based claims | RBAC | Low | Low (JWT cached) |
|
|
1012
|
+
| AAL2 MFA | Sensitive ops | Low | None |
|
|
1013
|
+
| IP restrictions | Office-only | Low | None |
|
|
1014
|
+
|
|
1015
|
+
**Best practices**:
|
|
1016
|
+
- Prefer JWT claims over database lookups (faster)
|
|
1017
|
+
- Always index columns used in policies
|
|
1018
|
+
- Use security definer functions for complex checks
|
|
1019
|
+
- Test with EXPLAIN ANALYZE
|
|
1020
|
+
- Wrap auth functions with SELECT for caching
|
|
1021
|
+
elicit: false
|
|
1022
|
+
|
|
1023
|
+
- id: testing
|
|
1024
|
+
title: "RLS Testing Strategy"
|
|
1025
|
+
instruction: |
|
|
1026
|
+
How to test and validate RLS policies:
|
|
1027
|
+
|
|
1028
|
+
## Unit Tests
|
|
1029
|
+
|
|
1030
|
+
Test individual policies with different auth contexts:
|
|
1031
|
+
|
|
1032
|
+
```sql
|
|
1033
|
+
-- Test as user A
|
|
1034
|
+
SET request.jwt.claims = '{"sub": "user-a-uuid"}';
|
|
1035
|
+
SELECT * FROM table_name; -- Should only see user A's records
|
|
1036
|
+
|
|
1037
|
+
-- Test as user B
|
|
1038
|
+
SET request.jwt.claims = '{"sub": "user-b-uuid"}';
|
|
1039
|
+
SELECT * FROM table_name; -- Should only see user B's records
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
## Integration Tests
|
|
1043
|
+
|
|
1044
|
+
Test with actual Supabase client:
|
|
1045
|
+
|
|
1046
|
+
```typescript
|
|
1047
|
+
// Test authenticated access
|
|
1048
|
+
const { data, error } = await supabase
|
|
1049
|
+
.from('table_name')
|
|
1050
|
+
.select('*');
|
|
1051
|
+
|
|
1052
|
+
// Verify only authorized records returned
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
## Security Audit
|
|
1056
|
+
|
|
1057
|
+
Checklist for RLS validation:
|
|
1058
|
+
- [ ] All tables with sensitive data have RLS enabled
|
|
1059
|
+
- [ ] No accidental policy holes (test with unauthorized users)
|
|
1060
|
+
- [ ] Service role usage is documented and justified
|
|
1061
|
+
- [ ] Policies perform well (no slow queries)
|
|
1062
|
+
- [ ] Cross-tenant data leakage tested
|
|
1063
|
+
- [ ] Anonymous vs authenticated access verified
|
|
1064
|
+
- [ ] Edge cases tested (null values, missing context)
|
|
1065
|
+
|
|
1066
|
+
## Automated Testing
|
|
1067
|
+
|
|
1068
|
+
Script or framework for continuous validation.
|
|
1069
|
+
elicit: false
|
|
1070
|
+
|
|
1071
|
+
- id: migration
|
|
1072
|
+
title: "RLS Migration Scripts"
|
|
1073
|
+
instruction: |
|
|
1074
|
+
Concrete SQL migration for implementing these policies:
|
|
1075
|
+
|
|
1076
|
+
## Migration: `YYYYMMDDHHMMSS_add_rls_policies.sql`
|
|
1077
|
+
|
|
1078
|
+
```sql
|
|
1079
|
+
-- Enable RLS on tables
|
|
1080
|
+
ALTER TABLE table1 ENABLE ROW LEVEL SECURITY;
|
|
1081
|
+
ALTER TABLE table2 ENABLE ROW LEVEL SECURITY;
|
|
1082
|
+
|
|
1083
|
+
-- Drop existing policies if re-running
|
|
1084
|
+
DROP POLICY IF EXISTS "policy_name" ON table_name;
|
|
1085
|
+
|
|
1086
|
+
-- Create policies
|
|
1087
|
+
CREATE POLICY "policy_name_select"
|
|
1088
|
+
ON table_name
|
|
1089
|
+
FOR SELECT
|
|
1090
|
+
TO authenticated
|
|
1091
|
+
USING (auth.uid() = user_id);
|
|
1092
|
+
|
|
1093
|
+
CREATE POLICY "policy_name_insert"
|
|
1094
|
+
ON table_name
|
|
1095
|
+
FOR INSERT
|
|
1096
|
+
TO authenticated
|
|
1097
|
+
WITH CHECK (auth.uid() = user_id);
|
|
1098
|
+
|
|
1099
|
+
-- ... additional policies ...
|
|
1100
|
+
|
|
1101
|
+
-- Create indexes to support policies
|
|
1102
|
+
CREATE INDEX IF NOT EXISTS idx_table_user_id
|
|
1103
|
+
ON table_name(user_id);
|
|
1104
|
+
|
|
1105
|
+
-- Grant permissions
|
|
1106
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON table_name TO authenticated;
|
|
1107
|
+
GRANT SELECT ON table_name TO anon;
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
## Rollback Migration
|
|
1111
|
+
|
|
1112
|
+
```sql
|
|
1113
|
+
-- Remove policies
|
|
1114
|
+
DROP POLICY IF EXISTS "policy_name_select" ON table_name;
|
|
1115
|
+
DROP POLICY IF EXISTS "policy_name_insert" ON table_name;
|
|
1116
|
+
|
|
1117
|
+
-- Disable RLS
|
|
1118
|
+
ALTER TABLE table_name DISABLE ROW LEVEL SECURITY;
|
|
1119
|
+
```
|
|
1120
|
+
elicit: false
|
|
1121
|
+
|
|
1122
|
+
- id: monitoring
|
|
1123
|
+
title: "RLS Monitoring & Debugging"
|
|
1124
|
+
instruction: |
|
|
1125
|
+
How to monitor and debug RLS policies:
|
|
1126
|
+
|
|
1127
|
+
## Query Performance
|
|
1128
|
+
|
|
1129
|
+
Identify slow queries caused by RLS:
|
|
1130
|
+
|
|
1131
|
+
```sql
|
|
1132
|
+
-- Check query plans
|
|
1133
|
+
EXPLAIN ANALYZE
|
|
1134
|
+
SELECT * FROM table_name;
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
## Policy Effectiveness
|
|
1138
|
+
|
|
1139
|
+
Verify policies are being applied:
|
|
1140
|
+
|
|
1141
|
+
```sql
|
|
1142
|
+
-- Check active policies
|
|
1143
|
+
SELECT schemaname, tablename, policyname, permissive, roles, cmd, qual
|
|
1144
|
+
FROM pg_policies
|
|
1145
|
+
WHERE tablename = 'your_table';
|
|
1146
|
+
```
|
|
1147
|
+
|
|
1148
|
+
## Common Issues
|
|
1149
|
+
|
|
1150
|
+
### Issue: Policy not applying
|
|
1151
|
+
- Check RLS is enabled on table
|
|
1152
|
+
- Verify user role matches policy target
|
|
1153
|
+
- Check auth context is set correctly
|
|
1154
|
+
|
|
1155
|
+
### Issue: Performance degradation
|
|
1156
|
+
- Add indexes for policy columns
|
|
1157
|
+
- Simplify policy expressions
|
|
1158
|
+
- Consider denormalization
|
|
1159
|
+
|
|
1160
|
+
### Issue: Unexpected access
|
|
1161
|
+
- Audit all policies on table
|
|
1162
|
+
- Check for permissive vs restrictive policies
|
|
1163
|
+
- Verify no service role leakage
|
|
1164
|
+
|
|
1165
|
+
## Logging
|
|
1166
|
+
|
|
1167
|
+
Log policy violations or unexpected access patterns.
|
|
1168
|
+
elicit: false
|
|
1169
|
+
|
|
1170
|
+
- id: best-practices
|
|
1171
|
+
title: "RLS Best Practices"
|
|
1172
|
+
instruction: |
|
|
1173
|
+
## Design Principles
|
|
1174
|
+
|
|
1175
|
+
1. **Start Restrictive**: Default deny, explicitly allow
|
|
1176
|
+
2. **Minimize Policy Complexity**: Simpler policies are easier to audit
|
|
1177
|
+
3. **Use Helper Functions**: Encapsulate complex logic
|
|
1178
|
+
4. **Index Policy Columns**: Performance is critical
|
|
1179
|
+
5. **Test Extensively**: Security bugs are costly
|
|
1180
|
+
6. **Document Everything**: Future you will thank you
|
|
1181
|
+
7. **Audit Regularly**: Policies drift over time
|
|
1182
|
+
8. **Avoid Service Role**: Use it only when absolutely necessary
|
|
1183
|
+
|
|
1184
|
+
## Common Pitfalls
|
|
1185
|
+
|
|
1186
|
+
- Forgetting to enable RLS on new tables
|
|
1187
|
+
- Policy expressions with poor performance
|
|
1188
|
+
- Not testing with actual user contexts
|
|
1189
|
+
- Overly permissive catch-all policies
|
|
1190
|
+
- Mixing USING and WITH CHECK incorrectly
|
|
1191
|
+
- Not considering null values in policies
|
|
1192
|
+
|
|
1193
|
+
## Security Checklist
|
|
1194
|
+
|
|
1195
|
+
- [ ] All sensitive tables have RLS enabled
|
|
1196
|
+
- [ ] Policies tested with unauthorized users
|
|
1197
|
+
- [ ] Anonymous access limited to public data only
|
|
1198
|
+
- [ ] Service role usage is minimal and documented
|
|
1199
|
+
- [ ] Policies use indexes for performance
|
|
1200
|
+
- [ ] Multi-tenant isolation is verified
|
|
1201
|
+
- [ ] Edge cases tested (nulls, empty results)
|
|
1202
|
+
- [ ] Policies are documented and reviewed
|
|
1203
|
+
elicit: false
|