_format_version: "1.1" # Kong declarative config for local dev. # Routes: /rest/ → postgrest, /auth/ → gotrue, /storage/ → storage-api, # /realtime/ → realtime, /functions/ → edge-runtime services: - name: auth-v1 url: http://auth:9999/ routes: # /auth/v1/* catch-all. Brute-force protection for password attempts is # handled by Keycloak's native `bruteForceProtected` flag at the realm # level (see keycloak/realm-export.json) — Kong-level rate-limiting on # /auth/v1/token would interfere with legitimate PKCE code exchanges # during E2E runs, since the same endpoint handles both. - name: auth-v1-all strip_path: true paths: - /auth/v1/ plugins: - name: cors - name: rest-v1 url: http://rest:3000/ routes: # Invitations POST — rate-limited per-auth-token: 20/hour. # (Using `limit_by: header` on Authorization gives us per-token quota # which is effectively per-session; the PKCE access token rotates every # hour so this doubles as a short-window leak protection.) - name: rest-v1-invitations strip_path: true methods: - POST paths: - /rest/v1/collective_invitations plugins: - name: rate-limiting config: hour: 20 policy: local fault_tolerant: true limit_by: header header_name: Authorization # strip_path: true on the full table path sends "/" upstream, which # PostgREST rejects with PGRST117 "Unsupported HTTP method". Rewrite # the URI back to the table path so PostgREST routes it correctly. - name: request-transformer config: replace: uri: /collective_invitations - name: rest-v1-all strip_path: true paths: - /rest/v1/ plugins: - name: cors - name: key-auth config: hide_credentials: false - name: acl config: hide_groups_header: true allow: - anon - service - name: graphql-v1 url: http://rest:3000/rpc/graphql routes: - name: graphql-v1-all strip_path: true paths: - /graphql/v1 plugins: - name: cors - name: key-auth config: hide_credentials: false - name: request-transformer config: add: headers: - Content-Profile:graphql_public - name: realtime-v1 url: http://realtime:4000/socket routes: - name: realtime-v1-all strip_path: true paths: - /realtime/v1/ plugins: - name: cors - name: storage-v1 url: http://storage:5000/ routes: - name: storage-v1-all strip_path: true paths: - /storage/v1/ plugins: - name: cors - name: meta url: http://meta:8080/ routes: - name: meta-all strip_path: true paths: - /pg/ consumers: - username: anon keyauth_credentials: - key: ${SUPABASE_ANON_KEY} acls: - group: anon - username: service_role keyauth_credentials: - key: ${SUPABASE_SERVICE_KEY} acls: - group: service