Skip to content

Cap the shared Postgres pool and accept retired proof keys - #62

Merged
Robertpaschal merged 1 commit into
mainfrom
cursor/db-pool-proof-keys-02e2
Oct 29, 2026
Merged

Robertpaschal merged 1 commit into
mainfrom
cursor/db-pool-proof-keys-02e2

Conversation

@Robertpaschal

Copy link
Copy Markdown
Owner

Summary

Idle Postgres backends on the 1 GiB RDS instance come from the shared client's postgres.js pool. Proof bundles also verify against only the current signing key, so a rotation would reject older proofs.

Configs touched

  • DB_POOL_MAX: optional positive integer. When set, it replaces the process default. Unset or blank keeps the default. Any other value stops the process at startup with DB_POOL_MAX must be a positive integer.
  • Pool options on the shared client: idle_timeout 20 seconds and max_lifetime 1800 seconds. The API passes a default max of 5. The worker passes a default max of 3.
  • PROOF_SIGNING_KEY: a real multi-line PKCS8 PEM still works. A single line with literal \n escapes is normalized in the same place the key is read. The value is never logged.
  • PROOF_VERIFY_PUBLIC_KEYS: optional comma-separated SPKI public PEMs (-----BEGIN PUBLIC KEY-----). Each entry may be multi-line or one line with \n escapes. Verification tries the current key, then each extra key. Signing still uses only PROOF_SIGNING_KEY. Proofs have no key id.

Prod behaviour preserved

  • Migrate still uses its own one-connection client. The Supabase hook server still uses its own pool (max 2).
  • Seeds and other one-shot scripts that do not pass a pool default still open at most 10 connections. They now close idle connections after 20 seconds, same as the API and worker.
  • Other postgres.js options are unchanged (ssl, connect_timeout, prepare).
  • Proof signing still uses the current Ed25519 PKCS8 key only. Outside production, a missing or non-PEM PROOF_SIGNING_KEY still falls back to the dev key. Production still refuses to start without a real Ed25519 key that is not the committed dev key.
  • POST /v1/proof/verify still ignores public_key on the bundle.
  • In production the committed dev public key is refused in PROOF_VERIFY_PUBLIC_KEYS.
  • This change does not rotate the key and does not deploy.

Proof verification today

  1. Existing proofs are checked only against the current signing key's public key. The response includes public_key and algorithm, and the verifier ignores that public key. There is no key id.
  2. The signing key is Ed25519, PKCS8 PEM (-----BEGIN PRIVATE KEY-----). It is not RSA.
  3. There is no JWKS and no separate published key URL. POST /v1/proof/verify uses the server's keys. Each new proof response includes the current public key. After a rotation, put the old public key in PROOF_VERIFY_PUBLIC_KEYS or older bundles fail that endpoint. Offline checks that use the public key stored on an old bundle are unchanged.
Open in Web Open in Cursor 

The API and worker were keeping idle postgres.js connections open on the
1 GiB RDS instance. Each app now passes its own pool default, DB_POOL_MAX
overrides it, and idle connections close. Proof verification can try extra
SPKI public keys after PROOF_SIGNING_KEY is rotated. Signing is unchanged.

Co-authored-by: Odinaka Robert Nnamani <nnamani.odinakarobert@gmail.com>
@Robertpaschal
Robertpaschal merged commit db93880 into main Oct 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants