cfsa-antigravity 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,658 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: postgresql
|
|
3
|
+
description: "Expert PostgreSQL guide covering schema design, index strategies, query optimization, connection pooling, migrations, row-level security, JSONB, and full-text search. Use when designing database schemas, writing complex queries, optimizing performance, or integrating PostgreSQL with TypeScript applications."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# PostgreSQL Expert
|
|
8
|
+
|
|
9
|
+
## 1. Schema Design Patterns
|
|
10
|
+
|
|
11
|
+
### Normalization vs Denormalization
|
|
12
|
+
|
|
13
|
+
**Normalize** when data integrity matters more than read speed. **Denormalize** when read performance is critical and you control write paths.
|
|
14
|
+
|
|
15
|
+
```sql
|
|
16
|
+
-- Normalized: data integrity, no duplication, slower reads with joins
|
|
17
|
+
CREATE TABLE users (
|
|
18
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
19
|
+
email text UNIQUE NOT NULL,
|
|
20
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE TABLE orders (
|
|
24
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
25
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
26
|
+
total numeric(12,2) NOT NULL CHECK (total >= 0),
|
|
27
|
+
status text NOT NULL DEFAULT 'pending'
|
|
28
|
+
CHECK (status IN ('pending','confirmed','shipped','delivered','cancelled')),
|
|
29
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
CREATE TABLE order_items (
|
|
33
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
34
|
+
order_id uuid NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
|
35
|
+
product_id uuid NOT NULL REFERENCES products(id),
|
|
36
|
+
quantity int NOT NULL CHECK (quantity > 0),
|
|
37
|
+
unit_price numeric(12,2) NOT NULL CHECK (unit_price >= 0)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
-- Denormalized: faster reads, requires maintaining consistency on writes
|
|
41
|
+
CREATE TABLE order_summaries (
|
|
42
|
+
order_id uuid PRIMARY KEY REFERENCES orders(id),
|
|
43
|
+
user_email text NOT NULL, -- duplicated from users
|
|
44
|
+
item_count int NOT NULL DEFAULT 0, -- computed from order_items
|
|
45
|
+
total numeric(12,2) NOT NULL, -- duplicated from orders
|
|
46
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
47
|
+
);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Decision guide**: Use normalized tables as your source of truth. Create materialized views or denormalized read tables only when you have measured query latency problems with joins.
|
|
51
|
+
|
|
52
|
+
### Enum Types vs Check Constraints
|
|
53
|
+
|
|
54
|
+
```sql
|
|
55
|
+
-- Enum type: compile-time safety, harder to migrate (requires ALTER TYPE)
|
|
56
|
+
CREATE TYPE order_status AS ENUM ('pending','confirmed','shipped','delivered','cancelled');
|
|
57
|
+
ALTER TABLE orders ALTER COLUMN status TYPE order_status USING status::order_status;
|
|
58
|
+
|
|
59
|
+
-- Check constraint: easier to modify, no type dependency
|
|
60
|
+
ALTER TABLE orders ADD CONSTRAINT valid_status
|
|
61
|
+
CHECK (status IN ('pending','confirmed','shipped','delivered','cancelled'));
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Prefer check constraints** for values that change over time. **Use enums** for truly stable domain values.
|
|
65
|
+
|
|
66
|
+
### Partitioning
|
|
67
|
+
|
|
68
|
+
```sql
|
|
69
|
+
-- Range partitioning for time-series data
|
|
70
|
+
CREATE TABLE events (
|
|
71
|
+
id uuid NOT NULL DEFAULT gen_random_uuid(),
|
|
72
|
+
event_type text NOT NULL,
|
|
73
|
+
payload jsonb NOT NULL DEFAULT '{}',
|
|
74
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
75
|
+
) PARTITION BY RANGE (created_at);
|
|
76
|
+
|
|
77
|
+
CREATE TABLE events_2025_q1 PARTITION OF events
|
|
78
|
+
FOR VALUES FROM ('2025-01-01') TO ('2025-04-01');
|
|
79
|
+
CREATE TABLE events_2025_q2 PARTITION OF events
|
|
80
|
+
FOR VALUES FROM ('2025-04-01') TO ('2025-07-01');
|
|
81
|
+
|
|
82
|
+
-- Partition pruning happens automatically when queries filter on created_at
|
|
83
|
+
SELECT * FROM events WHERE created_at >= '2025-02-01' AND created_at < '2025-03-01';
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 2. Index Types and Strategy
|
|
89
|
+
|
|
90
|
+
### B-tree (Default)
|
|
91
|
+
|
|
92
|
+
Best for equality and range queries. Used for `=`, `<`, `>`, `<=`, `>=`, `BETWEEN`, `IN`, `IS NULL`, `ORDER BY`.
|
|
93
|
+
|
|
94
|
+
```sql
|
|
95
|
+
CREATE INDEX idx_users_email ON users (email);
|
|
96
|
+
CREATE UNIQUE INDEX idx_users_email_unique ON users (lower(email));
|
|
97
|
+
CREATE INDEX idx_orders_user_created ON orders (user_id, created_at DESC);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### GIN (Generalized Inverted Index)
|
|
101
|
+
|
|
102
|
+
Best for composite values: arrays, JSONB, full-text search.
|
|
103
|
+
|
|
104
|
+
```sql
|
|
105
|
+
-- JSONB containment queries
|
|
106
|
+
CREATE INDEX idx_products_attrs ON products USING GIN (attributes);
|
|
107
|
+
-- Enables: SELECT * FROM products WHERE attributes @> '{"color": "red"}';
|
|
108
|
+
|
|
109
|
+
-- Array contains
|
|
110
|
+
CREATE INDEX idx_posts_tags ON posts USING GIN (tags);
|
|
111
|
+
-- Enables: SELECT * FROM posts WHERE tags @> ARRAY['postgresql'];
|
|
112
|
+
|
|
113
|
+
-- Full-text search
|
|
114
|
+
CREATE INDEX idx_articles_search ON articles USING GIN (to_tsvector('english', title || ' ' || body));
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### GiST (Generalized Search Tree)
|
|
118
|
+
|
|
119
|
+
Best for geometric data, ranges, and nearest-neighbor searches.
|
|
120
|
+
|
|
121
|
+
```sql
|
|
122
|
+
-- Range overlap queries
|
|
123
|
+
CREATE INDEX idx_bookings_during ON bookings USING GIST (tstzrange(start_at, end_at));
|
|
124
|
+
-- Enables: SELECT * FROM bookings WHERE tstzrange(start_at, end_at) && tstzrange('2025-03-01', '2025-03-08');
|
|
125
|
+
|
|
126
|
+
-- PostGIS geographic queries
|
|
127
|
+
CREATE INDEX idx_locations_geo ON locations USING GIST (coordinates);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### BRIN (Block Range Index)
|
|
131
|
+
|
|
132
|
+
Best for physically ordered data (time-series, append-only tables). Tiny index size.
|
|
133
|
+
|
|
134
|
+
```sql
|
|
135
|
+
-- Perfect for append-only time-series where rows are inserted in order
|
|
136
|
+
CREATE INDEX idx_events_created ON events USING BRIN (created_at);
|
|
137
|
+
-- 1000x smaller than B-tree on large tables, nearly as fast for range scans
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Partial Indexes
|
|
141
|
+
|
|
142
|
+
Index only the rows you query. Saves space, improves write performance.
|
|
143
|
+
|
|
144
|
+
```sql
|
|
145
|
+
-- Only index active users (90% of queries filter on active = true)
|
|
146
|
+
CREATE INDEX idx_active_users ON users (email) WHERE active = true;
|
|
147
|
+
|
|
148
|
+
-- Only index pending orders
|
|
149
|
+
CREATE INDEX idx_pending_orders ON orders (created_at) WHERE status = 'pending';
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Index Anti-Patterns
|
|
153
|
+
|
|
154
|
+
```sql
|
|
155
|
+
-- BAD: Indexing low-cardinality boolean columns alone
|
|
156
|
+
CREATE INDEX idx_users_active ON users (active); -- Only 2 values, rarely selective
|
|
157
|
+
|
|
158
|
+
-- BAD: Too many indexes on write-heavy tables
|
|
159
|
+
-- Each INSERT/UPDATE/DELETE must update every index
|
|
160
|
+
|
|
161
|
+
-- BAD: Redundant indexes
|
|
162
|
+
CREATE INDEX idx_a ON orders (user_id);
|
|
163
|
+
CREATE INDEX idx_b ON orders (user_id, created_at); -- idx_a is redundant, idx_b covers it
|
|
164
|
+
|
|
165
|
+
-- BAD: Indexing expressions differently than queried
|
|
166
|
+
CREATE INDEX idx_email ON users (email);
|
|
167
|
+
SELECT * FROM users WHERE lower(email) = 'test@example.com'; -- Index NOT used
|
|
168
|
+
-- FIX:
|
|
169
|
+
CREATE INDEX idx_email_lower ON users (lower(email));
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## 3. Query Optimization
|
|
175
|
+
|
|
176
|
+
### EXPLAIN ANALYZE
|
|
177
|
+
|
|
178
|
+
Always check actual execution, not just the plan.
|
|
179
|
+
|
|
180
|
+
```sql
|
|
181
|
+
-- Show actual timing and row counts
|
|
182
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
|
|
183
|
+
SELECT u.email, count(o.id) as order_count
|
|
184
|
+
FROM users u
|
|
185
|
+
JOIN orders o ON o.user_id = u.id
|
|
186
|
+
WHERE u.created_at > '2025-01-01'
|
|
187
|
+
GROUP BY u.email
|
|
188
|
+
ORDER BY order_count DESC
|
|
189
|
+
LIMIT 10;
|
|
190
|
+
|
|
191
|
+
-- Key things to look for in output:
|
|
192
|
+
-- 1. Seq Scan on large tables (missing index?)
|
|
193
|
+
-- 2. Nested Loop with high row estimates (consider Hash Join)
|
|
194
|
+
-- 3. actual rows >> estimated rows (stale statistics, run ANALYZE)
|
|
195
|
+
-- 4. Buffers: shared hit vs read (cache effectiveness)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### CTEs (Common Table Expressions)
|
|
199
|
+
|
|
200
|
+
```sql
|
|
201
|
+
-- CTE for readability (PostgreSQL 12+ may inline non-recursive CTEs)
|
|
202
|
+
WITH active_users AS (
|
|
203
|
+
SELECT id, email FROM users WHERE active = true
|
|
204
|
+
),
|
|
205
|
+
recent_orders AS (
|
|
206
|
+
SELECT user_id, count(*) as cnt, sum(total) as revenue
|
|
207
|
+
FROM orders
|
|
208
|
+
WHERE created_at > now() - interval '30 days'
|
|
209
|
+
GROUP BY user_id
|
|
210
|
+
)
|
|
211
|
+
SELECT au.email, ro.cnt, ro.revenue
|
|
212
|
+
FROM active_users au
|
|
213
|
+
JOIN recent_orders ro ON ro.user_id = au.id
|
|
214
|
+
ORDER BY ro.revenue DESC;
|
|
215
|
+
|
|
216
|
+
-- MATERIALIZED CTE: force separate execution (optimization fence)
|
|
217
|
+
WITH active_users AS MATERIALIZED (
|
|
218
|
+
SELECT id FROM users WHERE active = true
|
|
219
|
+
)
|
|
220
|
+
SELECT * FROM orders WHERE user_id IN (SELECT id FROM active_users);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Window Functions
|
|
224
|
+
|
|
225
|
+
```sql
|
|
226
|
+
-- Rank users by order count within their region
|
|
227
|
+
SELECT
|
|
228
|
+
email,
|
|
229
|
+
region,
|
|
230
|
+
order_count,
|
|
231
|
+
RANK() OVER (PARTITION BY region ORDER BY order_count DESC) as region_rank,
|
|
232
|
+
ROW_NUMBER() OVER (ORDER BY order_count DESC) as global_rank
|
|
233
|
+
FROM user_stats;
|
|
234
|
+
|
|
235
|
+
-- Running total
|
|
236
|
+
SELECT
|
|
237
|
+
date,
|
|
238
|
+
revenue,
|
|
239
|
+
SUM(revenue) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as running_total
|
|
240
|
+
FROM daily_revenue;
|
|
241
|
+
|
|
242
|
+
-- Moving average (7-day)
|
|
243
|
+
SELECT
|
|
244
|
+
date,
|
|
245
|
+
revenue,
|
|
246
|
+
AVG(revenue) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) as avg_7day
|
|
247
|
+
FROM daily_revenue;
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Pagination
|
|
251
|
+
|
|
252
|
+
```sql
|
|
253
|
+
-- BAD: OFFSET-based (gets slower as offset grows)
|
|
254
|
+
SELECT * FROM products ORDER BY created_at DESC LIMIT 20 OFFSET 10000;
|
|
255
|
+
|
|
256
|
+
-- GOOD: Cursor-based (constant performance)
|
|
257
|
+
SELECT * FROM products
|
|
258
|
+
WHERE created_at < $last_seen_created_at
|
|
259
|
+
ORDER BY created_at DESC
|
|
260
|
+
LIMIT 20;
|
|
261
|
+
|
|
262
|
+
-- For stable ordering with duplicates, use a tiebreaker
|
|
263
|
+
SELECT * FROM products
|
|
264
|
+
WHERE (created_at, id) < ($last_created_at, $last_id)
|
|
265
|
+
ORDER BY created_at DESC, id DESC
|
|
266
|
+
LIMIT 20;
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 4. Connection Pooling
|
|
272
|
+
|
|
273
|
+
### PgBouncer Patterns
|
|
274
|
+
|
|
275
|
+
```ini
|
|
276
|
+
; pgbouncer.ini
|
|
277
|
+
[databases]
|
|
278
|
+
myapp = host=127.0.0.1 port=5432 dbname=myapp
|
|
279
|
+
|
|
280
|
+
[pgbouncer]
|
|
281
|
+
listen_addr = 127.0.0.1
|
|
282
|
+
listen_port = 6432
|
|
283
|
+
auth_type = scram-sha-256
|
|
284
|
+
auth_file = /etc/pgbouncer/userlist.txt
|
|
285
|
+
|
|
286
|
+
; Transaction pooling: best for web apps
|
|
287
|
+
pool_mode = transaction
|
|
288
|
+
max_client_conn = 1000
|
|
289
|
+
default_pool_size = 20
|
|
290
|
+
min_pool_size = 5
|
|
291
|
+
reserve_pool_size = 5
|
|
292
|
+
reserve_pool_timeout = 3
|
|
293
|
+
|
|
294
|
+
; Connection limits
|
|
295
|
+
server_idle_timeout = 300
|
|
296
|
+
server_lifetime = 3600
|
|
297
|
+
client_idle_timeout = 0
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Pool modes**:
|
|
301
|
+
- `session`: one server connection per client session (safest, least efficient)
|
|
302
|
+
- `transaction`: connection returned to pool after each transaction (best for web apps)
|
|
303
|
+
- `statement`: connection returned after each statement (cannot use transactions)
|
|
304
|
+
|
|
305
|
+
**Transaction pooling caveats** -- these features require session-level state and break under transaction pooling:
|
|
306
|
+
- `SET` commands (use `SET LOCAL` inside transactions instead)
|
|
307
|
+
- `LISTEN/NOTIFY`
|
|
308
|
+
- Prepared statements (use `DEALLOCATE ALL` or disable with `server_reset_query`)
|
|
309
|
+
- Advisory locks
|
|
310
|
+
- Temporary tables
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 5. Zero-Downtime Migrations
|
|
315
|
+
|
|
316
|
+
### Safe Operations
|
|
317
|
+
|
|
318
|
+
```sql
|
|
319
|
+
-- SAFE: Add nullable column (no table rewrite, instant)
|
|
320
|
+
ALTER TABLE users ADD COLUMN phone text;
|
|
321
|
+
|
|
322
|
+
-- SAFE: Add column with a non-volatile default (PG 11+, instant)
|
|
323
|
+
ALTER TABLE users ADD COLUMN active boolean NOT NULL DEFAULT true;
|
|
324
|
+
|
|
325
|
+
-- SAFE: Create index concurrently (no write locks)
|
|
326
|
+
CREATE INDEX CONCURRENTLY idx_users_phone ON users (phone);
|
|
327
|
+
|
|
328
|
+
-- SAFE: Add constraint as NOT VALID, then validate separately
|
|
329
|
+
ALTER TABLE orders ADD CONSTRAINT positive_total CHECK (total >= 0) NOT VALID;
|
|
330
|
+
ALTER TABLE orders VALIDATE CONSTRAINT positive_total; -- scans table but allows writes
|
|
331
|
+
|
|
332
|
+
-- SAFE: Create enum value
|
|
333
|
+
ALTER TYPE order_status ADD VALUE 'refunded';
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Dangerous Operations (Require Lock Planning)
|
|
337
|
+
|
|
338
|
+
```sql
|
|
339
|
+
-- DANGEROUS: Adding NOT NULL constraint on existing column (full table scan with lock)
|
|
340
|
+
-- Instead, do this in steps:
|
|
341
|
+
-- Step 1: Add check constraint NOT VALID
|
|
342
|
+
ALTER TABLE users ADD CONSTRAINT users_email_not_null CHECK (email IS NOT NULL) NOT VALID;
|
|
343
|
+
-- Step 2: Validate (allows concurrent writes)
|
|
344
|
+
ALTER TABLE users VALIDATE CONSTRAINT users_email_not_null;
|
|
345
|
+
-- Step 3: Add NOT NULL using the existing constraint (instant in PG 12+)
|
|
346
|
+
ALTER TABLE users ALTER COLUMN email SET NOT NULL;
|
|
347
|
+
-- Step 4: Drop the now-redundant check constraint
|
|
348
|
+
ALTER TABLE users DROP CONSTRAINT users_email_not_null;
|
|
349
|
+
|
|
350
|
+
-- DANGEROUS: Renaming columns (breaks running application code)
|
|
351
|
+
-- Instead: add new column, backfill, deploy code using both, drop old column
|
|
352
|
+
|
|
353
|
+
-- DANGEROUS: Changing column type (may rewrite table)
|
|
354
|
+
-- Safe exceptions: varchar(N) to varchar(M) where M > N, varchar to text
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Migration File Pattern
|
|
358
|
+
|
|
359
|
+
```sql
|
|
360
|
+
-- migrations/20250216_001_add_user_preferences.sql
|
|
361
|
+
BEGIN;
|
|
362
|
+
|
|
363
|
+
-- Add the column (instant, no lock)
|
|
364
|
+
ALTER TABLE users ADD COLUMN preferences jsonb NOT NULL DEFAULT '{}';
|
|
365
|
+
|
|
366
|
+
-- Create index for querying preferences (no lock)
|
|
367
|
+
CREATE INDEX CONCURRENTLY idx_users_preferences ON users USING GIN (preferences);
|
|
368
|
+
|
|
369
|
+
COMMIT;
|
|
370
|
+
|
|
371
|
+
-- Note: CREATE INDEX CONCURRENTLY cannot run inside a transaction.
|
|
372
|
+
-- Run it separately after the ALTER TABLE commits.
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 6. Row-Level Security (RLS)
|
|
378
|
+
|
|
379
|
+
```sql
|
|
380
|
+
-- Enable RLS on the table
|
|
381
|
+
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
|
|
382
|
+
|
|
383
|
+
-- Force RLS even for table owners (important for testing)
|
|
384
|
+
ALTER TABLE documents FORCE ROW LEVEL SECURITY;
|
|
385
|
+
|
|
386
|
+
-- Users can only see their own documents
|
|
387
|
+
CREATE POLICY select_own ON documents
|
|
388
|
+
FOR SELECT
|
|
389
|
+
USING (owner_id = current_setting('app.current_user_id')::uuid);
|
|
390
|
+
|
|
391
|
+
-- Users can only insert documents they own
|
|
392
|
+
CREATE POLICY insert_own ON documents
|
|
393
|
+
FOR INSERT
|
|
394
|
+
WITH CHECK (owner_id = current_setting('app.current_user_id')::uuid);
|
|
395
|
+
|
|
396
|
+
-- Users can update only their own documents
|
|
397
|
+
CREATE POLICY update_own ON documents
|
|
398
|
+
FOR UPDATE
|
|
399
|
+
USING (owner_id = current_setting('app.current_user_id')::uuid)
|
|
400
|
+
WITH CHECK (owner_id = current_setting('app.current_user_id')::uuid);
|
|
401
|
+
|
|
402
|
+
-- Admins can see everything
|
|
403
|
+
CREATE POLICY admin_all ON documents
|
|
404
|
+
FOR ALL
|
|
405
|
+
USING (current_setting('app.current_role') = 'admin');
|
|
406
|
+
|
|
407
|
+
-- Setting the user context per request (in your application):
|
|
408
|
+
-- SET LOCAL only lasts for the current transaction
|
|
409
|
+
BEGIN;
|
|
410
|
+
SET LOCAL app.current_user_id = 'a1b2c3d4-...';
|
|
411
|
+
SET LOCAL app.current_role = 'user';
|
|
412
|
+
SELECT * FROM documents; -- RLS filters automatically
|
|
413
|
+
COMMIT;
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## 7. JSONB Operations
|
|
419
|
+
|
|
420
|
+
```sql
|
|
421
|
+
-- Store structured data
|
|
422
|
+
CREATE TABLE products (
|
|
423
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
424
|
+
name text NOT NULL,
|
|
425
|
+
attributes jsonb NOT NULL DEFAULT '{}'
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
-- Index for containment queries
|
|
429
|
+
CREATE INDEX idx_products_attrs ON products USING GIN (attributes);
|
|
430
|
+
|
|
431
|
+
-- Query patterns
|
|
432
|
+
SELECT * FROM products WHERE attributes @> '{"color": "red"}'; -- containment
|
|
433
|
+
SELECT * FROM products WHERE attributes ? 'warranty'; -- key exists
|
|
434
|
+
SELECT * FROM products WHERE attributes ->> 'brand' = 'Acme'; -- text extraction
|
|
435
|
+
SELECT * FROM products WHERE (attributes -> 'specs' ->> 'weight')::numeric < 2.0;
|
|
436
|
+
|
|
437
|
+
-- Update nested values
|
|
438
|
+
UPDATE products
|
|
439
|
+
SET attributes = jsonb_set(attributes, '{specs,weight}', '1.5')
|
|
440
|
+
WHERE id = $1;
|
|
441
|
+
|
|
442
|
+
-- Aggregate JSONB
|
|
443
|
+
SELECT jsonb_agg(jsonb_build_object('id', id, 'name', name)) FROM products;
|
|
444
|
+
|
|
445
|
+
-- Expand JSONB to rows
|
|
446
|
+
SELECT p.name, kv.key, kv.value
|
|
447
|
+
FROM products p, jsonb_each_text(p.attributes) kv;
|
|
448
|
+
|
|
449
|
+
-- JSONB path queries (PG 12+)
|
|
450
|
+
SELECT * FROM products WHERE attributes @? '$.specs.weight ? (@ < 2)';
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**When to use JSONB vs columns**: Use JSONB for truly dynamic/variable schemas (user preferences, plugin data, API payloads). Use columns for data you query, join, or constrain regularly.
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## 8. Full-Text Search
|
|
458
|
+
|
|
459
|
+
```sql
|
|
460
|
+
-- Add tsvector column with auto-update trigger
|
|
461
|
+
ALTER TABLE articles ADD COLUMN search_vector tsvector
|
|
462
|
+
GENERATED ALWAYS AS (
|
|
463
|
+
setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
|
|
464
|
+
setweight(to_tsvector('english', coalesce(body, '')), 'B')
|
|
465
|
+
) STORED;
|
|
466
|
+
|
|
467
|
+
CREATE INDEX idx_articles_search ON articles USING GIN (search_vector);
|
|
468
|
+
|
|
469
|
+
-- Search with ranking
|
|
470
|
+
SELECT
|
|
471
|
+
id, title,
|
|
472
|
+
ts_rank(search_vector, query) AS rank
|
|
473
|
+
FROM articles, plainto_tsquery('english', 'database optimization') query
|
|
474
|
+
WHERE search_vector @@ query
|
|
475
|
+
ORDER BY rank DESC
|
|
476
|
+
LIMIT 20;
|
|
477
|
+
|
|
478
|
+
-- Phrase search
|
|
479
|
+
SELECT * FROM articles
|
|
480
|
+
WHERE search_vector @@ phraseto_tsquery('english', 'connection pooling');
|
|
481
|
+
|
|
482
|
+
-- Highlight matching terms
|
|
483
|
+
SELECT
|
|
484
|
+
ts_headline('english', body, plainto_tsquery('english', 'optimization'),
|
|
485
|
+
'StartSel=<mark>, StopSel=</mark>, MaxWords=50, MinWords=20') as snippet
|
|
486
|
+
FROM articles
|
|
487
|
+
WHERE search_vector @@ plainto_tsquery('english', 'optimization');
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## 9. Common Anti-Patterns
|
|
493
|
+
|
|
494
|
+
### N+1 Queries
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
// BAD: N+1 -- one query per user to get their orders
|
|
498
|
+
const users = await db.query('SELECT * FROM users LIMIT 100');
|
|
499
|
+
for (const user of users.rows) {
|
|
500
|
+
const orders = await db.query('SELECT * FROM orders WHERE user_id = $1', [user.id]);
|
|
501
|
+
// ...
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// GOOD: single query with join
|
|
505
|
+
const result = await db.query(`
|
|
506
|
+
SELECT u.id, u.email, json_agg(o.*) as orders
|
|
507
|
+
FROM users u
|
|
508
|
+
LEFT JOIN orders o ON o.user_id = u.id
|
|
509
|
+
GROUP BY u.id, u.email
|
|
510
|
+
LIMIT 100
|
|
511
|
+
`);
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### Missing Indexes on Foreign Keys
|
|
515
|
+
|
|
516
|
+
```sql
|
|
517
|
+
-- Foreign keys do NOT automatically create indexes in PostgreSQL
|
|
518
|
+
-- Joins and ON DELETE CASCADE scans will be slow without them
|
|
519
|
+
ALTER TABLE orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id);
|
|
520
|
+
CREATE INDEX idx_orders_user_id ON orders (user_id); -- Add this explicitly
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Over-Indexing
|
|
524
|
+
|
|
525
|
+
Every index slows down writes and consumes disk. Audit unused indexes:
|
|
526
|
+
|
|
527
|
+
```sql
|
|
528
|
+
SELECT schemaname, relname, indexrelname, idx_scan
|
|
529
|
+
FROM pg_stat_user_indexes
|
|
530
|
+
WHERE idx_scan = 0 AND indexrelname NOT LIKE '%_pkey'
|
|
531
|
+
ORDER BY pg_relation_size(indexrelid) DESC;
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Unbounded Queries
|
|
535
|
+
|
|
536
|
+
```sql
|
|
537
|
+
-- BAD: no limit
|
|
538
|
+
SELECT * FROM logs;
|
|
539
|
+
|
|
540
|
+
-- GOOD: always paginate
|
|
541
|
+
SELECT * FROM logs ORDER BY created_at DESC LIMIT 50;
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## 10. TypeScript Integration
|
|
547
|
+
|
|
548
|
+
### With postgres.js (Recommended)
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
import postgres from 'postgres';
|
|
552
|
+
|
|
553
|
+
const sql = postgres({
|
|
554
|
+
host: process.env.DATABASE_HOST,
|
|
555
|
+
port: 5432,
|
|
556
|
+
database: process.env.DATABASE_NAME,
|
|
557
|
+
username: process.env.DATABASE_USER,
|
|
558
|
+
password: process.env.DATABASE_PASSWORD,
|
|
559
|
+
max: 20, // connection pool size
|
|
560
|
+
idle_timeout: 20, // seconds before closing idle connections
|
|
561
|
+
max_lifetime: 60 * 30, // max connection lifetime in seconds
|
|
562
|
+
transform: postgres.camel, // snake_case columns -> camelCase JS
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Parameterized queries (safe from injection)
|
|
566
|
+
const users = await sql`
|
|
567
|
+
SELECT id, email, created_at
|
|
568
|
+
FROM users
|
|
569
|
+
WHERE active = ${true}
|
|
570
|
+
ORDER BY created_at DESC
|
|
571
|
+
LIMIT ${20}
|
|
572
|
+
`;
|
|
573
|
+
|
|
574
|
+
// Transactions
|
|
575
|
+
await sql.begin(async (tx) => {
|
|
576
|
+
const [order] = await tx`
|
|
577
|
+
INSERT INTO orders (user_id, total, status)
|
|
578
|
+
VALUES (${userId}, ${total}, 'pending')
|
|
579
|
+
RETURNING *
|
|
580
|
+
`;
|
|
581
|
+
await tx`
|
|
582
|
+
INSERT INTO order_items ${sql(items.map(i => ({
|
|
583
|
+
order_id: order.id,
|
|
584
|
+
product_id: i.productId,
|
|
585
|
+
quantity: i.quantity,
|
|
586
|
+
unit_price: i.unitPrice,
|
|
587
|
+
})))}
|
|
588
|
+
`;
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// Dynamic columns with sql()
|
|
592
|
+
const columns = ['email', 'name'];
|
|
593
|
+
const result = await sql`SELECT ${sql(columns)} FROM users WHERE id = ${id}`;
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### Type Generation with pgtyped or Kysely
|
|
597
|
+
|
|
598
|
+
```typescript
|
|
599
|
+
// With Kysely: type-safe query builder
|
|
600
|
+
import { Kysely, PostgresDialect } from 'kysely';
|
|
601
|
+
import { Pool } from 'pg';
|
|
602
|
+
|
|
603
|
+
interface Database {
|
|
604
|
+
users: {
|
|
605
|
+
id: string;
|
|
606
|
+
email: string;
|
|
607
|
+
active: boolean;
|
|
608
|
+
created_at: Date;
|
|
609
|
+
};
|
|
610
|
+
orders: {
|
|
611
|
+
id: string;
|
|
612
|
+
user_id: string;
|
|
613
|
+
total: number;
|
|
614
|
+
status: 'pending' | 'confirmed' | 'shipped' | 'delivered' | 'cancelled';
|
|
615
|
+
created_at: Date;
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const db = new Kysely<Database>({
|
|
620
|
+
dialect: new PostgresDialect({ pool: new Pool({ connectionString: process.env.DATABASE_URL }) }),
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// Fully typed queries
|
|
624
|
+
const users = await db
|
|
625
|
+
.selectFrom('users')
|
|
626
|
+
.select(['id', 'email'])
|
|
627
|
+
.where('active', '=', true)
|
|
628
|
+
.orderBy('created_at', 'desc')
|
|
629
|
+
.limit(20)
|
|
630
|
+
.execute();
|
|
631
|
+
// users is typed as { id: string; email: string }[]
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## 11. Critical Reminders
|
|
637
|
+
|
|
638
|
+
### ALWAYS
|
|
639
|
+
|
|
640
|
+
- Use parameterized queries -- never interpolate user input into SQL strings
|
|
641
|
+
- Create indexes on foreign key columns
|
|
642
|
+
- Use `CREATE INDEX CONCURRENTLY` in production
|
|
643
|
+
- Set `statement_timeout` to prevent runaway queries
|
|
644
|
+
- Use `BEGIN; SET LOCAL ...; ... COMMIT;` for RLS context
|
|
645
|
+
- Monitor slow queries via `pg_stat_statements`
|
|
646
|
+
- Run `ANALYZE` after bulk data loads
|
|
647
|
+
- Use `LIMIT` on all user-facing queries
|
|
648
|
+
|
|
649
|
+
### NEVER
|
|
650
|
+
|
|
651
|
+
- Interpolate user input into SQL: `` `SELECT * FROM users WHERE id = '${id}'` ``
|
|
652
|
+
- Use `OFFSET` for deep pagination (use cursor-based instead)
|
|
653
|
+
- Add `NOT NULL` to existing columns without the multi-step constraint pattern
|
|
654
|
+
- Create indexes without `CONCURRENTLY` on production tables with traffic
|
|
655
|
+
- Forget to index foreign key columns
|
|
656
|
+
- Use `SELECT *` in application code (select only needed columns)
|
|
657
|
+
- Store passwords in plaintext (use `pgcrypto` or hash in application layer)
|
|
658
|
+
- Run migrations without testing on a copy of production data first
|