Skip to content

feat: Descope service, SDK library, and generic snapshot explorer#13

Closed
zozo123 wants to merge 5 commits intomainfrom
feat/descope-and-airbyte-services
Closed

feat: Descope service, SDK library, and generic snapshot explorer#13
zozo123 wants to merge 5 commits intomainfrom
feat/descope-and-airbyte-services

Conversation

@zozo123
Copy link
Contributor

@zozo123 zozo123 commented Feb 15, 2026

Summary

This PR adds three major components to DoubleAgent:

1. doubleagent-sdk Python Library (services/_lib/)

The shared SDK that all service fakes depend on:

  • StateOverlay: Copy-on-write state with immutable baseline + mutable overlay + tombstones
  • NamespaceRouter: Per-agent isolation via X-DoubleAgent-Namespace header
  • WebhookSimulator: Async delivery with retry, HMAC-SHA256 signatures, audit log
  • AirbyteAdapter: Wraps 300+ Airbyte Docker source connectors for snapshot pulling
  • PiiRedactor: Deterministic PII replacement before writing snapshots to disk
  • ReadOnlyHttpClient: GET/HEAD-only HTTP with SSRF protection for compliance mode
  • DualTargetValidator: Run same contract tests against fake + real API
  • Unit tests for all modules

2. Descope Identity Management Service (services/descope/)

Full stateful fake of the Descope Management + Auth API:

  • Server (870+ lines): User CRUD with search, tenant/role management, token exchange, OTP simulation, JWKS endpoint, JWT signing with auto-generated RSA keys
  • Contract tests: 30 tests across 5 files — all passing
  • Fixtures: startup.yaml (minimal) + enterprise.yaml (full org)
  • Connector: Schema discovery for snapshot pulling

3. Generic Snapshot Explorer (generic_server.py + Jira/Salesforce)

A read-only server for Airbyte-backed services that don't have custom fakes yet:

  • Serves any seeded/bootstrapped data at GET /resources/{type} and GET /resources/{type}/{id}
  • Supports filtering via ?q=field=value
  • All standard /_doubleagent/* control-plane endpoints
  • Jira and Salesforce wired to use this server

This enables the full Airbyte → DoubleAgent pipeline:

doubleagent snapshot pull jira    # Airbyte Docker pulls data
doubleagent start jira            # Generic server serves it
curl localhost:8080/resources     # Browse the data

Also

  • Root .gitignore for Python/Rust/IDE artifacts

Test plan

  • Descope: 30/30 contract tests passing (pytest services/descope/contracts/)
  • Generic server: health check, seed, list resources, get by ID, filtering, reset all verified via curl
  • Jira: started with generic server, seeded test data, queried successfully
  • Run full CI pipeline

🤖 Generated with Claude Code

zozo123 and others added 5 commits February 15, 2026 14:28
Covers Python artifacts (__pycache__, .venv, .pytest_cache),
Rust target/, IDE files, and .doubleagent.env config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Core SDK providing the stateful fake server infrastructure:

- StateOverlay: copy-on-write state with immutable baseline + mutable overlay
- NamespaceRouter: per-agent isolation via X-DoubleAgent-Namespace header
- WebhookSimulator: async webhook delivery with retry and HMAC signatures
- SnapshotConnector: abstract interface for snapshot pulling
- AirbyteAdapter: wraps 300+ Airbyte Docker connectors for snapshot pulls
- PiiRedactor: deterministic PII replacement before writing to disk
- ReadOnlyHttpClient: GET/HEAD-only HTTP with SSRF protection
- DualTargetValidator: run same tests against fake + real API

Includes unit tests for all modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full stateful fake of the Descope Management + Auth API:

Server (870+ lines):
- User CRUD with search, status management, roles, tenants
- Tenant and role management with full CRUD
- Token exchange, OTP simulation, JWKS endpoint
- Password hashing, JWT signing with auto-generated RSA keys
- All standard /_doubleagent control-plane endpoints

Contract tests (30 tests, all passing):
- test_users: CRUD, search, status, role assignment
- test_tenants: CRUD, member management
- test_roles: CRUD with permission management
- test_tokens: JWT exchange, OTP flow, JWKS validation
- test_snapshots: seed/reset/bootstrap state management

Fixtures:
- startup.yaml: minimal seed (1 user, 1 tenant, 1 role)
- enterprise.yaml: full org (5 users, 3 tenants, 4 roles)

Connector:
- DescopeConnector with schema discovery
- Returns empty data for POST-only APIs (documented)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a generic read-only server that can serve any Airbyte-pulled
snapshot data as a REST API. This enables services that have an
Airbyte connector but no custom fake server (Jira, Salesforce, etc.)
to be started and queried immediately.

Generic server endpoints:
- GET  /resources              → list available resource types
- GET  /resources/{type}       → list resources with filtering (?q=field=value)
- GET  /resources/{type}/{id}  → get single resource by ID
- All standard /_doubleagent/* control-plane endpoints

Wires up Jira and Salesforce to use the generic server:
- services/jira/service.yaml → server command uses generic_server
- services/salesforce/service.yaml → same
- Both include .mise.toml and server/pyproject.toml for dependencies

Usage:
  doubleagent start jira
  curl localhost:8080/_doubleagent/health
  curl -X POST localhost:8080/_doubleagent/seed \
    -d '{"projects": {"P1": {"id": "P1", "name": "Test"}}}'
  curl localhost:8080/resources/projects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… snapshots

Adds PyAirbyte backend (no Docker required) and smart relational filtering
so snapshot pulls produce small, relationally-consistent datasets instead
of brute-force full-stream dumps.

New modules:
- smart_filter.py: breadth-first relational graph traversal (projects → issues → comments)
- pyairbyte_backend.py: wraps PyAirbyte's get_source/get_records API
- airbyte_pull.py: rewritten CLI entry point with dual backend + smart filter

Rust CLI:
- ConnectorConfig gains seeding/backend fields
- snapshot pull passes --seeding-json and --backend to Python subprocess

Service configs:
- Jira: 3 projects → issues/sprints/boards/comments with per-parent limits
- Salesforce: 5 accounts → contacts/opportunities/cases

12 unit tests passing, 3 integration tests (skipped without airbyte pkg).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zozo123
Copy link
Contributor Author

zozo123 commented Feb 15, 2026

Superseded by 3 focused, stacked PRs:

PRs #15 and #16 are based on #14. Merge #14 first, then #15 and #16 can merge in parallel.

@zozo123 zozo123 closed this Feb 15, 2026
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.

1 participant