Commit Graph

48 Commits

Author SHA1 Message Date
Ejiro Asiuwhu
d0550079f7 fix: address PR review findings from bot analysis
- Fix incorrect docstring method names in get_item (set_quantity ->
  increase_quantity, decrease_quantity, try_decrease_quantity)
- Add asyncio.Lock to AsyncJWKSFetcher._fetch_jwks to deduplicate
  concurrent JWKS fetches on cold/expired cache
- Add threading.Lock to SyncJWKSFetcher._fetch_jwks for same reason
- Add threading.Lock to _get_or_create_memory_store to prevent
  race condition in token store registry
- Fix README clone URL to point to upstream repo
- Fix E2E test SyncJWKSFetcher constructor to use correct signature
  (jwks_url + http_client instead of project_id + base_url)
2026-03-26 09:01:06 +01:00
Ejiro Asiuwhu
9ddc8aa818 docs: add comprehensive README for python sdk
Covers installation, quick start, async usage, authentication with
FastAPI example, error handling, teams, self-hosted config, full API
reference, and development/testing instructions.
2026-03-25 08:10:59 +01:00
Ejiro Asiuwhu
625e3c06b6 test: add end-to-end integration test suite for live Stack Auth validation
Covers user CRUD lifecycle, team management, sessions, API key management,
authenticate_request with real request shapes, and async variants.
Requires STACK_E2E=1 env var and running Stack Auth instance.
2026-03-25 08:10:51 +01:00
Ejiro Asiuwhu
b7e21a02e8 fix: replace broad exception catches with specific types and add debug logging
- _decode_jwt_payload catches only ValueError and json.JSONDecodeError
- Token refresh catches httpx.HTTPError, ValueError, KeyError with debug log
- authenticate_request catches jwt.PyJWTError, httpx.HTTPError, ValueError, KeyError
- Added docstring to _token_store_registry explaining purpose and test reset
- Updated test mocks to use jwt.PyJWTError instead of bare Exception
2026-03-25 08:08:12 +01:00
Ejiro Asiuwhu
7ec2e27a8e fix: add debug logging to authenticate_request exception handlers
- Add logger = logging.getLogger("stack_auth") at module level
- Emit logger.debug("authenticate_request failed", exc_info=True) in both sync and async handlers
- Add tests verifying debug log emission on verification failure
2026-03-25 08:02:10 +01:00
Ejiro Asiuwhu
bfff27d4e7 fix: make RequestLike runtime_checkable and remove type: ignore from resolve_token_store
- Add @runtime_checkable decorator to RequestLike Protocol
- Replace bare fallback with isinstance(init, RequestLike) check in resolve_token_store
- Raise TypeError for invalid token store initializer types
- Add tests for isinstance checks and invalid input handling
2026-03-25 08:00:59 +01:00
Ejiro Asiuwhu
6c0c58d2eb feat: add get_partial_user method to StackServerApp and AsyncStackServerApp
- Decode JWT access token claims locally without network request
- Return TokenPartialUser with user ID, display name, email, and flags
- Return None when no token store or no access token available
- Support token_store override parameter for per-call flexibility
- Method is synchronous on both classes since it performs no I/O
2026-03-25 07:53:35 +01:00
Ejiro Asiuwhu
80f2c32f2e test: add failing tests for get_partial_user method
- Test get_partial_user returns TokenPartialUser from valid JWT
- Test returns None when no token store, explicit None, or empty store
- Test token_store override parameter
- Test async variant works identically (sync method, no I/O)
2026-03-25 07:52:42 +01:00
Ejiro Asiuwhu
09595481dd fix: add publishable_client_key parameter and fix token store defaults
- Add publishable_client_key param to BaseAPIClient, StackServerApp, AsyncStackServerApp
- Include x-stack-publishable-client-key header when key is provided
- Change ExplicitTokenStore defaults from empty string to None
- Remove empty string fallback in resolve_token_store dict branch
2026-03-25 07:51:38 +01:00
Ejiro Asiuwhu
6138ff0997 test: add failing tests for publishable_client_key and token store defaults
- Test publishable_client_key header included/omitted in _build_headers
- Test ExplicitTokenStore defaults to None without arguments
- Test resolve_token_store dict branch defaults missing keys to None
- Test StackServerApp/AsyncStackServerApp accept publishable_client_key
2026-03-25 07:50:42 +01:00
Ejiro Asiuwhu
0f39d103ae fix: make metadata fields nullable on user and team models
The Stack Auth API returns null for client_metadata, client_read_only_metadata,
and server_metadata when not set, but the models expected dict. Changed to
dict | None to handle null responses gracefully.
2026-03-25 05:28:42 +01:00
Ejiro Asiuwhu
1343d3ab2f test: add integration tests for payment, email, and data vault methods
- Add sync+async tests for list_products, get_item, grant_product, cancel_subscription
- Add tests for ServerItem.increase_quantity, decrease_quantity, try_decrease_quantity
- Add sync+async tests for send_email (html, text, multi-recipient) and get_email_delivery_stats
- Add sync+async tests for DataVaultStore get, set, delete, list_keys with NotFoundError handling
- Coverage grows from 299 to 337 tests, all passing
2026-03-25 02:26:45 +01:00
Ejiro Asiuwhu
c4ee7daa45 docs: add module docstring with quick-start example and complete PyPI metadata
- Replace one-line module docstring with comprehensive quick-start guide
  covering sync, async, and error handling usage patterns
