Skip to content

traylinx/traylinx-auth-client-py

Repository files navigation

Traylinx Auth Client (Python)

PyPI version Python 3.8+ License: MIT

A robust, enterprise-grade Python library for Traylinx Sentinel Agent-to-Agent (A2A) authentication. This client provides secure token management, automatic retry logic, comprehensive error handling, and seamless integration with FastAPI applications.

πŸš€ Features

  • πŸ” Dual Token Authentication: Handles both access_token and agent_secret_token with automatic refresh
  • πŸ›‘οΈ Enterprise Security: Input validation, secure credential handling, and comprehensive error management
  • ⚑ High Performance: Connection pooling, automatic retries with exponential backoff, and efficient token caching
  • πŸ”„ Thread-Safe: Built-in thread safety for concurrent applications and production environments
  • 🎯 FastAPI Integration: Simple decorators for protecting endpoints with A2A authentication
  • πŸ“‘ JSON-RPC Support: Full support for A2A RPC method calls with automatic credential detection
  • πŸ”§ Zero Configuration: Works with environment variables out of the box
  • πŸ“Š Production Ready: Configurable logging, monitoring, and comprehensive error handling

πŸ“¦ Installation

Using pip

pip install traylinx-auth-client

Using Poetry

poetry add traylinx-auth-client

Requirements

  • Python 3.8 or higher
  • requests >= 2.25.0
  • pydantic >= 2.0.0

⚑ Quick Start (5 lines)

from traylinx_auth_client import make_a2a_request

# Set environment variables: TRAYLINX_CLIENT_ID, TRAYLINX_CLIENT_SECRET, 
# TRAYLINX_API_BASE_URL, TRAYLINX_AGENT_USER_ID

# Make authenticated request to another agent
response = make_a2a_request("GET", "https://other-agent.com/api/data")
print(response)  # JSON response from the agent

πŸ”§ Configuration

Environment Variables

Set these environment variables for your agent:

export TRAYLINX_CLIENT_ID="your-client-id"
export TRAYLINX_CLIENT_SECRET="your-client-secret"  
export TRAYLINX_API_BASE_URL="https://auth.traylinx.com"
export TRAYLINX_AGENT_USER_ID="12345678-1234-1234-1234-123456789abc"

Programmatic Configuration

from traylinx_auth_client import TraylinxAuthClient

client = TraylinxAuthClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    api_base_url="https://auth.traylinx.com",
    agent_user_id="12345678-1234-1234-1234-123456789abc",
    timeout=30,           # Request timeout in seconds
    max_retries=3,        # Maximum retry attempts
    retry_delay=1.0,      # Base delay between retries
    cache_tokens=True,    # Enable token caching
    log_level="INFO"      # Logging level
)

πŸ“– Usage Examples

Making Authenticated Requests

Simple Function Approach

from traylinx_auth_client import make_a2a_request

# GET request
data = make_a2a_request("GET", "https://other-agent.com/api/users")

# POST request with JSON data
result = make_a2a_request(
    "POST", 
    "https://other-agent.com/api/process",
    json={"items": ["item1", "item2"]},
    timeout=60
)

# PUT request with custom headers
response = make_a2a_request(
    "PUT",
    "https://other-agent.com/api/update/123",
    json={"status": "completed"},
    headers={"X-Custom-Header": "value"}
)

Manual Header Management

from traylinx_auth_client import get_agent_request_headers
import requests

# Get headers for calling other agents
headers = get_agent_request_headers()

# Make authenticated request
response = requests.get(
    "https://other-agent.com/api/data",
    headers=headers
)

# Headers include:
# {
#     "X-Agent-Secret-Token": "your-agent-secret-token",
#     "X-Agent-User-Id": "your-agent-user-id"
# }

Protecting FastAPI Endpoints

Simple Decorator Approach

from fastapi import FastAPI, Request
from traylinx_auth_client import require_a2a_auth

app = FastAPI()

@app.get("/protected")
@require_a2a_auth
async def protected_endpoint(request: Request):
    return {"message": "This endpoint requires A2A authentication"}

@app.post("/process")
@require_a2a_auth
async def process_data(request: Request, data: dict):
    # This endpoint is automatically protected
    return {"processed": data}

