Skip to content

Conversation

@imaxxs
Copy link
Contributor

@imaxxs imaxxs commented Jan 10, 2026

Note

Major SDK and platform upgrade centered on a unified, model-agnostic gateway and split-key secret management.

  • Adds GatewayClient (client.gateway) with GET/POST/etc and auto secret-name detection; new AnthropicIntegration; refactors OpenAI integration to use gateway
  • Extends Client: new client.anthropic, client.openai (refactored), client.credentials namespace, identity_manager property, get_agent() alias
  • Vault admin ops: SDK methods (get_secret_direct, store_secret_direct, delete_secret_direct, list_secrets_direct) and CLI (vault store|get-secret|list|delete) with masked display and labels
  • Implements split-key secret flow: control-plane share_1 storage, gateway Redis share_2 storage with encryption, Shamir reassembly; new internal endpoints on both services
  • Policy management fixes: PolicyClient uses admin API token, adds get_by_name, strips agent- prefix; CLI switches to model_dump
  • Gateway robustness: header normalization/redaction, response header filtering, path handling for streaming and regular proxy, config enhancements
  • Backend schema/CRUD/API updates: metadata/prime_mod handling, list/get/delete secret endpoints, policy agent_id normalization; utcnow→timezone and Pydantic v2 cleanups
  • Tooling: Makefile test targets (test-unit, test-integration, test-report); version bump to 0.1.11; example fixes (examples 13/14)

Written by Cursor Bugbot for commit 789dafc. This will update automatically on new commits. Configure here.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

# Parse the extracted text to get a list of note titles.
# This logic can be refined based on the actual output of the Granola app.
# For now, we'll filter out very short strings and potential OCR noise.
lines = extracted_text.strip().split('\\n')
Copy link

Choose a reason for hiding this comment

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

String split uses escaped literal instead of newline character

High Severity

The list_granola_notes function uses split('\\n') which splits by the literal two-character string backslash-n, not by actual newline characters. Since pytesseract.image_to_string() returns text with real newline characters, the split will not work correctly, causing the entire OCR output to be treated as a single line instead of being parsed into individual note titles. The code should use split('\n') instead.

Fix in Cursor Fix in Web

return {
"name": secret_obj.name,
"value": secret_obj.value,
"created_at": secret_obj.created_at
Copy link

Choose a reason for hiding this comment

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

Store endpoint lacks update logic despite documentation claiming support

Medium Severity

The /store endpoint docstring states "Store or update a secret" but the implementation only calls crud.secret.create_secret() without any update logic. If a secret with the same name already exists, this will either raise a database integrity error (returning a generic 500 error) or create duplicate entries if there's no unique constraint. Users expecting update functionality based on the documentation will encounter unexpected failures when trying to overwrite existing secrets.

Fix in Cursor Fix in Web

…tion

- Add GatewayClient class for generic API proxying through DeepSecure Gateway
- Add client.gateway with request(), get(), post(), put(), delete(), patch() methods
- Auto-detect secret names for well-known services (OpenAI, Anthropic, Google, etc.)
- Refactor OpenAIIntegration to use GatewayClient underneath
- Add AnthropicIntegration with create_message(), count_tokens(), complete() methods
- Fix example 14 AttributeError: 'Client' object has no attribute 'gateway'
deleted = crud.secret.delete_secret(db=db, name=name)
if deleted:
logger.info(f"Successfully deleted secret '{name}' from control plane")
return {"name": name, "message": "Secret deleted successfully"}
Copy link

Choose a reason for hiding this comment

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

Server response format doesn't match client expectation

High Severity

The control plane's delete_secret endpoint returns {"name": name, "message": "..."} but the CLI expects {"status": "deleted", ...} and checks result.get("status") == "deleted". Since the server response lacks a status key, successful deletions will incorrectly trigger the error path, printing "Unexpected response" and exiting with code 1.

Additional Locations (1)

Fix in Cursor Fix in Web

return client_schemas.CredentialVerificationResponse(
credential_id=credential_id,
status="valid"
)
Copy link

Choose a reason for hiding this comment

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

Credential verification stub always returns valid

High Severity

The verify() method in VaultClient is a stub that always returns is_valid=True without actually calling the backend to verify the credential. The CredentialVerificationResponse schema has is_valid: bool = True as a default, and the verify method never overrides it. This means any call to client.credentials.verify() will report the credential as valid even if it's revoked, expired, or doesn't exist. The comment says "In a full implementation, this would call the backend" but the method is exposed through the public API where users expect it to perform real verification.

Additional Locations (1)

Fix in Cursor Fix in Web

return policy
return None
except Exception:
return None
Copy link

Choose a reason for hiding this comment

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

Exception swallowing masks errors as "not found"

Medium Severity

The get_by_name() method uses a bare except Exception: that catches all exceptions and returns None. This makes it impossible for callers to distinguish between a policy that doesn't exist and an actual error (network failure, authentication issue, server error). Code checking if policy is None: create_policy(...) could incorrectly create duplicate policies or miss security misconfigurations when the real issue was a transient network error. The exception should either propagate or be re-raised after logging.

Fix in Cursor Fix in Web

@imaxxs imaxxs merged commit 91af13b into dev Jan 12, 2026
1 check 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