- Add Framework :: Pydantic :: 2 and Topic classifiers to pyproject.toml
- Add keywords for PyPI discoverability
- Add project.urls section with Homepage, Repository, Documentation, Bug Tracker
2026-03-25 02:05:44 +01:00
Ejiro Asiuwhu
f3780f2c60 docs: add comprehensive Google-style docstrings to all public SDK methods
- Add Args, Returns, and Raises sections to all public methods on
  StackServerApp and AsyncStackServerApp (~46 methods each)
- Expand class-level docstrings with full constructor and usage examples
- Document return-None-on-404 behavior, ValueError raises, and error types
2026-03-25 02:04:58 +01:00
Ejiro Asiuwhu
23c9f850b9 feat: add get_data_vault_store to facade classes and exports
- StackServerApp.get_data_vault_store returns sync DataVaultStore
- AsyncStackServerApp.get_data_vault_store returns AsyncDataVaultStore
- Export DataVaultStore and AsyncDataVaultStore from package root
2026-03-25 01:52:46 +01:00
Ejiro Asiuwhu
299718c9db feat: add data vault store with key-value operations
- DataVaultStore class with sync get/set/delete/list_keys methods
- AsyncDataVaultStore class with async variants
- Export both from models package
2026-03-25 01:51:59 +01:00
Ejiro Asiuwhu
c5ab83984f feat: add payment methods and email sending to StackServerApp
- Add _resolve_customer_path helper for polymorphic customer identification
- Add list_products, get_item, grant_product, cancel_subscription to both sync and async facades
- Add send_email and get_email_delivery_stats to both sync and async facades
- Export ServerItem, AsyncServerItem, EmailDeliveryInfo from package root
2026-03-25 01:49:12 +01:00
Ejiro Asiuwhu
0e6afdc9a7 feat: add ServerItem, AsyncServerItem, and EmailDeliveryInfo models
- ServerItem wraps Item with increase/decrease/tryDecrease quantity methods
- AsyncServerItem provides async counterpart for quantity operations
- EmailDeliveryInfo model for delivery statistics (delivered/bounced/complained/total)
- Export new models from models package
2026-03-25 01:47:35 +01:00
Ejiro Asiuwhu
e8ce41bfbb fix: update team member profile test to include required user_id field
The user_id field was added to TeamMemberProfile during team management
implementation but the pre-existing model test was not updated.
2026-03-25 01:39:56 +01:00
Ejiro Asiuwhu
eae4842ab1 feat: add oauth provider methods and connected accounts to both facades
- create_oauth_provider links OAuth provider to a user
- list_oauth_providers and get_oauth_provider for provider lookup
- list_connected_accounts as alias for list_oauth_providers
- Sync and async versions on both facade classes with tests
2026-03-25 01:37:25 +01:00
Ejiro Asiuwhu
7e41fc8f95 feat: add api key management methods to both facades
- User API key create/list/revoke on StackServerApp and AsyncStackServerApp
- Team API key create/list/revoke on both facades
- check_api_key validates any key and returns user_id/team_id
- Tests for all sync and async API key methods
2026-03-25 01:35:44 +01:00
Ejiro Asiuwhu
adeb156d1a feat: add contact channel verification methods to StackServerApp
- list_contact_channels, create_contact_channel for user channels
- send_verification_code with optional callback URL
- verify_contact_channel to validate codes
- Both sync and async facades
2026-03-25 01:31:32 +01:00
Ejiro Asiuwhu
c2f3a3a03a test: add failing tests for contact channel verification methods
- Tests for list, create, send verification, verify on sync facade
- Tests for all contact channel methods on async facade
- Covers optional fields and callback URL parameter
2026-03-25 01:30:07 +01:00
Ejiro Asiuwhu
e26f3a228e feat: add permission management methods to StackServerApp
- grant_permission, revoke_permission for team and project scope
- list_permissions with optional direct filter
- has_permission boolean check, get_permission single lookup
- Both sync and async facades
2026-03-25 01:29:12 +01:00
Ejiro Asiuwhu
6b012c02d7 test: add failing tests for permission management methods
- Tests for grant, revoke, list, has, get permission on sync facade
- Tests for all permission methods on async facade
- Covers team-scoped and project-level permissions
2026-03-25 01:28:28 +01:00
Ejiro Asiuwhu
cd64ecb703 feat: add team membership, invitations, and member profiles
- Add add_team_member and remove_team_member via /team-memberships
- Add send_team_invitation, list_team_invitations, revoke_team_invitation
- Add list_team_member_profiles and get_team_member_profile
- Add user_id field to TeamMemberProfile for profile filtering
- Both sync and async facades have identical method surfaces
2026-03-25 01:24:57 +01:00
Ejiro Asiuwhu
c48b9ca7fc test: add failing tests for team membership, invitations, and profiles
- Tests for add_team_member, remove_team_member
- Tests for send/list/revoke team invitations
- Tests for list_team_member_profiles and get_team_member_profile
- Async equivalents for all membership/invitation/profile operations
2026-03-25 01:24:01 +01:00
Ejiro Asiuwhu
3bf752f120 feat: add team CRUD and API key lookup to StackServerApp
- Add get_team, list_teams, create_team, update_team, delete_team
- Add get_team_by_api_key with two-step lookup via /api-keys/check
- Import ServerTeam, TeamInvitation, TeamMemberProfile models
- Both sync and async facades have identical method surfaces
- Uses _UNSET sentinel pattern for update_team (same as update_user)
2026-03-25 01:22:59 +01:00
Ejiro Asiuwhu
3094338b42 test: add failing tests for team CRUD methods
- Tests for get_team, list_teams, create_team, update_team, delete_team
- Tests for get_team_by_api_key two-step lookup
- Async equivalents for all team CRUD operations
- Uses respx mocking pattern consistent with existing user tests
2026-03-25 01:22:09 +01:00
Ejiro Asiuwhu
7f4e3eb428 feat: add session management methods to StackServerApp and AsyncStackServerApp
- list_sessions(user_id) returns list of ActiveSession for a user
- get_session(session_id, user_id) filters from list_sessions, returns ActiveSession or None
- revoke_session(session_id, user_id) deletes session via DELETE endpoint
- Both sync and async facades implement all three methods
2026-03-25 01:11:22 +01:00
Ejiro Asiuwhu
e1ccb718f4 test: add failing tests for session management methods
- list_sessions, get_session, revoke_session tests for sync and async
- Tests verify user_id query param, empty results, session filtering
2026-03-25 01:10:41 +01:00
Ejiro Asiuwhu
7eb0c25dc6 feat: export StackServerApp and AsyncStackServerApp from package root
- Add top-level imports so users can write: from stack_auth import StackServerApp
- Remove outdated comment about Phase 3 adding facades
2026-03-25 01:07:48 +01:00
Ejiro Asiuwhu
fd3a816700 feat: add StackServerApp and AsyncStackServerApp with user CRUD
- StackServerApp (sync) and AsyncStackServerApp (async) facade classes
- get_user returns ServerUser or None on 404
- list_users with cursor/limit/order_by/desc/query/include_restricted/include_anonymous
- create_user sends only non-None fields
- update_user uses _UNSET sentinel to distinguish not-provided from explicit None
- delete_user returns None
- get_user_by_api_key performs two-step lookup via /api-keys/check then /users/{id}
- Both classes support context managers and compose API client + optional token store
2026-03-25 01:07:02 +01:00
Ejiro Asiuwhu
13f88755e3 test: add failing tests for StackServerApp and AsyncStackServerApp
- Tests for get_user, list_users, create_user, update_user, delete_user
- Tests for get_user_by_api_key two-step lookup
- Tests for sentinel pattern in update_user (None vs not-provided)
- Both sync and async facades covered with respx mocks
2026-03-25 01:05:49 +01:00
Ejiro Asiuwhu
6b1138981d feat: add token store with CAS-based refresh and dual locks
- TokenStore ABC with get_stored_access_token, get_stored_refresh_token, compare_and_set
- MemoryTokenStore, ExplicitTokenStore, RequestTokenStore implementations
- Module-level registry shares MemoryTokenStore instances per project_id
- resolve_token_store handles memory/dict/request/None init variants
- CAS refresh algorithm (sync + async) with 20s expiry buffer and 75s iat threshold
- Token refresh via form-encoded POST to /api/v1/auth/oauth/token
- Per-instance threading.Lock and asyncio.Lock for concurrency safety
- 34 passing tests covering all store types, registry, helpers, and CAS branches
2026-03-25 00:51:40 +01:00
Ejiro Asiuwhu
8060bc67ff feat: export auth types and functions from stack_auth package
- Add AuthState, TokenPartialUser, decode_access_token_claims to public API
- Add sync_authenticate_request and async_authenticate_request exports
- Existing exports unchanged
2026-03-25 00:51:27 +01:00
Ejiro Asiuwhu
3ca550191b feat: add authenticate_request with jwt verification and partial decode
- TokenPartialUser frozen dataclass for unverified JWT payload extraction
- AuthState frozen dataclass for authentication results
- decode_access_token_claims extracts user info without signature verification
- _extract_token_from_headers handles Authorization and x-stack-auth headers
- sync_authenticate_request and async_authenticate_request compose with JWKS verifier
2026-03-25 00:50:59 +01:00
Ejiro Asiuwhu
ad63cf03a0 test: add failing tests for token store subsystem
- TokenStore ABC, MemoryTokenStore, ExplicitTokenStore, RequestTokenStore
- Registry with shared instances per project_id
- CAS refresh algorithm with timing thresholds (20s/75s)
- Sync and async variants of get_or_fetch_likely_valid_tokens
- Helper functions: _is_fresh_enough, _is_expired, _decode_jwt_payload
2026-03-25 00:50:23 +01:00
Ejiro Asiuwhu
ea427ed423 test: add failing tests for auth module
- Tests for decode_access_token_claims (valid JWT, defaults, malformed, missing sub, base64url)
- Tests for _extract_token_from_headers (Authorization, lowercase, x-stack-auth, missing)
- Tests for sync_authenticate_request and async_authenticate_request
2026-03-25 00:50:06 +01:00
Ejiro Asiuwhu
07c32d4a6e feat: add pagination support with cursor-based PaginatedResult
- PaginatedResult[T] generic wrapping nested {items, pagination: {next_cursor}} shape
- Convenience properties .next_cursor and .has_next_page
- Package __init__.py exports all models, errors, and PaginatedResult
- SyncAPIClient/AsyncAPIClient intentionally excluded from public API
- Tests verify pagination with ServerUser and Team types
2026-03-24 22:25:13 +01:00
Ejiro Asiuwhu
aecd4aa6e7 feat: add project, api key, oauth, payment, and notification models
- Project with nested ProjectConfig and OAuthProviderConfig
- ApiKey hierarchy: ApiKey, UserApiKey, UserApiKeyFirstView, TeamApiKey, TeamApiKeyFirstView
- OAuthConnection and OAuthProvider models
- Item and Product payment models
- NotificationCategory model
- models/__init__.py re-exports all 20+ model classes
2026-03-24 22:23:58 +01:00
Ejiro Asiuwhu
28171d43cf feat: add sync and async HTTP client with retry logic
- BaseAPIClient generic base with header construction, URL building,
  response parsing via x-stack-actual-status and x-stack-known-error
- SyncAPIClient wrapping httpx.Client with context manager support
- AsyncAPIClient wrapping httpx.AsyncClient with async context manager
- Exponential backoff retry for idempotent methods (GET/PUT/DELETE)
- 429 rate limit handling with Retry-After header support
- POST/PUT/PATCH with no body sends {} as JSON
- All 26 tests passing
2026-03-24 22:23:56 +01:00
Ejiro Asiuwhu
7b75ba81a8 feat: add jwt verification with async jwks fetcher and ttl cache
- AsyncJWKSFetcher and SyncJWKSFetcher with 5-minute in-memory TTL cache
- verify_token (async + sync) decodes RS256 JWTs via PyJWT
- Algorithm hardcoded to RS256 to prevent CVE-2022-29217 algorithm confusion
- Force-refresh on unknown kid for key rotation handling
2026-03-24 22:23:23 +01:00
Ejiro Asiuwhu
488e72a9cf feat: add user, team, session, contact channel, and permission pydantic models
- BaseUser and ServerUser with camelCase aliases and millis-to-datetime properties
- Team, ServerTeam, TeamMemberProfile, TeamInvitation with timestamp conversions
- ActiveSession with GeoInfo nested model
- ContactChannel and TeamPermission/ProjectPermission
- Tests for user and team model parsing, inheritance, and field conversion
2026-03-24 22:23:11 +01:00
Ejiro Asiuwhu
6b4cd35875 test: add failing tests for jwt verification and jwks fetching
- AsyncJWKSFetcher and SyncJWKSFetcher construction and key retrieval
- TTL cache behavior with 5-minute expiry
- Force-refresh on unknown kid
- verify_token for valid, expired, invalid signature, missing kid tokens
- CVE-2022-29217 protection: HS256 tokens rejected
2026-03-24 22:22:34 +01:00
Ejiro Asiuwhu
fbe1c5bfc3 test: add failing tests for sync and async HTTP client
- 22 tests covering construction, headers, URL building, request pipeline
- Response processing with x-stack-actual-status and x-stack-known-error
- Retry logic with exponential backoff for idempotent methods
- 429 rate limit handling with Retry-After header
- Context manager protocol for both sync and async clients
2026-03-24 22:22:32 +01:00
Ejiro Asiuwhu
a8c18f366b feat: add python sdk package skeleton with error hierarchy
- StackAuthError base with code/message/details and from_response() factory
- 13 category subclasses: Authentication, NotFound, Validation, PermissionDenied,
  Conflict, OAuth, Passkey, ApiKey, Payment, Email, RateLimit, Cli, Analytics
- Complete _ERROR_CODE_MAP with 143 error codes from known-errors.tsx
- StackAuthModel base class with Pydantic v2 ConfigDict and millis conversion
- Package exports via __init__.py with __all__
2026-03-24 22:18:36 +01:00
Ejiro Asiuwhu
728533c87f test: add failing tests for python sdk error hierarchy and base model
- Test StackAuthError base class storage and string representation
- Test all 13 category subclasses inherit from StackAuthError
- Test from_response() dispatch for known and unknown error codes
- Test StackAuthModel config and millis conversion
- Package skeleton with pyproject.toml (stubs only, tests expected to fail)
2026-03-24 22:17:03 +01:00