Skip to content

Tags: Zipstack/unstract

Tags

v0.141.1

Toggle v0.141.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2994 [FIX] hitl rules issue fix (#1655)

hitl rules issue fix

v0.141.0

Toggle v0.141.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2586 [FEAT] Add email notification support for connector sharing (#…

…1647)

Implement notification functionality when connectors are shared with users.
When a connector owner shares with specific users via PATCH request, the
system now sends personalized email notifications to newly shared users.

Changes:
- Add notification service integration in ConnectorInstanceViewSet
- Override partial_update() to detect newly shared users
- Send email notifications via SharingNotificationService
- Graceful error handling without breaking sharing operation

The implementation follows the pattern used in pipeline sharing, using
SendGrid for email delivery with dynamic templates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <[email protected]>

v0.140.1

Toggle v0.140.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2972 [MISC] Improve global rate limit error message for better use…

…r experience (#1652)

* Improve global rate limit error message for better user experience

Changed global limit exceeded error message to be more user-friendly:
  "Our system is currently experiencing high load. Please try again in a few moments."

This provides a clearer, more actionable message for end users when the system
is at capacity. Organization-specific limit errors remain unchanged and continue
to show current usage details.

Updated documentation to show both error response formats.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Remove unused parameters from get_global_limit_exceeded_message()

The method returns a static generic message and doesn't use the current_usage
and limit parameters. Removing them makes the API clearer and less confusing.

Addresses PR review feedback.

* Apply suggestion from @ritwik-g

Signed-off-by: Ritwik G <[email protected]>

---------

Signed-off-by: Ritwik G <[email protected]>
Co-authored-by: Claude <[email protected]>

v0.140.0

Toggle v0.140.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2950 [MISC] Modify check_feature_flag_status to handle None namesp…

…ace_key and Support ENV based default value (#1645)

* Modify check_feature_flag_status to handle None namespace_key and Support ENV based default value

Update namespace_key parameter to accept None and adjust documentation.

Signed-off-by: Ritwik G <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Signed-off-by: Ritwik G <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Rahul Johny <[email protected]>

v0.139.8

Toggle v0.139.8's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2972 [FEAT] Implement API deployment rate limiting with Django cac…

…he and per-org locks (#1649)

* UN-2972: Implement API deployment rate limiting with Django cache and per-org locks

This commit implements a comprehensive rate limiting system for API deployments
with atomic operations, caching, and management commands.

Features:
- Organization-level and global concurrent request limits
- Per-organization Redis distributed locks to prevent race conditions
- Django cache integration for org limits (~95% reduction in DB queries)
- Automatic cache invalidation on limit updates
- Centralized constants to eliminate magic strings
- Management commands for easy administration

Technical Details:
- Uses Redis ZSET for tracking active executions with TTL-based cleanup
- Per-org locks ensure atomic check-and-acquire operations
- Global limit enforced with eventual consistency (acceptable tolerance)
- Rate limiter fails open on Redis errors for system reliability
- Retry-After header in 429 responses for proper client backoff

New Files:
- backend/api_v2/rate_limit_constants.py: Centralized keys and constants
- backend/api_v2/rate_limiter.py: Core rate limiting logic
- backend/api_v2/migrations/0003_add_organization_rate_limit.py: DB migration
- backend/api_v2/management/commands/set_org_rate_limit.py: Set org limits
- backend/api_v2/management/commands/get_org_rate_limit.py: View org limits
- backend/api_v2/management/commands/list_org_rate_limits.py: List all limits

Modified Files:
- backend/api_v2/models.py: OrganizationRateLimit model with auto cache clearing
- backend/api_v2/deployment_helper.py: Use atomic check_and_acquire
- backend/api_v2/admin.py: Admin interface for OrganizationRateLimit
- backend/api_v2/exceptions.py: RateLimitExceeded exception
- backend/backend/exceptions.py: Add Retry-After header to 429 responses
- backend/workflow_manager/workflow_v2/models/execution.py: Auto-release on completion
- backend/backend/settings/base.py: Rate limiting configuration
- backend/sample.env: Configuration documentation

Configuration (environment variables):
- API_DEPLOYMENT_DEFAULT_RATE_LIMIT: Default per-org limit (default: 5)
- API_DEPLOYMENT_GLOBAL_RATE_LIMIT: System-wide limit (default: 50)
- API_DEPLOYMENT_RATE_LIMIT_TTL_HOURS: ZSET entry TTL (default: 6 hours)
- API_DEPLOYMENT_RATE_LIMIT_CACHE_TTL: Cache TTL (default: 1 hour)
- API_DEPLOYMENT_RATE_LIMIT_LOCK_TIMEOUT: Lock timeout (default: 2 seconds)
- API_DEPLOYMENT_RATE_LIMIT_LOCK_BLOCKING_TIMEOUT: Lock wait (default: 5 seconds)
- API_DEPLOYMENT_RATE_LIMIT_RETRY_AFTER: Retry-After value (default: 300 seconds)

Management Commands:
- python manage.py set_org_rate_limit <org-id-or-name> <limit>
- python manage.py get_org_rate_limit <org-id-or-name> [--clear-cache]
- python manage.py list_org_rate_limits [--with-usage]

Performance Impact:
- DB queries for org limits: ~95% reduction (cached)
- Rate limit check latency: 10-20ms (acceptable tradeoff for no race conditions)
- Lock contention: Minimal (per-org, not global)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* UN-2972 [FIX] Move signal imports to top of models.py to fix Ruff E402

Fix Ruff linting errors by moving Django signal imports to the top of the file
according to PEP 8 conventions.

Changes:
- Moved `from django.db.models.signals import post_delete` to line 7
- Moved `from django.dispatch import receiver` to line 8
- Removed duplicate imports from line 268-269 (bottom of file)
- Signal handler function remains at bottom unchanged

Fixes Ruff errors:
- E402: Module level import not at top of file (line 266)
- E402: Module level import not at top of file (line 267)

Also installed pre-commit hooks locally for future commits.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Fix organization lookup in rate limit management commands

The Organization.organization_id field is a CharField (not UUIDField),
storing custom string IDs like "org_qijtoAkJNhznYhNt". The previous
implementation attempted UUID parsing which failed for these values.

Changes:
- Remove UUID validation that assumes organization_id is a UUID
- Try organization_id lookup first (handles both UUID and string formats)
- Fall back to name lookup if organization_id lookup fails
- Update help text to remove "UUID" reference

This allows commands to work with both:
- Organization ID: python manage.py set_org_rate_limit org_qijtoAkJNhznYhNt 10
- Organization name: python manage.py set_org_rate_limit zipstack 10

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Add delete_org_rate_limit management command and improve error logging

New command allows administrators to remove custom organization rate limits,
reverting organizations back to the system default limit.

Features:
- Delete custom rate limit for an organization (by ID or name)
- Confirmation prompt (can be skipped with --force)
- Shows default limit that will be used after deletion
- Warns if current usage exceeds default
- Automatic cache clearing via post_delete signal

Also improved error logging in WorkflowExecution to use logger.exception()
instead of logger.error() for better stack trace visibility.

Usage:
  python manage.py delete_org_rate_limit org_qijtoAkJNhznYhNt
  python manage.py delete_org_rate_limit zipstack --force

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Add cache clearing command and improve cache TTL behavior

New Features:
1. Management command to clear organization rate limit cache
   - Clear specific org: --org-id <org_id>
   - Clear all with custom limits: (default)
   - Clear ALL orgs: --all
   - Uses Redis pattern deletion (rate_limit:cache:org_limit:*)
     for performance, falls back to individual deletion

2. Reduced cache TTL from 1 hour to 10 minutes
   - Allows faster pickup of default limit changes from ENV
   - Still provides significant DB query reduction

3. Implement cache TTL refresh on every read
   - TTL is extended by 10 minutes on every cache hit
   - Frequently-used orgs stay cached indefinitely
   - Inactive orgs expire after 10 minutes
   - LRU-like behavior without explicit LRU cache

Usage:
  # Clear specific organization cache
  python manage.py clear_org_rate_limit_cache --org-id org_qijtoAkJNhznYhNt

  # Clear cache for all orgs with custom limits
  python manage.py clear_org_rate_limit_cache

  # Clear cache for ALL organizations (uses pattern deletion if Redis)
  python manage.py clear_org_rate_limit_cache --all

This is useful when changing API_DEPLOYMENT_DEFAULT_RATE_LIMIT to ensure
organizations pick up the new default value immediately.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Add comprehensive rate limiting documentation and update default limits

Documentation:
- Created docs/API_DEPLOYMENT_RATE_LIMITING.md with:
  - Architecture overview (per-org + global limits, Redis locks, cache)
  - All 7 ENV variables with detailed explanations
  - All 5 management commands with usage examples
  - Usage scenarios and best practices
  - Troubleshooting guide
  - Performance characteristics and security considerations
  - Confirms rate limiting ONLY affects API deployments (not ETL/tasks)

Default Limit Updates (3 locations):
- Organization limit: 5 → 20 concurrent requests
- Global limit: 50 → 100 concurrent requests
- Updated in:
  1. backend/api_v2/rate_limit_constants.py (RateLimitDefaults)
  2. backend/sample.env (environment variable defaults)
  3. backend/backend/settings/base.py (Django setting defaults)

Also updated cache TTL default in base.py: 3600s → 600s (10 minutes)
to match the change made in previous commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Use centralized constants and remove Retry-After functionality

Issues Fixed:
1. RateLimitExceeded was not using centralized RateLimitMessages constants
2. Response format documentation didn't match actual drf-standardized-errors format
3. Retry-After header and retry_after_seconds were not useful (hard to predict accurately)

Changes:
- RateLimitExceeded now uses RateLimitMessages.get_org_limit_exceeded_message()
  and get_global_limit_exceeded_message() for consistent error messages
- Removed retry_after_seconds parameter from RateLimitExceeded.__init__()
- Removed retry_after_seconds from rate_limiter.py return dicts
- Removed retry_after_seconds from deployment_helper.py exception call
- Removed dead Retry-After header code from backend/exceptions.py
- Removed API_DEPLOYMENT_RATE_LIMIT_RETRY_AFTER from:
  - sample.env
  - settings/base.py
  - rate_limit_constants.py (DEFAULT_RETRY_AFTER_SECONDS)
- Updated documentation to show actual drf-standardized-errors response format:
  {
    "type": "client_error",
    "errors": [{"code": "error", "detail": "...", "attr": null}]
  }
- Removed all Retry-After references from documentation

Clients should implement their own retry logic with exponential backoff.
Rate limits are released when active requests complete.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Fix late imports and comparison bug in rate limit management commands

- Move APIDeploymentRateLimiter import to module top (PEP 8 compliance)
- Fix off-by-one warning bug: change > to >= to match rate limiter blocking logic
- Affects: delete_org_rate_limit, set_org_rate_limit, get_org_rate_limit, list_org_rate_limits

The rate limiter blocks when usage >= limit, so warnings must also use >= for consistency.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Refactor rate limiting to view layer with dual release paths

**Problem:**
Review bot identified critical bug where early failures (DB, file staging, queue dispatch)
would leak rate limit slots for 6 hours, potentially exhausting org/global quotas.

**Root Cause:**
- Rate limiting was in deployment_helper.py
- Helper has internal try-catch that swallows exceptions and returns error response
- Exceptions that don't propagate can't be caught by outer handlers
- No slot release on these failures → orphaned slots

**Solution:**
Move rate limiting to view layer with dual release strategy:

1. **View Layer (api_deployment_views.py)**
   - Acquires rate limit slot before calling execute_workflow()
   - Wraps execute_workflow() in try-catch
   - Releases slot if exception propagates (early setup failures)

2. **Helper Layer (deployment_helper.py)**
   - Accepts optional execution_id parameter
   - Existing exception handler now also releases slot
   - Handles failures in async dispatch that don't propagate

3. **Signal (workflow completion)**
   - Unchanged - releases slot when async job completes successfully

**Coverage:**
✅ Lines 197-241 failures (Tag creation, WorkflowExecution, file staging) → View catches & releases
✅ Lines 243-289 failures (Async dispatch, config checks) → Helper catches & releases
✅ Async job completion → Signal releases
✅ No double-release (each path has one release point)
✅ No orphaned slots on any error path

**Files Changed:**
- api_deployment_views.py: Add rate limit check + blanket exception handler
- deployment_helper.py: Accept execution_id param, add slot release to exception handler
- API_DEPLOYMENT_RATE_LIMITING.md: Update architecture diagram and code locations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Use logger.exception() to capture full traceback in rate limit exception handler

Changed logger.error() to logger.exception() in api_deployment_views.py exception
handler to automatically include the full stack trace. This provides better debugging
information when workflow execution fails during rate limit protected operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Update documentation with generic organization IDs

* Address PR review comments: remove dead code and clarify TTL behavior

1. Remove deprecated acquire_slot() method (PR comment #1)
   - Method marked as deprecated, not used anywhere in codebase
   - check_and_acquire() is the only method used (atomic operation)
   - Dead code removal improves maintainability

2. Add detailed comment explaining TTL vs manual cleanup (PR comment #2)
   - Clarifies why _cleanup_expired_entries() is needed even with TTL
   - Redis ZSET TTL expires entire key, not individual entries
   - Manual cleanup (ZREMRANGEBYSCORE) removes stale entries within ZSET
   - Both mechanisms work together for accurate rate limiting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

v0.139.7

Toggle v0.139.7's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2932 [FIX] hitl rules check issue fix (#1648)

hitl rules check issue fix

v0.139.6

Toggle v0.139.6's commit message

Partially verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
[MISC] Add workers directory to UV automation workflow (#1642)

* Add 'workers' directory to the list of directories

Signed-off-by: jagadeeswaran-zipstack <[email protected]>

* updated uv lock

---------

Signed-off-by: jagadeeswaran-zipstack <[email protected]>
Co-authored-by: Deepak K <[email protected]>

v0.139.5

Toggle v0.139.5's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2942 [HOT-FIX] Fix API deployment directory cleanup and MinIO comp…

…atibility (#1637)

* Fix/un 2910 fix prevent task duplication while warm shutdown heartbeatkeeper and resolve sigsegv issues (#1616)

* UN-2910 [FIX] Prevent task duplication during Kubernetes warm shutdown with HeartbeatKeeper

Implemented HeartbeatKeeper bootstep to maintain RabbitMQ connection during
Celery warm shutdown, preventing task requeuing and duplication during
Kubernetes rolling updates and graceful pod terminations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* structuretool-for-testing

* handling envs

* sonar issue addressing

* forksafe gcs and gdrive connectors

* updated grpc imports

* fork safty in shared internal client session

* reverted forksafty fropm baseclient, addressed coderabbitai comments

* minor changes

* reverted structure tool changes that was changed for tetsing

* plugin registry changes for .so file comaptibility

* added default value for heartbeat

---------

Co-authored-by: Claude <[email protected]>

* Fix: Added InternalAPIAuthMiddleware to Django middleware stack (#1628)

* UN-2942 [HOT-FIX] API deployments now properly clean up execution directories after completion (#1635)

UN-2942 [FIX] API deployments now properly clean up execution directories after completion

* UN-2942 [FIX] Fix API deployment directory cleanup and MinIO compatibility (#1636)

* Added boto3 version pin to match backend

* Added uvlock

* fix execution directory for api

---------

Signed-off-by: ali <[email protected]>
Co-authored-by: Claude <[email protected]>

v0.139.4

Toggle v0.139.4's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2226: Platform settings modal fix (#1632)

UN-2226: Paltform settings modal fix

v0.138.19

Toggle v0.138.19's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
UN-2942 [FIX] Fix API deployment directory cleanup and MinIO compatib…

…ility (#1636)

* Added boto3 version pin to match backend

* Added uvlock

* fix execution directory for api