Skip to content

feat: api keys#1703

Merged
nikhilsinhaparseable merged 2 commits into
parseablehq:mainfrom
nikhilsinhaparseable:feat/api-key
Jun 26, 2026
Merged

feat: api keys#1703
nikhilsinhaparseable merged 2 commits into
parseablehq:mainfrom
nikhilsinhaparseable:feat/api-key

Conversation

@nikhilsinhaparseable

@nikhilsinhaparseable nikhilsinhaparseable commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

move API key handlers and route scope into oss
all server modes - prism, query, standalone - share the same webscope

Summary by CodeRabbit

  • New Features
    • Added tenant-scoped API key management endpoints (create, list, retrieve, validate, delete) under /apikeys.
    • API key listings show masked key values, while retrieve returns the full key value.
    • Tenant-aware API key creation validates requested roles and prevents duplicate key names within the tenant.
    • API key deletion and cluster sync are integrated for consistent revocation.
  • Bug Fixes
    • Improved handling of revocation sync failures: requests now return a clear service-unavailable response when sync cannot complete.

move API key handlers and route scope into oss
all server modes - prism, query, standalone - share the same webscope
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds tenant-scoped API key HTTP endpoints for create, delete, list, validate, and fetch, plus route registration and revocation-sync error handling.

Changes

API key HTTP surface

Layer / File(s) Summary
Auth, models, and helpers
src/handlers/http/apikeys.rs
Adds admin verification, request/response types, masked list entries, tenant API-key collection, and role-name validation.
Create API key
src/handlers/http/apikeys.rs
Creates a new tenant API-key user after admin and role checks, persists it to metadata, updates the local Users map, and returns the full key.
Delete API key
src/apikeys.rs, src/handlers/http/apikeys.rs
Adds revocation-sync error handling and deletes a tenant API-key user by key id after syncing revocation, removing it from metadata and the local cache.
List, validate, and fetch keys
src/handlers/http/apikeys.rs
Lists masked API keys, validates a presented key against the tenant’s API-key users, and returns a full key record by id.
Module and route wiring
src/handlers/http/mod.rs, src/handlers/http/modal/query_server.rs, src/handlers/http/modal/server.rs
Exports the new handler module and registers the /apikeys web scope in both route configuration paths with authorize(Action::All).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • parseablehq/parseable#1620: Introduces the API-key storage and validation path that the new /apikeys handlers build on.
  • parseablehq/parseable#1628: Refactors API-key entries into UserType::ApiKey tenant users, which the new handlers now create, delete, and query.

Suggested reviewers

  • nitisht
  • praveen5959

Poem