Manual Validation

from fastapi import FastAPI, Request, HTTPException
from traylinx_auth_client import validate_a2a_request

app = FastAPI()

@app.post("/manual-validation")
async def manual_validation(request: Request):
    if not validate_a2a_request(request.headers):
        raise HTTPException(status_code=401, detail="Invalid A2A token")
    
    return {"message": "Token is valid"}

Dual Authentication Support (A2A + Bearer)

from traylinx_auth_client import require_dual_auth, detect_auth_mode

@app.get("/flexible-auth")
@require_dual_auth  # Supports both Bearer tokens and custom headers
async def flexible_endpoint(request: Request):
    auth_mode = detect_auth_mode(request.headers)
    return {"auth_mode": auth_mode, "message": "Authenticated successfully"}

πŸ”§ Advanced Usage

Using the Client Directly

from traylinx_auth_client import TraylinxAuthClient

# Create client with custom configuration
client = TraylinxAuthClient(
    timeout=60,
    max_retries=5,
    retry_delay=2.0
)

# Get individual tokens
access_token = client.get_access_token()
agent_secret_token = client.get_agent_secret_token()

# Get different header types
auth_headers = client.get_request_headers()      # For auth service calls
agent_headers = client.get_agent_request_headers()  # For agent calls
a2a_headers = client.get_a2a_headers()          # A2A-compatible format

# Validate incoming tokens
is_valid = client.validate_token(
    agent_secret_token="incoming-token",
    agent_user_id="sender-agent-id"
)

# Context manager for automatic cleanup
with TraylinxAuthClient() as client:
    response = client.rpc_health_check()

JSON-RPC Method Calls

from traylinx_auth_client import TraylinxAuthClient

client = TraylinxAuthClient()

# Built-in RPC methods
result = client.rpc_introspect_token(
    agent_secret_token="token-to-validate",
    agent_user_id="agent-id"
)

capabilities = client.rpc_get_capabilities()
health = client.rpc_health_check()

# Custom RPC calls
response = client.rpc_call(
    method="custom_method",
    params={"param1": "value1"},
    rpc_url="https://custom-agent.com/a2a/rpc"
)

# RPC call with explicit credential control
response = client.rpc_call(
    method="auth_service_method",
    params={},
    include_agent_credentials=False  # Uses only access_token
)

Error Handling

from traylinx_auth_client import (
    TraylinxAuthClient, 
    AuthenticationError, 
    NetworkError, 
    ValidationError,
    TokenExpiredError
)

try:
    client = TraylinxAuthClient(
        client_id="invalid-id",
        client_secret="invalid-secret"
    )
    response = client.rpc_health_check()
    
except ValidationError as e:
    print(f"Configuration error: {e}")
    print(f"Error code: {e.error_code}")
    
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
    print(f"Status code: {e.status_code}")
    
except NetworkError as e:
    print(f"Network error: {e}")
    if e.error_code == "TIMEOUT":
        print("Request timed out - check network connectivity")
    elif e.error_code == "RATE_LIMIT":
        print("Rate limited - retry after delay")
        
except TokenExpiredError as e:
    print(f"Token expired: {e}")
    # Token will be automatically refreshed on next request

Concurrent Usage

import threading
from traylinx_auth_client import TraylinxAuthClient

# Thread-safe client usage
client = TraylinxAuthClient()

def worker_function(worker_id):
    try:
        # Each thread can safely use the same client
        headers = client.get_agent_request_headers()
        response = make_a2a_request("GET", f"https://api.com/data/{worker_id}")
        print(f"Worker {worker_id}: {response}")
    except Exception as e:
        print(f"Worker {worker_id} error: {e}")

# Create multiple threads
threads = []
for i in range(10):
    thread = threading.Thread(target=worker_function, args=(i,))
    threads.append(thread)
    thread.start()

# Wait for all threads to complete
for thread in threads:
    thread.join()

πŸ“š Complete API Reference

Core Functions

make_a2a_request(method: str, url: str, **kwargs) -> dict

Make an authenticated A2A request to another agent.

