@evertonferreira96/agents 0.0.0-stage → 0.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/.claude/agents/api.md +45 -0
- package/.claude/agents/app.md +41 -0
- package/.claude/agents/architect.md +49 -0
- package/.claude/agents/infra.md +27 -0
- package/.claude/agents/product.md +58 -0
- package/.claude/agents/quick.md +33 -0
- package/.claude/agents/security.md +39 -0
- package/.claude/agents/ui.md +54 -0
- package/.claude/agents/verifier.md +56 -0
- package/.claude/agents/web.md +41 -0
- package/.claude/hooks/config-update-check.mjs +14 -0
- package/.claude/hooks/context-budget.mjs +51 -0
- package/.claude/hooks/graphify-update.sh +16 -0
- package/.claude/hooks/guard-bash.sh +64 -0
- package/.claude/hooks/orchestrator-guard.sh +49 -0
- package/.claude/hooks/post-compact.sh +26 -0
- package/.claude/hooks/readonly-guard.sh +54 -0
- package/.claude/hooks/stop-verify.sh +52 -0
- package/.claude/rules/api.md +21 -0
- package/.claude/rules/db.md +9 -0
- package/.claude/rules/delivery-diagram.md +16 -0
- package/.claude/rules/git-workflow.md +34 -0
- package/.claude/rules/graphify.md +3 -0
- package/.claude/rules/mobile.md +22 -0
- package/.claude/rules/tickets.md +9 -0
- package/.claude/rules/ui.md +14 -0
- package/.claude/rules/web.md +27 -0
- package/.claude/settings.json +114 -0
- package/.claude/skills/animate/RECIPES.md +324 -0
- package/.claude/skills/animate/SKILL.md +208 -0
- package/.claude/skills/animate/agents/openai.yaml +5 -0
- package/.claude/skills/animate-expo/RECIPES.md +385 -0
- package/.claude/skills/animate-expo/SKILL.md +264 -0
- package/.claude/skills/animate-expo/agents/openai.yaml +5 -0
- package/.claude/skills/animation-performance/SKILL.md +223 -0
- package/.claude/skills/animation-performance/agents/openai.yaml +5 -0
- package/.claude/skills/apple-design/SKILL.md +291 -0
- package/.claude/skills/apple-design/agents/openai.yaml +5 -0
- package/.claude/skills/arch-api/SKILL.md +291 -0
- package/.claude/skills/arch-api/agents/openai.yaml +3 -0
- package/.claude/skills/arch-api/references/common.md +174 -0
- package/.claude/skills/arch-api/references/contract.md +289 -0
- package/.claude/skills/arch-api/references/domain.md +301 -0
- package/.claude/skills/arch-api/references/endpoints.md +184 -0
- package/.claude/skills/arch-api/references/review.md +228 -0
- package/.claude/skills/arch-api/references/security.md +151 -0
- package/.claude/skills/arch-app/SKILL.md +278 -0
- package/.claude/skills/arch-app/agents/openai.yaml +3 -0
- package/.claude/skills/arch-app/references/navigation-session.md +257 -0
- package/.claude/skills/arch-app/references/review.md +155 -0
- package/.claude/skills/arch-app/references/screens.md +214 -0
- package/.claude/skills/arch-app/references/services.md +301 -0
- package/.claude/skills/arch-app/references/ui-mobile.md +124 -0
- package/.claude/skills/arch-db/SKILL.md +181 -0
- package/.claude/skills/arch-db/agents/openai.yaml +3 -0
- package/.claude/skills/arch-db/references/indexes-queries.md +251 -0
- package/.claude/skills/arch-db/references/migrations.md +191 -0
- package/.claude/skills/arch-db/references/modeling.md +214 -0
- package/.claude/skills/arch-db/references/mysql.md +262 -0
- package/.claude/skills/arch-db/references/pooling-ops.md +112 -0
- package/.claude/skills/arch-db/references/review.md +143 -0
- package/.claude/skills/arch-db/references/transactions-locks.md +141 -0
- package/.claude/skills/arch-web/SKILL.md +307 -0
- package/.claude/skills/arch-web/agents/openai.yaml +3 -0
- package/.claude/skills/arch-web/references/auth-session-env.md +165 -0
- package/.claude/skills/arch-web/references/blocks.md +198 -0
- package/.claude/skills/arch-web/references/cache.md +124 -0
- package/.claude/skills/arch-web/references/review.md +142 -0
- package/.claude/skills/arch-web/references/services.md +297 -0
- package/.claude/skills/arch-web/references/tests.md +159 -0
- package/.claude/skills/arch-web/references/ui-forms.md +143 -0
- package/.claude/skills/break-ui/CATALOG.md +135 -0
- package/.claude/skills/break-ui/SKILL.md +176 -0
- package/.claude/skills/break-ui/agents/openai.yaml +5 -0
- package/.claude/skills/brief/SKILL.md +91 -0
- package/.claude/skills/brief/agents/openai.yaml +3 -0
- package/.claude/skills/diagnosing-bugs/SKILL.md +138 -0
- package/.claude/skills/diagnosing-bugs/agents/openai.yaml +3 -0
- package/.claude/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
- package/.claude/skills/emil-design-eng/SKILL.md +675 -0
- package/.claude/skills/emil-design-eng/agents/openai.yaml +5 -0
- package/.claude/skills/find-animation-opportunities/SKILL.md +141 -0
- package/.claude/skills/find-animation-opportunities/agents/openai.yaml +5 -0
- package/.claude/skills/graphify/.graphify_version +1 -0
- package/.claude/skills/graphify/SKILL.md +742 -0
- package/.claude/skills/graphify/agents/openai.yaml +3 -0
- package/.claude/skills/graphify/references/add-watch.md +56 -0
- package/.claude/skills/graphify/references/exports.md +91 -0
- package/.claude/skills/graphify/references/extraction-spec.md +70 -0
- package/.claude/skills/graphify/references/github-and-merge.md +46 -0
- package/.claude/skills/graphify/references/hooks.md +33 -0
- package/.claude/skills/graphify/references/query.md +317 -0
- package/.claude/skills/graphify/references/transcribe.md +52 -0
- package/.claude/skills/graphify/references/update.md +221 -0
- package/.claude/skills/grill-me/SKILL.md +7 -0
- package/.claude/skills/grill-me/agents/openai.yaml +5 -0
- package/.claude/skills/grill-with-docs/SKILL.md +64 -0
- package/.claude/skills/grill-with-docs/agents/openai.yaml +5 -0
- package/.claude/skills/grilling/SKILL.md +30 -0
- package/.claude/skills/grilling/agents/openai.yaml +3 -0
- package/.claude/skills/handoff/SKILL.md +28 -0
- package/.claude/skills/handoff/agents/openai.yaml +5 -0
- package/.claude/skills/impeccable/SKILL.md +89 -0
- package/.claude/skills/impeccable/agents/openai.yaml +5 -0
- package/.claude/skills/impeccable/reference/adapt.md +318 -0
- package/.claude/skills/impeccable/reference/adapt.native.md +58 -0
- package/.claude/skills/impeccable/reference/android.md +46 -0
- package/.claude/skills/impeccable/reference/animate.md +89 -0
- package/.claude/skills/impeccable/reference/audit.md +137 -0
- package/.claude/skills/impeccable/reference/audit.native.md +139 -0
- package/.claude/skills/impeccable/reference/bolder.md +33 -0
- package/.claude/skills/impeccable/reference/clarify.md +94 -0
- package/.claude/skills/impeccable/reference/colorize.md +86 -0
- package/.claude/skills/impeccable/reference/component-review.md +63 -0
- package/.claude/skills/impeccable/reference/craft-floor.md +44 -0
- package/.claude/skills/impeccable/reference/craft.md +5 -0
- package/.claude/skills/impeccable/reference/critique.md +809 -0
- package/.claude/skills/impeccable/reference/degraded/asset-producer.md +42 -0
- package/.claude/skills/impeccable/reference/degraded/documenter.md +24 -0
- package/.claude/skills/impeccable/reference/degraded/finish-reviewer.md +38 -0
- package/.claude/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/.claude/skills/impeccable/reference/delight.md +70 -0
- package/.claude/skills/impeccable/reference/distill.md +111 -0
- package/.claude/skills/impeccable/reference/doctor.md +54 -0
- package/.claude/skills/impeccable/reference/document.md +416 -0
- package/.claude/skills/impeccable/reference/extract.md +69 -0
- package/.claude/skills/impeccable/reference/generate.md +101 -0
- package/.claude/skills/impeccable/reference/harden.md +345 -0
- package/.claude/skills/impeccable/reference/hooks.md +113 -0
- package/.claude/skills/impeccable/reference/init.md +131 -0
- package/.claude/skills/impeccable/reference/ios.md +51 -0
- package/.claude/skills/impeccable/reference/layout.md +84 -0
- package/.claude/skills/impeccable/reference/live-setup.md +104 -0
- package/.claude/skills/impeccable/reference/live.md +325 -0
- package/.claude/skills/impeccable/reference/mode-operate.md +21 -0
- package/.claude/skills/impeccable/reference/mode-persuade.md +19 -0
- package/.claude/skills/impeccable/reference/mode-read.md +21 -0
- package/.claude/skills/impeccable/reference/new-work.md +154 -0
- package/.claude/skills/impeccable/reference/onboard.md +234 -0
- package/.claude/skills/impeccable/reference/operate.md +61 -0
- package/.claude/skills/impeccable/reference/optimize.md +258 -0
- package/.claude/skills/impeccable/reference/overdrive.md +127 -0
- package/.claude/skills/impeccable/reference/polish.md +105 -0
- package/.claude/skills/impeccable/reference/quieter.md +99 -0
- package/.claude/skills/impeccable/reference/region-map.md +26 -0
- package/.claude/skills/impeccable/reference/routing.md +24 -0
- package/.claude/skills/impeccable/reference/shape.md +59 -0
- package/.claude/skills/impeccable/reference/typeset.md +80 -0
- package/.claude/skills/impeccable/reference/visualize.md +47 -0
- package/.claude/skills/impeccable/scripts/VERSION +1 -0
- package/.claude/skills/impeccable/scripts/command-metadata.json +98 -0
- package/.claude/skills/impeccable/scripts/data/font-index-failures.json +121 -0
- package/.claude/skills/impeccable/scripts/data/font-index.json +1 -0
- package/.claude/skills/impeccable/scripts/impeccable +206 -0
- package/.claude/skills/impeccable/scripts/impeccable.cmd +214 -0
- package/.claude/skills/impeccable/scripts/live-browser-dom.js +281 -0
- package/.claude/skills/impeccable/scripts/live-browser-ignores.js +242 -0
- package/.claude/skills/impeccable/scripts/live-browser-session.js +148 -0
- package/.claude/skills/impeccable/scripts/live-browser.js +13532 -0
- package/.claude/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/.claude/skills/improve-animations/AUDIT.md +115 -0
- package/.claude/skills/improve-animations/PLAN-TEMPLATE.md +73 -0
- package/.claude/skills/improve-animations/SKILL.md +110 -0
- package/.claude/skills/improve-animations/agents/openai.yaml +5 -0
- package/.claude/skills/mobile-native/SKILL.md +311 -0
- package/.claude/skills/mobile-native/agents/openai.yaml +3 -0
- package/.claude/skills/orchestrate/SKILL.md +181 -0
- package/.claude/skills/orchestrate/agents/openai.yaml +3 -0
- package/.claude/skills/pick-ui-library/SKILL.md +85 -0
- package/.claude/skills/pick-ui-library/agents/openai.yaml +5 -0
- package/.claude/skills/ponytail/SKILL.md +52 -0
- package/.claude/skills/ponytail/agents/openai.yaml +3 -0
- package/.claude/skills/ponytail-audit/SKILL.md +103 -0
- package/.claude/skills/ponytail-audit/agents/openai.yaml +3 -0
- package/.claude/skills/ponytail-debt/SKILL.md +44 -0
- package/.claude/skills/ponytail-debt/agents/openai.yaml +3 -0
- package/.claude/skills/ponytail-review/SKILL.md +101 -0
- package/.claude/skills/ponytail-review/agents/openai.yaml +3 -0
- package/.claude/skills/postgres-best-practices/SKILL.md +42 -0
- package/.claude/skills/postgres-best-practices/agents/openai.yaml +3 -0
- package/.claude/skills/postgres-best-practices/references/backup-restore.md +372 -0
- package/.claude/skills/postgres-best-practices/references/bulk-loading.md +315 -0
- package/.claude/skills/postgres-best-practices/references/connection-pooling.md +310 -0
- package/.claude/skills/postgres-best-practices/references/hot-standby.md +221 -0
- package/.claude/skills/postgres-best-practices/references/indexing.md +318 -0
- package/.claude/skills/postgres-best-practices/references/logical-replication.md +610 -0
- package/.claude/skills/postgres-best-practices/references/major-version-upgrades.md +334 -0
- package/.claude/skills/postgres-best-practices/references/performance-diagnostics.md +553 -0
- package/.claude/skills/postgres-best-practices/references/query-optimization.md +294 -0
- package/.claude/skills/postgres-best-practices/references/query-patterns.md +566 -0
- package/.claude/skills/postgres-best-practices/references/schema-design.md +362 -0
- package/.claude/skills/postgres-best-practices/references/security-roles.md +489 -0
- package/.claude/skills/postgres-best-practices/references/transaction-isolation.md +344 -0
- package/.claude/skills/project-docs/SKILL.md +330 -0
- package/.claude/skills/project-docs/agents/openai.yaml +3 -0
- package/.claude/skills/prototype/PICKER.md +197 -0
- package/.claude/skills/prototype/SKILL.md +98 -0
- package/.claude/skills/prototype/agents/openai.yaml +5 -0
- package/.claude/skills/retro/SKILL.md +43 -0
- package/.claude/skills/retro/agents/openai.yaml +5 -0
- package/.claude/skills/review/SKILL.md +74 -0
- package/.claude/skills/review/agents/openai.yaml +3 -0
- package/.claude/skills/review/references/smells.md +23 -0
- package/.claude/skills/review-animations/SKILL.md +120 -0
- package/.claude/skills/review-animations/STANDARDS.md +187 -0
- package/.claude/skills/review-animations/agents/openai.yaml +5 -0
- package/.claude/skills/tdd/SKILL.md +38 -0
- package/.claude/skills/tdd/agents/openai.yaml +3 -0
- package/.claude/skills/tdd/mocking.md +59 -0
- package/.claude/skills/tdd/tests.md +77 -0
- package/.claude/skills/triage/SKILL.md +58 -0
- package/.claude/skills/triage/agents/openai.yaml +3 -0
- package/.claude/skills/ui-ux-pro-max/SKILL.md +378 -0
- package/.claude/skills/ui-ux-pro-max/agents/openai.yaml +5 -0
- package/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.claude/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.claude/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.claude/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.claude/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.claude/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.claude/skills/ui-ux-pro-max/scripts/core.py +253 -0
- package/.claude/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.claude/skills/ui-ux-pro-max/scripts/search.py +114 -0
- package/.claude/skills/writing-for-agents/SKILL-MECHANICS.md +22 -0
- package/.claude/skills/writing-for-agents/SKILL.md +81 -0
- package/.claude/skills/writing-for-agents/agents/openai.yaml +3 -0
- package/.worktreeinclude +3 -0
- package/AGENTS.md +44 -0
- package/README.md +14 -2
- package/VERSION +1 -0
- package/bin/agents.mjs +45 -0
- package/docs/adr/README.md +31 -0
- package/docs/brief-template.md +3 -0
- package/docs/plans/README.md +73 -0
- package/package.json +46 -4
- package/scripts/bootstrap.mjs +188 -0
- package/scripts/check-catalog.mjs +43 -0
- package/scripts/skills-update.mjs +51 -0
- package/skills-lock.json +269 -0
- package/templates/CLAUDE.project.md +41 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
# Security & Roles Reference
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
- Role management
|
|
5
|
+
- Privilege system
|
|
6
|
+
- Schema-based access control
|
|
7
|
+
- Row-Level Security (RLS)
|
|
8
|
+
- pg_hba.conf authentication
|
|
9
|
+
- Password policies and authentication methods
|
|
10
|
+
- Security functions and best practices
|
|
11
|
+
|
|
12
|
+
## Role Management
|
|
13
|
+
|
|
14
|
+
PostgreSQL uses **roles** for both users and groups. A role with `LOGIN` is a user; a role without is a group.
|
|
15
|
+
|
|
16
|
+
### Creating Roles
|
|
17
|
+
|
|
18
|
+
```sql
|
|
19
|
+
-- User role (can log in)
|
|
20
|
+
CREATE ROLE app_user WITH LOGIN PASSWORD 'strong_password_here';
|
|
21
|
+
|
|
22
|
+
-- Group role (cannot log in, used for privilege grouping)
|
|
23
|
+
CREATE ROLE readonly;
|
|
24
|
+
CREATE ROLE readwrite;
|
|
25
|
+
CREATE ROLE admin;
|
|
26
|
+
|
|
27
|
+
-- Role with specific attributes
|
|
28
|
+
CREATE ROLE backup_user WITH LOGIN REPLICATION PASSWORD '...';
|
|
29
|
+
CREATE ROLE migrator WITH LOGIN CREATEDB PASSWORD '...';
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Role Attributes
|
|
33
|
+
|
|
34
|
+
| Attribute | Meaning |
|
|
35
|
+
|-----------|---------|
|
|
36
|
+
| `LOGIN` | Can connect to the database |
|
|
37
|
+
| `SUPERUSER` | Bypasses all permission checks (dangerous) |
|
|
38
|
+
| `CREATEDB` | Can create databases |
|
|
39
|
+
| `CREATEROLE` | Can create/alter/drop other roles |
|
|
40
|
+
| `REPLICATION` | Can initiate streaming replication |
|
|
41
|
+
| `BYPASSRLS` | Bypasses Row-Level Security policies |
|
|
42
|
+
| `INHERIT` | Automatically inherits privileges of member roles (default) |
|
|
43
|
+
| `CONNECTION LIMIT n` | Max concurrent connections for this role |
|
|
44
|
+
| `VALID UNTIL 'timestamp'` | Password expiration |
|
|
45
|
+
|
|
46
|
+
```sql
|
|
47
|
+
-- Modify attributes
|
|
48
|
+
ALTER ROLE app_user WITH CONNECTION LIMIT 10;
|
|
49
|
+
ALTER ROLE temp_user VALID UNTIL '2025-01-01';
|
|
50
|
+
ALTER ROLE app_user WITH PASSWORD 'new_password';
|
|
51
|
+
|
|
52
|
+
-- Inspect roles
|
|
53
|
+
SELECT rolname, rolsuper, rolcreatedb, rolcreaterole, rolcanlogin,
|
|
54
|
+
rolreplication, rolbypassrls, rolconnlimit, rolvaliduntil
|
|
55
|
+
FROM pg_roles
|
|
56
|
+
WHERE rolname NOT LIKE 'pg_%'
|
|
57
|
+
ORDER BY rolname;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Group Membership
|
|
61
|
+
|
|
62
|
+
```sql
|
|
63
|
+
-- Add a user to a group
|
|
64
|
+
GRANT readonly TO app_user;
|
|
65
|
+
GRANT readwrite TO app_user;
|
|
66
|
+
|
|
67
|
+
-- Remove membership
|
|
68
|
+
REVOKE readwrite FROM app_user;
|
|
69
|
+
|
|
70
|
+
-- Check memberships
|
|
71
|
+
SELECT
|
|
72
|
+
r.rolname AS role,
|
|
73
|
+
m.rolname AS member
|
|
74
|
+
FROM pg_auth_members am
|
|
75
|
+
JOIN pg_roles r ON r.oid = am.roleid
|
|
76
|
+
JOIN pg_roles m ON m.oid = am.member
|
|
77
|
+
ORDER BY r.rolname, m.rolname;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Predefined Roles
|
|
81
|
+
|
|
82
|
+
PostgreSQL provides system-defined roles for common privileged capabilities. PostgreSQL 13 and earlier documentation called these "default roles"; PostgreSQL 14 renamed the category to "predefined roles." Individual roles were introduced in different releases.
|
|
83
|
+
|
|
84
|
+
| Role | Grants |
|
|
85
|
+
|------|--------|
|
|
86
|
+
| `pg_read_all_data` | SELECT on all tables, views, sequences in all schemas |
|
|
87
|
+
| `pg_write_all_data` | INSERT, UPDATE, DELETE on all tables, sequences in all schemas |
|
|
88
|
+
| `pg_read_all_settings` | Read all GUC settings (even superuser-only) |
|
|
89
|
+
| `pg_read_all_stats` | Read all pg_stat_* views |
|
|
90
|
+
| `pg_monitor` | Read monitoring views (`pg_stat_*`, `pg_locks`, etc.) |
|
|
91
|
+
| `pg_signal_backend` | Send signals to other backends (cancel/terminate) |
|
|
92
|
+
| `pg_checkpoint` (PG15+) | Run CHECKPOINT |
|
|
93
|
+
| `pg_maintain` (PG17+) | Run VACUUM, ANALYZE, REINDEX, CLUSTER, REFRESH MATERIALIZED VIEW, and LOCK TABLE on all relations |
|
|
94
|
+
|
|
95
|
+
```sql
|
|
96
|
+
-- Give a monitoring role read access to all stats
|
|
97
|
+
GRANT pg_monitor TO monitoring_user;
|
|
98
|
+
|
|
99
|
+
-- Give an app role read access to all data without per-table grants
|
|
100
|
+
GRANT pg_read_all_data TO reporting_user;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Privilege System
|
|
104
|
+
|
|
105
|
+
### Object Privileges
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
-- Grant on tables
|
|
109
|
+
GRANT SELECT ON orders TO readonly;
|
|
110
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON orders TO readwrite;
|
|
111
|
+
GRANT ALL PRIVILEGES ON orders TO admin;
|
|
112
|
+
|
|
113
|
+
-- Grant on all tables in a schema
|
|
114
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
|
|
115
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO readwrite;
|
|
116
|
+
|
|
117
|
+
-- Grant on sequences (needed for INSERT with serial/identity columns)
|
|
118
|
+
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO readwrite;
|
|
119
|
+
|
|
120
|
+
-- Grant on schema (required to access objects within it)
|
|
121
|
+
GRANT USAGE ON SCHEMA public TO readonly;
|
|
122
|
+
GRANT USAGE, CREATE ON SCHEMA public TO readwrite;
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Default Privileges
|
|
126
|
+
|
|
127
|
+
Set privileges that automatically apply to future objects:
|
|
128
|
+
|
|
129
|
+
```sql
|
|
130
|
+
-- As the object owner or superuser:
|
|
131
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
132
|
+
GRANT SELECT ON TABLES TO readonly;
|
|
133
|
+
|
|
134
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
135
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO readwrite;
|
|
136
|
+
|
|
137
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
138
|
+
GRANT USAGE ON SEQUENCES TO readwrite;
|
|
139
|
+
|
|
140
|
+
-- For objects created by a specific role:
|
|
141
|
+
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public
|
|
142
|
+
GRANT SELECT ON TABLES TO readonly;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Important**: Default privileges only affect objects created **after** the `ALTER DEFAULT PRIVILEGES` command. Existing objects need explicit `GRANT`.
|
|
146
|
+
|
|
147
|
+
### Revoking Privileges
|
|
148
|
+
|
|
149
|
+
```sql
|
|
150
|
+
-- Revoke specific privileges
|
|
151
|
+
REVOKE INSERT, UPDATE, DELETE ON orders FROM readonly;
|
|
152
|
+
|
|
153
|
+
-- Revoke all privileges
|
|
154
|
+
REVOKE ALL PRIVILEGES ON orders FROM some_role;
|
|
155
|
+
|
|
156
|
+
-- Revoke from public (default grant on new databases)
|
|
157
|
+
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
|
158
|
+
REVOKE ALL ON DATABASE mydb FROM PUBLIC;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Inspecting Privileges
|
|
162
|
+
|
|
163
|
+
```sql
|
|
164
|
+
-- Table privileges
|
|
165
|
+
SELECT
|
|
166
|
+
grantee,
|
|
167
|
+
table_schema,
|
|
168
|
+
table_name,
|
|
169
|
+
privilege_type
|
|
170
|
+
FROM information_schema.table_privileges
|
|
171
|
+
WHERE table_schema = 'public'
|
|
172
|
+
ORDER BY table_name, grantee;
|
|
173
|
+
|
|
174
|
+
-- Compact: privileges per table
|
|
175
|
+
SELECT
|
|
176
|
+
relname,
|
|
177
|
+
relacl -- array of 'grantee=privileges/grantor'
|
|
178
|
+
FROM pg_class
|
|
179
|
+
WHERE relkind = 'r' AND relnamespace = 'public'::regnamespace;
|
|
180
|
+
|
|
181
|
+
-- Function privileges
|
|
182
|
+
SELECT
|
|
183
|
+
routine_name,
|
|
184
|
+
grantee,
|
|
185
|
+
privilege_type
|
|
186
|
+
FROM information_schema.routine_privileges
|
|
187
|
+
WHERE routine_schema = 'public';
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Schema-Based Access Control
|
|
191
|
+
|
|
192
|
+
Use schemas to organize objects and control access:
|
|
193
|
+
|
|
194
|
+
```sql
|
|
195
|
+
-- Create isolated schemas
|
|
196
|
+
CREATE SCHEMA app;
|
|
197
|
+
CREATE SCHEMA reporting;
|
|
198
|
+
CREATE SCHEMA staging;
|
|
199
|
+
|
|
200
|
+
-- Grant access per schema
|
|
201
|
+
GRANT USAGE ON SCHEMA app TO app_user;
|
|
202
|
+
GRANT USAGE ON SCHEMA reporting TO reporting_user;
|
|
203
|
+
GRANT USAGE ON SCHEMA staging TO etl_user;
|
|
204
|
+
|
|
205
|
+
-- Remove default public schema access
|
|
206
|
+
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Search Path Security
|
|
210
|
+
|
|
211
|
+
The `search_path` determines which schemas are searched for unqualified table names. A malicious `search_path` can redirect queries to attacker-controlled tables.
|
|
212
|
+
|
|
213
|
+
```sql
|
|
214
|
+
-- Set a safe search path (explicit, no reliance on public)
|
|
215
|
+
ALTER ROLE app_user SET search_path = app, public;
|
|
216
|
+
|
|
217
|
+
-- For functions: use SECURITY DEFINER carefully
|
|
218
|
+
CREATE FUNCTION get_balance(account_id int) RETURNS numeric
|
|
219
|
+
SECURITY DEFINER
|
|
220
|
+
SET search_path = pg_catalog, pg_temp
|
|
221
|
+
AS $$
|
|
222
|
+
SELECT balance FROM app.accounts WHERE id = account_id;
|
|
223
|
+
$$ LANGUAGE sql;
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Always give `SECURITY DEFINER` functions a fixed `search_path` containing only trusted schemas.** Explicitly list `pg_temp` last: if it is omitted, PostgreSQL searches the session's temporary schema first for relations and data types, which can allow temporary objects to shadow intended objects. When application objects are fully qualified, prefer `pg_catalog, pg_temp`; otherwise list only trusted application schemas followed by `pg_temp`.
|
|
227
|
+
|
|
228
|
+
## Row-Level Security (RLS)
|
|
229
|
+
|
|
230
|
+
RLS adds per-row access control enforced by the database, not the application.
|
|
231
|
+
|
|
232
|
+
### Basic Setup
|
|
233
|
+
|
|
234
|
+
```sql
|
|
235
|
+
-- Enable RLS on a table
|
|
236
|
+
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
|
|
237
|
+
|
|
238
|
+
-- Policy for tenant isolation
|
|
239
|
+
CREATE POLICY tenant_isolation ON orders
|
|
240
|
+
USING (tenant_id = current_setting('app.current_tenant')::int);
|
|
241
|
+
|
|
242
|
+
-- Test through a non-owner application role; table owners bypass RLS by default.
|
|
243
|
+
SET ROLE app_user;
|
|
244
|
+
SET app.current_tenant = '42';
|
|
245
|
+
|
|
246
|
+
-- All queries on orders now automatically filter by tenant_id = 42
|
|
247
|
+
SELECT * FROM orders; -- only sees tenant 42's orders
|
|
248
|
+
RESET ROLE;
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Policy Types
|
|
252
|
+
|
|
253
|
+
```sql
|
|
254
|
+
-- SELECT policy (restrict which rows can be read)
|
|
255
|
+
CREATE POLICY read_own ON documents
|
|
256
|
+
FOR SELECT
|
|
257
|
+
USING (owner_id = current_setting('app.current_user_id')::bigint);
|
|
258
|
+
|
|
259
|
+
-- INSERT policy (restrict which rows can be inserted)
|
|
260
|
+
CREATE POLICY insert_own ON documents
|
|
261
|
+
FOR INSERT
|
|
262
|
+
WITH CHECK (owner_id = current_setting('app.current_user_id')::bigint);
|
|
263
|
+
|
|
264
|
+
-- UPDATE policy (restrict which rows can be updated, and what values are allowed)
|
|
265
|
+
CREATE POLICY update_own ON documents
|
|
266
|
+
FOR UPDATE
|
|
267
|
+
USING (owner_id = current_setting('app.current_user_id')::bigint) -- rows selectable for update
|
|
268
|
+
WITH CHECK (owner_id = current_setting('app.current_user_id')::bigint); -- required post-update value
|
|
269
|
+
|
|
270
|
+
-- DELETE policy
|
|
271
|
+
CREATE POLICY delete_own ON documents
|
|
272
|
+
FOR DELETE
|
|
273
|
+
USING (owner_id = current_setting('app.current_user_id')::bigint);
|
|
274
|
+
|
|
275
|
+
-- ALL (applies to all commands)
|
|
276
|
+
CREATE POLICY full_access ON documents
|
|
277
|
+
FOR ALL
|
|
278
|
+
USING (owner_id = current_setting('app.current_user_id')::bigint)
|
|
279
|
+
WITH CHECK (owner_id = current_setting('app.current_user_id')::bigint);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Multiple Policies
|
|
283
|
+
|
|
284
|
+
Multiple policies on the same table are combined with OR (by default). Use `RESTRICTIVE` for AND:
|
|
285
|
+
|
|
286
|
+
```sql
|
|
287
|
+
-- Permissive (default): combined with OR
|
|
288
|
+
CREATE POLICY see_active ON orders
|
|
289
|
+
USING (status = 'active');
|
|
290
|
+
|
|
291
|
+
CREATE POLICY see_own ON orders
|
|
292
|
+
USING (user_id = current_setting('app.current_user_id')::bigint);
|
|
293
|
+
-- User sees rows that are active OR owned by them
|
|
294
|
+
|
|
295
|
+
-- Restrictive: combined with AND (with permissive policies)
|
|
296
|
+
CREATE POLICY must_be_active ON orders AS RESTRICTIVE
|
|
297
|
+
USING (status != 'deleted');
|
|
298
|
+
-- Combined: (active OR own) AND not_deleted
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### RLS Caveats
|
|
302
|
+
|
|
303
|
+
- **Table owner bypasses RLS** by default. Use `ALTER TABLE ... FORCE ROW LEVEL SECURITY` to apply RLS to the owner too.
|
|
304
|
+
- **Superusers and `BYPASSRLS` roles** bypass all RLS policies.
|
|
305
|
+
- **No policies = deny all** when RLS is enabled (except for table owner).
|
|
306
|
+
- **Performance**: RLS adds filter conditions to every query. Ensure the policy columns are indexed.
|
|
307
|
+
- **Leaky views**: Functions in RLS policies that are not `LEAKPROOF` could theoretically leak data via error messages or side channels. Use `LEAKPROOF` functions where possible.
|
|
308
|
+
|
|
309
|
+
```sql
|
|
310
|
+
-- Force RLS on table owner
|
|
311
|
+
ALTER TABLE orders FORCE ROW LEVEL SECURITY;
|
|
312
|
+
|
|
313
|
+
-- Check which tables have RLS enabled
|
|
314
|
+
SELECT relname, relrowsecurity, relforcerowsecurity
|
|
315
|
+
FROM pg_class
|
|
316
|
+
WHERE relkind = 'r' AND relnamespace = 'public'::regnamespace;
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## pg_hba.conf Authentication
|
|
320
|
+
|
|
321
|
+
`pg_hba.conf` controls who can connect, from where, and how they authenticate. Rules are evaluated top-to-bottom; first match wins.
|
|
322
|
+
|
|
323
|
+
### Format
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
# TYPE DATABASE USER ADDRESS METHOD
|
|
327
|
+
local all all scram-sha-256
|
|
328
|
+
host all all 127.0.0.1/32 scram-sha-256
|
|
329
|
+
host all all ::1/128 scram-sha-256
|
|
330
|
+
host mydb app_user 10.0.0.0/8 scram-sha-256
|
|
331
|
+
host all all 0.0.0.0/0 reject
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Authentication Methods
|
|
335
|
+
|
|
336
|
+
| Method | Security | Use case |
|
|
337
|
+
|--------|----------|----------|
|
|
338
|
+
| `scram-sha-256` | Strong | **Recommended default** — salted challenge-response |
|
|
339
|
+
| `md5` | Weak | Legacy — **deprecated in PG18** (emits warnings) |
|
|
340
|
+
| `cert` | Strong | Client certificate (mutual TLS) |
|
|
341
|
+
| `peer` | Strong | Local connections — maps OS user to PG role |
|
|
342
|
+
| `ident` | Moderate | TCP — maps OS user via ident server |
|
|
343
|
+
| `gss` | Strong | Kerberos/GSSAPI |
|
|
344
|
+
| `ldap` | Moderate | LDAP directory authentication |
|
|
345
|
+
| `trust` | None | **Never use in production** — no password required |
|
|
346
|
+
| `reject` | N/A | Explicitly deny connections |
|
|
347
|
+
|
|
348
|
+
### Best Practices
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
# 1. Use scram-sha-256 (not md5)
|
|
352
|
+
# 2. Be specific — don't use 'all' for database/user in production
|
|
353
|
+
# 3. Restrict by IP range
|
|
354
|
+
# 4. Put reject rules at the bottom as a catch-all
|
|
355
|
+
# 5. Use 'local peer' for admin access (no password over unix socket)
|
|
356
|
+
|
|
357
|
+
local all postgres peer
|
|
358
|
+
host mydb app_user 10.0.1.0/24 scram-sha-256
|
|
359
|
+
host replication repl_user 10.0.2.0/24 scram-sha-256
|
|
360
|
+
hostssl mydb all 0.0.0.0/0 scram-sha-256
|
|
361
|
+
host all all 0.0.0.0/0 reject
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
After modifying `pg_hba.conf`, reload:
|
|
365
|
+
|
|
366
|
+
```sql
|
|
367
|
+
SELECT pg_reload_conf();
|
|
368
|
+
-- or from CLI: pg_ctl reload
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Password Policies and Authentication
|
|
372
|
+
|
|
373
|
+
### Enforce scram-sha-256
|
|
374
|
+
|
|
375
|
+
```sql
|
|
376
|
+
-- In postgresql.conf:
|
|
377
|
+
-- password_encryption = scram-sha-256 (default in PG14+)
|
|
378
|
+
|
|
379
|
+
-- Verify
|
|
380
|
+
SHOW password_encryption;
|
|
381
|
+
|
|
382
|
+
-- Check which roles still use md5
|
|
383
|
+
SELECT rolname, rolpassword LIKE 'md5%' AS uses_md5
|
|
384
|
+
FROM pg_authid
|
|
385
|
+
WHERE rolcanlogin AND rolpassword IS NOT NULL;
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Password Expiration
|
|
389
|
+
|
|
390
|
+
```sql
|
|
391
|
+
-- Set expiration on a role
|
|
392
|
+
ALTER ROLE app_user VALID UNTIL '2025-06-01';
|
|
393
|
+
|
|
394
|
+
-- Check expiration
|
|
395
|
+
SELECT rolname, rolvaliduntil
|
|
396
|
+
FROM pg_roles
|
|
397
|
+
WHERE rolvaliduntil IS NOT NULL;
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
PostgreSQL does not enforce password complexity natively. Use `passwordcheck` module or application-level validation:
|
|
401
|
+
|
|
402
|
+
```sql
|
|
403
|
+
-- In postgresql.conf:
|
|
404
|
+
-- shared_preload_libraries = 'passwordcheck'
|
|
405
|
+
-- Enforces minimum length and basic complexity
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### SSL/TLS
|
|
409
|
+
|
|
410
|
+
```sql
|
|
411
|
+
-- Check if SSL is enabled
|
|
412
|
+
SHOW ssl;
|
|
413
|
+
|
|
414
|
+
-- Check current connection's SSL status
|
|
415
|
+
SELECT ssl, version, cipher, bits
|
|
416
|
+
FROM pg_stat_ssl
|
|
417
|
+
WHERE pid = pg_backend_pid();
|
|
418
|
+
|
|
419
|
+
-- Require SSL for specific connections (in pg_hba.conf):
|
|
420
|
+
-- hostssl mydb all 0.0.0.0/0 scram-sha-256
|
|
421
|
+
-- hostnossl mydb all 0.0.0.0/0 reject
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Security Best Practices
|
|
425
|
+
|
|
426
|
+
### Principle of Least Privilege
|
|
427
|
+
|
|
428
|
+
```sql
|
|
429
|
+
-- 1. Revoke default public access
|
|
430
|
+
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
|
|
431
|
+
REVOKE ALL ON DATABASE mydb FROM PUBLIC;
|
|
432
|
+
|
|
433
|
+
-- 2. Create role groups with specific privileges
|
|
434
|
+
CREATE ROLE app_readonly;
|
|
435
|
+
GRANT USAGE ON SCHEMA public TO app_readonly;
|
|
436
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_readonly;
|
|
437
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO app_readonly;
|
|
438
|
+
|
|
439
|
+
CREATE ROLE app_readwrite;
|
|
440
|
+
GRANT USAGE ON SCHEMA public TO app_readwrite;
|
|
441
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_readwrite;
|
|
442
|
+
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO app_readwrite;
|
|
443
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
444
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_readwrite;
|
|
445
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
446
|
+
GRANT USAGE ON SEQUENCES TO app_readwrite;
|
|
447
|
+
|
|
448
|
+
-- 3. Assign users to groups
|
|
449
|
+
CREATE ROLE web_app WITH LOGIN PASSWORD '...';
|
|
450
|
+
GRANT app_readwrite TO web_app;
|
|
451
|
+
|
|
452
|
+
CREATE ROLE analyst WITH LOGIN PASSWORD '...';
|
|
453
|
+
GRANT app_readonly TO analyst;
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Audit Who Has Access
|
|
457
|
+
|
|
458
|
+
```sql
|
|
459
|
+
-- All role memberships
|
|
460
|
+
SELECT
|
|
461
|
+
r.rolname AS group_role,
|
|
462
|
+
m.rolname AS member,
|
|
463
|
+
am.admin_option
|
|
464
|
+
FROM pg_auth_members am
|
|
465
|
+
JOIN pg_roles r ON r.oid = am.roleid
|
|
466
|
+
JOIN pg_roles m ON m.oid = am.member
|
|
467
|
+
ORDER BY r.rolname, m.rolname;
|
|
468
|
+
|
|
469
|
+
-- Roles with superuser
|
|
470
|
+
SELECT rolname FROM pg_roles WHERE rolsuper;
|
|
471
|
+
|
|
472
|
+
-- Roles with BYPASSRLS (can circumvent row-level security)
|
|
473
|
+
SELECT rolname FROM pg_roles WHERE rolbypassrls;
|
|
474
|
+
|
|
475
|
+
-- Roles that can create databases or roles
|
|
476
|
+
SELECT rolname, rolcreatedb, rolcreaterole
|
|
477
|
+
FROM pg_roles
|
|
478
|
+
WHERE rolcreatedb OR rolcreaterole;
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Avoid Common Security Mistakes
|
|
482
|
+
|
|
483
|
+
1. **Never use `trust` authentication** in production (allows passwordless access)
|
|
484
|
+
2. **Never run applications as superuser** — create dedicated roles with minimal privileges
|
|
485
|
+
3. **Don't store passwords in connection strings** in code — use `.pgpass`, environment variables, or secret managers
|
|
486
|
+
4. **Pin `search_path`** in `SECURITY DEFINER` functions
|
|
487
|
+
5. **Enable SSL** for all non-local connections (`hostssl` in pg_hba.conf)
|
|
488
|
+
6. **Audit superuser access** regularly — minimize the number of superuser roles
|
|
489
|
+
7. **Use `scram-sha-256`** — md5 is deprecated (PG18 emits warnings on md5 password creation)
|