A rabbit hopped in with a shiny new key,
Masked ones for lists and full ones to see.
/apikeys now dances through tenant night air,
With admin checks, rabbits, and careful revocation care.
🐰🔑

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is too sparse and misses the required issue link, rationale, key changes, and checklist details. Expand the PR description to match the template: add Fixes #XXXX if applicable, a Description section with goal/rationale/key changes, and the checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is brief and directly refers to the main change: API key support.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 OpenGrep (1.23.0)
src/apikeys.rs

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.12][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist

src/handlers/http/apikeys.rs

┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

[00.13][ERROR]: unable to find a config; path .coderabbit-opengrep-fallback.yml does not exist


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/handlers/http/apikeys.rs`:
- Around line 37-40: The tenant-admin check in the API key authorization flow is
bypassing RBAC aggregation by reading user.roles directly, so group-derived
admins can be denied. Update the authorization logic in the relevant API key
handler/utility that contains this admin gate to use the same runtime RBAC
permission path used elsewhere, rather than the cached direct role set on user.
Ensure the check recalculates permissions on each authorization decision so
dynamic/group-based admin grants are honored.
- Around line 277-293: The API-key deletion flow in the handler that calls
sync_user_deletion_with_ingestors currently logs sync failures but still returns
a successful response, which can mislead callers about revocation status. Update
the delete path so cluster sync is part of the success contract: if
sync_user_deletion_with_ingestors fails, return a retryable/pending-revocation
response instead of the success JSON, or otherwise only emit success after the
sync completes. Keep the fix localized to the deletion handler around the
existing tracing::error and HttpResponse::Ok response.
- Around line 199-214: The API key flow is persisting and re-serving the raw
bearer secret through the metadata and fetch paths. Update the api key creation
and storage logic around User::new_api_key, get_metadata, put_metadata, and
Users.put_user so only a hash or fingerprint is stored, while the raw secret is
returned once from create. Then adjust the GET/list handlers in this module so
they return masked API key metadata only and never expose the secret again.
- Around line 183-187: Role validation is happening before acquiring
UPDATE_LOCK, so the check can race with concurrent tenant role changes before
the API-key user update is persisted. Move the validate_roles(&body.roles,
&tenant_id) call inside the same locked section in the apikeys handler, after
the UPDATE_LOCK::lock().await guard is acquired and before any storage writes,
so the validation and update run atomically.
- Around line 311-320: The validate_api_key handler currently accepts any
authenticated tenant identity, which makes it usable as a secret-validity
oracle. Update validate_api_key to enforce the same admin gate used elsewhere by
calling verify_admin(&req)? before checking the request body, and keep the
existing collect_tenant_api_keys and ApiKeyError handling unchanged unless
needed to pass the admin check context.

In `@src/handlers/http/modal/server.rs`:
- Around line 233-234: The fetch route wired in server::resource("/{key_id}") to
apikeys::get_api_key is returning the full ApiKeyResponse, including the secret
api_key. Update get_api_key and its response type so this endpoint only returns
masked/non-sensitive metadata for an existing key, and keep full secret exposure
limited to the creation flow where the key is first generated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 6b18c45a-227d-4dfe-a646-159e30e69d52

📥 Commits

Reviewing files that changed from the base of the PR and between 5e7a0f2 and 539095a.

📒 Files selected for processing (4)
  • src/handlers/http/apikeys.rs
  • src/handlers/http/mod.rs
  • src/handlers/http/modal/query_server.rs
  • src/handlers/http/modal/server.rs

Comment thread src/handlers/http/apikeys.rs Outdated
Comment thread src/handlers/http/apikeys.rs Outdated
Comment thread src/handlers/http/apikeys.rs
Comment thread src/handlers/http/apikeys.rs Outdated
Comment thread src/handlers/http/apikeys.rs
Comment thread src/handlers/http/modal/server.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/handlers/http/apikeys.rs (1)

255-272: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make revocation ordering compensatable before remote side effects.

If sync_user_deletion_with_ingestors succeeds but get_metadata/put_metadata fails afterward, remote nodes have revoked the key while this node keeps it in metadata and Users. Consider a pending-revocation/tombstone or compensation flow so local persistence failure cannot leave split cluster auth state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/handlers/http/apikeys.rs` around lines 255 - 272, The revocation flow in
the API-key handler applies the remote cluster deletion before local metadata
updates, which can leave split auth state if get_metadata or put_metadata fails
afterward. Update the revocation path in the apikeys handler around
sync_user_deletion_with_ingestors and the subsequent metadata mutation so local
persistence is committed first or is made compensatable via a
pending-revocation/tombstone state, and only then perform the remote side
effect; if the remote call must stay first, add a retryable compensation path so
a local failure cannot strand the key revoked on other nodes but still present
in local Users/metadata.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/apikeys.rs`:
- Around line 52-53: The `ApiKeyError::RevocationSyncFailed` variant currently
carries the full sync error into its `Display` text, which will be exposed to
clients via `ResponseError`. Update `src/apikeys.rs` so this error variant uses
a generic client-safe message, and keep the detailed `e.to_string()` only in the
logging path in `src/handlers/http/apikeys.rs` where the revocation sync failure
is recorded. Use the `RevocationSyncFailed` symbol and its handling in the HTTP
apikeys handler to make sure the client response no longer leaks internal sync
details.

---

Outside diff comments:
In `@src/handlers/http/apikeys.rs`:
- Around line 255-272: The revocation flow in the API-key handler applies the
remote cluster deletion before local metadata updates, which can leave split
auth state if get_metadata or put_metadata fails afterward. Update the
revocation path in the apikeys handler around sync_user_deletion_with_ingestors
and the subsequent metadata mutation so local persistence is committed first or
is made compensatable via a pending-revocation/tombstone state, and only then
perform the remote side effect; if the remote call must stay first, add a
retryable compensation path so a local failure cannot strand the key revoked on
other nodes but still present in local Users/metadata.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 10190542-8132-4c4a-a263-db496f2a9244

📥 Commits

Reviewing files that changed from the base of the PR and between 539095a and 654ff2b.

📒 Files selected for processing (2)
  • src/apikeys.rs
  • src/handlers/http/apikeys.rs

Comment thread src/apikeys.rs
@nikhilsinhaparseable nikhilsinhaparseable merged commit 4602281 into parseablehq:main Jun 26, 2026
12 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