Parameters:

  • method (str): HTTP method (GET, POST, PUT, DELETE, etc.)
  • url (str): Target agent's URL
  • **kwargs: Additional arguments for requests.request()

Returns:

  • dict: JSON response from the target agent

Raises:

  • NetworkError: For network-related issues
  • AuthenticationError: For authentication failures
  • ValidationError: For invalid parameters

Example:

response = make_a2a_request("POST", "https://agent.com/api", json={"key": "value"})

get_request_headers() -> dict

Returns headers for calling the auth service (includes access_token).

Returns:

{
    "Authorization": "Bearer <access_token>",
    "X-Agent-Secret-Token": "<agent_secret_token>",
    "X-Agent-User-Id": "<agent_user_id>"
}

get_agent_request_headers() -> dict

Returns headers for calling other agents (ONLY agent_secret_token).

Returns:

{
    "X-Agent-Secret-Token": "<agent_secret_token>",
    "X-Agent-User-Id": "<agent_user_id>"
}

get_a2a_request_headers() -> dict

Returns A2A-compatible headers using Bearer token format.

Returns:

{
    "Authorization": "Bearer <agent_secret_token>",
    "X-Agent-User-Id": "<agent_user_id>"
}

require_a2a_auth(func)

Decorator that protects FastAPI endpoints with A2A authentication.

Example:

@app.get("/protected")
@require_a2a_auth
async def protected_endpoint(request: Request):
    return {"message": "Protected"}

require_dual_auth(func)

Enhanced decorator supporting both Bearer tokens and custom headers.

validate_a2a_request(headers: dict) -> bool

Validates incoming A2A request headers (custom format).

Parameters:

  • headers (dict): Request headers

Returns:

  • bool: True if valid, False otherwise

validate_dual_auth_request(headers: dict) -> bool

Validates incoming requests supporting both Bearer tokens and custom headers.

detect_auth_mode(headers: dict) -> str

Detect authentication mode from request headers.

Returns:

  • str: 'bearer', 'custom', or 'none'

TraylinxAuthClient Class

Constructor

TraylinxAuthClient(
    client_id: str = None,           # OAuth client ID
    client_secret: str = None,       # OAuth client secret  
    api_base_url: str = None,        # Traylinx API base URL
    agent_user_id: str = None,       # Agent user UUID
    timeout: int = 30,               # Request timeout (seconds)
    max_retries: int = 3,            # Maximum retry attempts
    retry_delay: float = 1.0,        # Base retry delay (seconds)
    cache_tokens: bool = True,       # Enable token caching
    log_level: str = "INFO"          # Logging level
)

Parameters:

  • All parameters default to corresponding environment variables
  • timeout: Request timeout in seconds (default: 30)
  • max_retries: Maximum retry attempts for failed requests (default: 3)
  • retry_delay: Base delay between retries in seconds (default: 1.0)
  • cache_tokens: Whether to cache tokens in memory (default: True)
  • log_level: Logging level - DEBUG, INFO, WARN, ERROR (default: "INFO")

Raises:

  • ValidationError: If configuration parameters are invalid

Token Management Methods

get_access_token() -> str

Get current access token for calling auth service.

Returns:

  • str: Valid access token

Raises:

  • TokenExpiredError: If token is unavailable
  • AuthenticationError: If token fetch fails
get_agent_secret_token() -> str

Get current agent secret token for agent-to-agent communication.

Returns:

  • str: Valid agent secret token

Raises:

  • TokenExpiredError: If token is unavailable
  • AuthenticationError: If token fetch fails

Header Generation Methods

get_request_headers() -> dict

Get headers for calling the auth service (includes access_token).

get_agent_request_headers() -> dict

Get headers for calling other agents (ONLY agent_secret_token).

get_a2a_headers() -> dict

Get A2A-compatible authentication headers using Bearer token format.

Validation Methods

validate_token(agent_secret_token: str, agent_user_id: str) -> bool

Validate an agent secret token against the auth service.

Parameters:

  • agent_secret_token (str): Token to validate
  • agent_user_id (str): Agent user ID associated with token

Returns:

  • bool: True if token is valid and active

Raises:

  • AuthenticationError: If validation request fails
  • NetworkError: For network-related issues
