Skip to content

Store hosted keys and sessions in Supabase for Render - #46

Merged
pramodbn27 merged 7 commits into
mainfrom
feat/supabase-storage
Oct 20, 2026
Merged

pramodbn27 merged 7 commits into
mainfrom
feat/supabase-storage

Conversation

@pramodbn27

@pramodbn27 pramodbn27 commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add PostgreSQL/Supabase backends for hosted API keys (SHA-256 digests only), per-user sessions and signup limits, selected by DEEP_AGENTIC_CORE_MCP_DATABASE_URL.
  • deploy/supabase/schema.sql creates a private mcp schema (not exposed through the Data API), RLS, and a least-privilege mcp_service role.
  • Render Blueprint drops Key Value and takes the database URL and public URL as secrets; the public URL's hostname is added to allowed hosts.
  • Key rotation/revocation conflicts raise a backend-neutral KeyConflictError.
  • Fix transport/signup test fixtures that leaked remote mode into later chaos tests (test order dependent; also present on main).

Testing

  • pytest: 251 passed against PostgreSQL 16 in Docker (DEEP_AGENTIC_CORE_MCP_TEST_DATABASE_URL); 245 passed, 6 skipped without it.
  • ruff, ruff format, mypy strict: clean.
  • Built Dockerfile.render and ran it against PostgreSQL as mcp_service: /healthz ok, unauthenticated /mcp 401, signup 201, authenticated tool call 200.

Copilot AI lite review requested due to automatic review settings October 20, 2026 07:33
@pramodbn27
pramodbn27 requested a review from a team as a code owner October 20, 2026 07:33
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T07:36:49.365471Z f4a8f11 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f4a8f113b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +81 to +82
elif pool is not None:
store = PostgresSessionStore(pool)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reconcile PostgreSQL sessions with the hosted contract

When DEEP_AGENTIC_CORE_MCP_DATABASE_URL is set without Redis—the exact configuration introduced in render.yaml—this path serves HTTP workflow state from PostgreSQL, while the repository's hosted deployment contract explicitly requires Redis-backed user-scoped workflow state. Either retain Redis for this path or update the governing contract as part of the change; otherwise the default Render deployment violates a documented storage invariant.

AGENTS.md reference: AGENTS.md:L125-L128

Useful? React with 👍 / 👎.

Comment on lines +178 to +179
if any(count >= limit for count, (_, limit, _) in zip(counts, buckets, strict=True)):
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent denied signups from creating permanent buckets

Once the global counter reaches 100, a request from a previously unseen peer has already inserted its ip: bucket before this return, and exiting the connection context commits that row. Because no code deletes expired signup counters, requests from distinct client addresses—including globally denied requests—make mcp.signup_counters grow permanently and can eventually exhaust the hosted database; avoid inserting the client bucket after global denial or periodically delete expired buckets.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved moderate findings remain across documentation, error handling, pool lifecycle and capacity, counter retention, and CI coverage.

3 open issues
What changed in this PR

Adds Supabase/PostgreSQL persistence for hosted keys, sessions, and signup limits, with updated Render deployment support.

Changes:

  • Adds PostgreSQL stores, schema, dependencies, and integration tests.
  • Updates transport, signup handling, and key conflict behavior.
  • Updates Render configuration, documentation, and test fixtures.
File Summary
uv.lock Locks PostgreSQL dependencies.
tests/​test_transport_http.py Updates transport fixture isolation.
tests/​test_signup.py Updates signup and conflict tests.
tests/​test_postgres_store.py Adds PostgreSQL integration coverage.
src/​deep_agentic_core_mcp/​transport_http.py Selects database backends and configures hosts.
src/​deep_agentic_core_mcp/​signup.py Generalizes signup storage handling.
src/​deep_agentic_core_mcp/​services/​postgres_store.py Implements PostgreSQL backends.
src/​deep_agentic_core_mcp/​services/​api_keys.py Adds backend-neutral key conflict handling.
render.yaml Configures Supabase-backed deployment.
pyproject.toml Adds PostgreSQL dependencies.
docs/​remote-hosting.md Documents remote hosting configuration.
deploy/​supabase/​schema.sql Defines the private schema and permissions.
CHANGELOG.md Records the changes.

Review effort: Lite

Comment thread docs/remote-hosting.md
Comment on lines +118 to +121
API keys (SHA-256 digests only), per-user workflow sessions and signup limits
are stored in Supabase PostgreSQL when `DEEP_AGENTIC_CORE_MCP_DATABASE_URL` is
set. Redis is used for sessions instead only if `DEEP_AGENTIC_CORE_MCP_REDIS_URL`
is also set.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c51e9c5: the table now lists DEEP_AGENTIC_CORE_MCP_DATABASE_URL, marks Redis and the database as alternatives, and the intro and expiry text cover both backends.

Comment on lines +27 to +31
return ConnectionPool(
url,
min_size=1,
max_size=max_size,
timeout=10,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e10d533: the pool's max_size is now max_concurrent_total + 4, so every admitted request gets a connection with headroom for auth/signup queries.

Comment on lines +60 to +63
database_url = os.environ.get("DEEP_AGENTIC_CORE_MCP_DATABASE_URL")
pool: Any = None
if database_url and (store is None or (key_store is None and api_keys is None)):
pool = connect(database_url)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in e10d533: the lifespan closes the pool in a finally block (including failed startup), and create_app closes it if construction fails after opening it. Covered by new tests.

…hutdown

A session transaction holds a pool connection for a whole tool call, so the
pool now allows max_concurrent_total plus headroom for auth and signup queries.
The app owns the pool: lifespan closes it, and so does a failed create_app.
@pramodbn27
pramodbn27 merged commit 021e07b into main Oct 20, 2026
6 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