validate_a2a_request(headers: dict) -> bool

Validate A2A request supporting both Bearer tokens and custom headers.

detect_auth_mode(headers: dict) -> str

Detect authentication mode from request headers.

JSON-RPC Methods

rpc_call(method: str, params: dict, rpc_url: str = None, include_agent_credentials: bool = None) -> dict

Make a JSON-RPC call with automatic credential detection.

Parameters:

  • method (str): RPC method name
  • params (dict): RPC method parameters
  • rpc_url (str, optional): Custom RPC endpoint URL
  • include_agent_credentials (bool, optional): Whether to include agent credentials

Returns:

  • dict: JSON-RPC response

Raises:

  • ValidationError: For invalid RPC requests or parameters
  • AuthenticationError: For authentication failures
  • NetworkError: For network issues
  • TraylinxAuthError: For RPC-specific errors
rpc_introspect_token(agent_secret_token: str, agent_user_id: str) -> dict

Introspect a token via JSON-RPC.

rpc_get_capabilities() -> dict

Get agent capabilities via JSON-RPC.

rpc_health_check() -> dict

Perform health check via JSON-RPC.

Context Manager Methods

close()

Close the HTTP session and clean up resources.

__enter__() and __exit__()

Support for context manager usage:

with TraylinxAuthClient() as client:
    response = client.rpc_health_check()
# Automatically cleaned up

Exception Classes

TraylinxAuthError

Base exception class for all TraylinxAuthClient errors.

Attributes:

  • error_code (str): Specific error code
  • status_code (int): HTTP status code (if applicable)

ValidationError(TraylinxAuthError)

Raised for input validation failures.

AuthenticationError(TraylinxAuthError)

Raised for authentication-related failures.

TokenExpiredError(TraylinxAuthError)

Raised when tokens are expired or unavailable.

NetworkError(TraylinxAuthError)

Raised for network-related issues (timeouts, connection errors, etc.).

Configuration Classes

AuthConfig

Pydantic model for configuration validation.

Fields:

  • client_id (str): OAuth client ID
  • client_secret (str): OAuth client secret
  • api_base_url (HttpUrl): Traylinx API base URL
  • agent_user_id (str): Agent user UUID
  • timeout (int): Request timeout in seconds
  • max_retries (int): Maximum retry attempts
  • retry_delay (float): Base retry delay
  • cache_tokens (bool): Enable token caching
  • log_level (str): Logging level

πŸ” Authentication Flow

Dual Token System

Traylinx uses a dual-token authentication system for enhanced security:

  1. access_token: Used for calling Traylinx auth service endpoints
  2. agent_secret_token: Used for agent-to-agent communication

Authentication Process

sequenceDiagram
    participant Client as TraylinxAuthClient
    participant Auth as Traylinx Sentinel API
    participant Agent as Target Agent
    
    Note over Client,Auth: Initial Authentication
    Client->>Auth: POST /oauth/token (client_credentials)
    Auth-->>Client: {access_token, agent_secret_token, expires_in}
    
    Note over Client,Auth: Calling Auth Service
    Client->>Auth: GET /a2a/rpc (Authorization: Bearer access_token)
    Auth-->>Client: Response
    
    Note over Client,Agent: Calling Other Agents
    Client->>Agent: POST /endpoint (X-Agent-Secret-Token: agent_secret_token)
    Agent->>Auth: Validate token
    Auth-->>Agent: Token valid
    Agent-->>Client: Response
Loading

Token Usage Matrix

Scenario access_token agent_secret_token Headers
Auth service calls βœ… Required ❌ Not used Authorization: Bearer <access_token>
Agent-to-agent calls ❌ Not used βœ… Required X-Agent-Secret-Token: <agent_secret_token>
A2A compatible calls ❌ Not used βœ… Required Authorization: Bearer <agent_secret_token>
Token validation βœ… Required ❌ Not used Authorization: Bearer <access_token>

Automatic Token Management

  1. Token Acquisition: Automatically fetches tokens using OAuth2 client_credentials grant
  2. Token Caching: Tokens cached in memory with thread-safe access
  3. Automatic Refresh: Expired tokens refreshed automatically before requests
  4. Error Recovery: Handles token expiration and authentication failures gracefully

Example token response:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "agent_secret_token": "TqlJuJi5aJa7lz8rg9zWjbRDChND8m9PMr4bsn...",
    "token_type": "Bearer",
    "expires_in": 7200,
    "scope": "a2a"
}

πŸ›‘οΈ Error Handling & Resilience

Comprehensive Error Management

The client provides robust error handling with specific exception types:

from traylinx_auth_client import (
    TraylinxAuthError,      # Base exception
    ValidationError,        # Configuration/input validation
    AuthenticationError,    # Authentication failures  
    TokenExpiredError,      # Token expiration
    NetworkError           # Network/connectivity issues
)

Automatic Retry Logic

  • Exponential Backoff: Automatic retries with increasing delays
  • Configurable Retries: Set max_retries and retry_delay parameters
  • Smart Retry Logic: Only retries on transient failures (429, 5xx errors)
  • Connection Pooling: Efficient connection reuse for better performance

Error Scenarios Handled

Error Type HTTP Status Retry Description
ValidationError 400 ❌ Invalid configuration or parameters
AuthenticationError 401 ❌ Invalid credentials or expired tokens
NetworkError (Rate Limit) 429 βœ… Rate limiting - automatic retry with backoff
NetworkError (Timeout) 408 βœ… Request timeout - configurable retry
NetworkError (Server Error) 5xx βœ… Server errors - automatic retry
NetworkError (Connection) 0 βœ… Connection failures - automatic retry

Production Monitoring

import logging
from traylinx_auth_client import TraylinxAuthClient, NetworkError

# Configure logging
logging.basicConfig(level=logging.INFO)

client = TraylinxAuthClient(log_level="INFO")

try:
    response = client.rpc_health_check()
except NetworkError as e:
    if e.error_code == "RATE_LIMIT":
        logging.warning(f"Rate limited: {e}")
        # Implement backoff strategy
    elif e.error_code == "TIMEOUT":
        logging.error(f"Request timeout: {e}")
        # Check network connectivity
    else:
        logging.error(f"Network error: {e}")

πŸ”’ Security Best Practices

Credential Management

βœ… DO:

  • Store credentials in environment variables or secure vaults
  • Use different credentials for different environments (dev/staging/prod)
  • Regularly rotate client credentials
  • Monitor authentication failures and unusual patterns
  • Use HTTPS for all communications

❌ DON'T:

  • Hard-code credentials in source code
  • Log sensitive data (tokens, secrets, passwords)
  • Share credentials between different applications
  • Use production credentials in development/testing

Secure Configuration

# βœ… Good: Use environment variables
client = TraylinxAuthClient()  # Reads from env vars

# βœ… Good: Use secure credential management
import os
from your_vault import get_secret

client = TraylinxAuthClient(
    client_id=os.getenv("TRAYLINX_CLIENT_ID"),
    client_secret=get_secret("traylinx_client_secret"),
    api_base_url=os.getenv("TRAYLINX_API_BASE_URL"),
    agent_user_id=os.getenv("TRAYLINX_AGENT_USER_ID")
)

# ❌ Bad: Hard-coded credentials
client = TraylinxAuthClient(
    client_id="hardcoded-id",  # Never do this!
    client_secret="hardcoded-secret"  # Never do this!
)

Network Security

  • TLS/HTTPS: All communications use HTTPS with certificate validation
  • Request Signing: Tokens provide request authenticity
  • Timeout Protection: Configurable timeouts prevent hanging requests
  • Rate Limiting: Built-in protection against rate limiting

Logging Security

import logging

# βœ… Safe logging - no sensitive data
logging.info("Authentication successful for agent %s", agent_user_id)
logging.error("Authentication failed with status %d", response.status_code)

# ❌ Unsafe logging - exposes sensitive data
logging.info("Token: %s", access_token)  # Never log tokens!
logging.debug("Secret: %s", client_secret)  # Never log secrets!

πŸ”§ Troubleshooting

Common Issues

Authentication Failures

Problem: AuthenticationError: Invalid credentials

Solutions:

  1. Verify environment variables are set correctly
  2. Check client_id and client_secret are valid
  3. Ensure API base URL is correct
  4. Verify agent_user_id is a valid UUID
# Check environment variables
echo $TRAYLINX_CLIENT_ID
echo $TRAYLINX_CLIENT_SECRET  
echo $TRAYLINX_API_BASE_URL
echo $TRAYLINX_AGENT_USER_ID

Network Issues

Problem: NetworkError: Connection failed

Solutions:

  1. Check network connectivity to API endpoint
  2. Verify firewall/proxy settings
  3. Increase timeout value
  4. Check DNS resolution
# Test connectivity
import requests
response = requests.get("https://your-api-base-url/health")
print(response.status_code)

Configuration Errors

Problem: ValidationError: Configuration validation failed

Solutions:

  1. Ensure agent_user_id is a valid UUID format
  2. Verify API base URL is a valid HTTPS URL
  3. Check all required parameters are provided
# Validate UUID format
import uuid
try:
    uuid.UUID("your-agent-user-id")
    print("Valid UUID")
except ValueError:
    print("Invalid UUID format")

Token Issues

Problem: TokenExpiredError: Token is not available

Solutions:

  1. Check if initial authentication succeeded
  2. Verify network connectivity during token refresh
  3. Check if credentials are still valid

Debug Mode

import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)

client = TraylinxAuthClient(log_level="DEBUG")
# This will show detailed request/response information

Performance Optimization

# Optimize for high-throughput scenarios
client = TraylinxAuthClient(
    timeout=60,          # Longer timeout for slow networks
    max_retries=5,       # More retries for reliability
    retry_delay=0.5,     # Faster initial retry
    cache_tokens=True    # Enable token caching
)

# Use context manager for automatic cleanup
with TraylinxAuthClient() as client:
    # Client automatically cleaned up after use
    response = client.rpc_health_check()

❓ FAQ

Q: What's the difference between access_token and agent_secret_token?

A: The access_token is used for calling Traylinx auth service endpoints, while agent_secret_token is used for agent-to-agent communication. They serve different purposes in the dual-token authentication system.

Q: How do I handle token expiration?

A: Token expiration is handled automatically. The client will refresh tokens before they expire and retry failed requests with fresh tokens.

Q: Can I use the same client instance across multiple threads?

A: Yes! The client is thread-safe and can be safely used across multiple threads. Token management is protected with locks.

Q: How do I customize retry behavior?

A: Use the max_retries and retry_delay parameters:

client = TraylinxAuthClient(
    max_retries=5,      # Retry up to 5 times
    retry_delay=2.0     # Start with 2-second delay
)

Q: What happens if the auth service is down?

A: The client will retry requests with exponential backoff. If all retries fail, it will raise a NetworkError with details about the failure.

Q: How do I validate incoming requests in my agent?

A: Use the @require_a2a_auth decorator or validate_a2a_request() function:

@app.post("/endpoint")
@require_a2a_auth
async def my_endpoint(request: Request):
    return {"status": "authenticated"}

πŸš€ Development

Setting Up Development Environment

# Clone the repository
git clone https://github.com/traylinx/traylinx-auth-client-py.git
cd traylinx-auth-client-py

# Install Poetry (if not already installed)
curl -sSL https://install.python-poetry.org | python3 -

# Install dependencies
poetry install

# Activate virtual environment
poetry shell

Running Tests

# Run all tests
poetry run pytest

# Run tests with coverage report
poetry run pytest --cov=traylinx_auth_client --cov-report=html

# Run specific test file
poetry run pytest tests/test_client.py

# Run tests with verbose output
poetry run pytest -v

# Run tests and generate coverage report
poetry run pytest --cov=traylinx_auth_client --cov-report=term-missing

Code Quality

# Format code with Black
poetry run black traylinx_auth_client/ tests/

# Lint with flake8
poetry run flake8 traylinx_auth_client/ tests/

# Type checking with mypy
poetry run mypy traylinx_auth_client/

# Security scan with bandit
poetry run bandit -r traylinx_auth_client/

Building and Publishing

# Build package
poetry build

# Check package contents
tar -tzf dist/traylinx-auth-client-*.tar.gz

# Test publish to TestPyPI
poetry config repositories.testpypi https://test.pypi.org/legacy/
poetry publish -r testpypi

# Publish to PyPI
poetry publish

Project Structure

traylinx_auth_client_py/
β”œβ”€β”€ traylinx_auth_client/
β”‚   β”œβ”€β”€ __init__.py          # Public API exports
β”‚   β”œβ”€β”€ main.py              # High-level functions and decorators
β”‚   β”œβ”€β”€ client.py            # Core TraylinxAuthClient class
β”‚   β”œβ”€β”€ config.py            # Configuration validation with Pydantic
β”‚   └── exceptions.py        # Custom exception hierarchy
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_client.py       # Client class tests
β”‚   β”œβ”€β”€ test_config.py       # Configuration validation tests
β”‚   β”œβ”€β”€ test_exceptions.py   # Exception handling tests
β”‚   └── test_main.py         # High-level function tests
β”œβ”€β”€ pyproject.toml           # Project configuration and dependencies
β”œβ”€β”€ README.md                # This file
β”œβ”€β”€ CHANGELOG.md             # Version history
β”œβ”€β”€ CONTRIBUTING.md          # Contribution guidelines
β”œβ”€β”€ SECURITY.md              # Security policy
└── LICENSE                  # MIT license

Adding New Features

  1. Create Feature Branch: git checkout -b feature/new-feature
  2. Write Tests First: Add tests in appropriate test file
  3. Implement Feature: Add implementation with proper docstrings
  4. Update Documentation: Update README and docstrings
  5. Run Quality Checks: Ensure tests pass and code quality is maintained
  6. Submit Pull Request: Include description of changes and test results

Testing Guidelines

  • Unit Tests: Test individual functions and methods
  • Integration Tests: Test end-to-end authentication flows
  • Error Tests: Test all error conditions and edge cases
  • Mock External Services: Use mocks for HTTP requests to auth service
  • Thread Safety Tests: Test concurrent access patterns

🀝 Contributing

We welcome contributions! Please see CONTRIBUTING.md for detailed guidelines.

Quick Contribution Guide

  1. Fork the repository on GitHub
  2. Clone your fork locally
  3. Create a feature branch from main
  4. Make your changes with tests
  5. Run the test suite to ensure everything works
  6. Submit a pull request with a clear description

Contribution Types

  • πŸ› Bug Fixes: Fix issues and improve reliability
  • ✨ New Features: Add new functionality
  • πŸ“š Documentation: Improve docs and examples
  • πŸ”§ Performance: Optimize performance and efficiency
  • πŸ§ͺ Tests: Add or improve test coverage
  • 🎨 Code Quality: Refactoring and code improvements

Code Standards

  • Follow PEP 8 style guidelines
  • Add type hints for all public functions
  • Write comprehensive docstrings
  • Maintain test coverage above 90%
  • Use meaningful variable and function names

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

MIT License Summary

  • βœ… Commercial use allowed
  • βœ… Modification allowed
  • βœ… Distribution allowed
  • βœ… Private use allowed
  • ❌ No warranty provided
  • ❌ No liability accepted

πŸ†˜ Support & Community

Getting Help

Reporting Issues

When reporting issues, please include:

  1. Python version and operating system
  2. Library version (pip show traylinx-auth-client)
  3. Minimal code example that reproduces the issue
  4. Full error traceback if applicable
  5. Expected vs actual behavior

Feature Requests

We welcome feature requests! Please:

  1. Check existing issues to avoid duplicates
  2. Describe the use case and problem you're solving
  3. Provide examples of how the feature would be used
  4. Consider contributing the implementation

Security Issues

For security-related issues, please follow our Security Policy:

  • πŸ”’ Private Disclosure: Email [email protected]
  • ⏱️ Response Time: We aim to respond within 24 hours
  • πŸ›‘οΈ Responsible Disclosure: We follow coordinated disclosure practices

Made with ❀️ by the Traylinx Team

GitHub stars PyPI downloads GitHub contributors

About

Enterprise-grade Python authentication client for Traylinx Sentinel API with full A2A Protocol support

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages