Skip to main content

speedle

Python SDK for Speedle authorization checks: is-allowed against Speedle Cloud and self-hosted Speedle+. Python 3.10 or later, sync and asyncio clients, fully typed. The only runtime dependency is httpx. The behaviour follows docs/design.md.

Not published yet. Version 0.1.0 is in development.

Install

pip install speedle

Quickstart: Speedle Cloud

import datetime
import os

from speedle import Attribute, Auth, Client

with Client(
    backend="speedle-cloud",
    endpoint="https://cloud.speedle.io",
    auth=Auth.bearer(os.environ["SPEEDLE_TOKEN"]),
    service_name="books",  # the token's service
) as speedle:
    if speedle.is_allowed(
        "alice",
        "get",
        "/books/123",
        [
            Attribute.string("team", "eng"),
            Attribute.numeric("clearance", 4),
            Attribute.datetime("issued_at", datetime.datetime(2026, 11, 5, 3, tzinfo=datetime.timezone.utc)),
        ],
    ):
        ...

Quickstart: Speedle+ with asyncio

from speedle import AsyncClient, Auth

async with AsyncClient(
    backend="speedle-plus",
    endpoint="https://ads.internal:6734",
    auth=Auth.none(),  # or Auth.mutual_tls("client.pem", "client.key") with --force-client-cert
    ca_file="ca.pem",  # extra trust anchor for a private CA
    service_name="books",
) as speedle:
    decision = await speedle.check("alice", "get", "/books/123", {"team": "eng", "clearance": 4})
    # Decision(allowed=False, reason=<Reason.NO_APPLICABLE_POLICIES: 3>, ...)

http:// is accepted only for speedle-plus with Auth.none(), and only for loopback hosts unless you pass allow_insecure_http=True. Speedle+ warns that an unauthenticated plaintext endpoint lets anyone on the network ask for decisions; prefer HTTPS.

API

  • Client(...) and AsyncClient(...) take the same keyword arguments. Create one per endpoint and share it; it is thread-safe and owns one pooled httpx client. Use it as a context manager, or call close() / aclose().
  • is_allowed(subject, action, resource, attributes=None, *, deadline=None, service_name=None) returns the server's allowed value.
  • check(...) returns a Decision: allowed, reason (a Reason, or an unknown integer as is), error_message (Speedle+ evaluator errors) and quota_daily_remaining (Speedle Cloud).
  • subject is a user name or a list of Principal(name, type="user", idd=None) (PrincipalType has the Speedle+ values).
  • attributes is either a list built with Attribute.string, Attribute.numeric, Attribute.boolean (type bool) and Attribute.datetime (each takes one value or a list), or a mapping whose types are inferred: str, int/float, bool (checked before int), time-zone-aware datetime, or a non-empty list of one of them. A str is always a string, even if it looks like a date. Inferred attributes are sent sorted by name. Invalid values (empty or duplicate names, None, NaN, infinities, bool as a number, naive datetimes, mixed or empty inferred lists) raise InvalidRequestError before any request. Numbers above 2^53 lose precision, because Speedle+ decodes numbers as float64.
  • service_name= overrides the client's service for one call. On Speedle Cloud a service other than the token's fails with ForbiddenError (code service_mismatch); that call is charged.
  • deadline= replaces the client's deadline (seconds) for one call.
  • AsyncClient honours task cancellation and asyncio.timeout(), also during a retry delay; asyncio.CancelledError is re-raised in every failure mode.

Reason.DISCOVER_MODE (5) returns allowed=True but is not a production grant.

Retries and deadlines

RetryPolicy field (seconds) Default
max_attempts (counts the first; 1 disables retries) 3
base_delay 0.1
max_delay 2.0
attempt_timeout 2.0
deadline (the whole call) 5.0

Backoff is exponential with full jitter, raised to Retry-After when the server sends one. Retried: connection errors, attempt timeouts, 502, 503 and 504, and a burst 429 whose Retry-After fits the remaining deadline. Never retried: 400, 401, 403, 404, the daily-quota 429, 500 and other 5xx, 413, 415, TLS failures and unexpected bodies. Speedle Cloud charges every call that reaches its handler, including a retried snapshot_unavailable 503, so a call costs at most max_attempts units.

In the sync client, attempt_timeout bounds each phase of an attempt (connect, write and each read), because httpx has no single total timeout for blocking requests. The async client bounds the whole attempt.

Errors

Every error extends SpeedleError and carries status, code (Speedle Cloud error code), message and quota_daily_remaining. The types are ConfigurationError, InvalidRequestError, UnauthorizedError, ForbiddenError, RequestTooLargeError, TooManyRequestsError (with retry_after in seconds; subtypes RateLimitedError and QuotaExceededError), ServiceUnavailableError, ServerError, HttpError, UnexpectedResponseError, NetworkError (subtype speedle.TimeoutError, whose subtype is DeadlineExceededError) and CircuitOpenError. speedle.TimeoutError is the SDK's own class, not the built-in.

Failure mode

failure_mode="closed" makes is_allowed return False instead of raising any SDK error, including CircuitOpenError and validation errors; on_give_up still reports the error. check always raises. Constructor errors and cancellation are never converted. There is no fail-open mode: is_allowed returns True only for a 200 response whose allowed is true.

Circuit breaker

Off by default. circuit_breaker=CircuitBreaker(failure_threshold=5, cool_down=30.0) opens after that many consecutive failed calls (network errors, timeouts and 5xx), fails fast with CircuitOpenError during the cool-down, then lets one trial call through.

Hooks

hooks=Hooks(on_attempt=..., on_retry=..., on_give_up=..., on_breaker_state_change=...) are called synchronously; exceptions and return values are ignored. Payloads never contain the token, headers, subject, action, resource or attributes. The SDK sends no telemetry and does no logging; it sends only the is-allowed request, with User-Agent: speedle-sdk-python/<version> (python/<version>; <os>) plus user_agent_suffix. Proxy, netrc and certificate settings from environment variables are not used.

Security

  • The Speedle Cloud token is a server-side secret. Never ship it to browsers, mobile apps or desktop clients.
  • Auth.bearer requires HTTPS. The token is redacted from repr, hook payloads and error messages, and Auth cannot be pickled.
  • Redirects are never followed. TLS verification cannot be disabled.
  • Take subjects and attributes from your own authenticated context, never from untrusted client input.
  • Decisions are never cached.

Development

uv sync
uv run ruff check && uv run ruff format --check && uv run mypy
uv run pytest tests --ignore=tests/conformance  # unit tests
uv run pytest tests/conformance                 # every vector in ../conformance/vectors

License

UPL-1.0. Copyright (c) 2026 The Speedle Authors.

Metadata

Release files for speedle 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for speedle 0.1.0
File Size Uploaded Provenance Actions
speedle-0.1.0.tar.gz 18.8 kB With provenance Details for speedle-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for speedle 0.1.0
File Interpreter ABI Platform Actions
speedle-0.1.0-py3-none-any.whl Python 3 none any Details for speedle-0.1.0-py3-none-any.whl

Total release size: 41.7 kB

Release files / speedle-0.1.0.tar.gz

Download URL speedle-0.1.0.tar.gz
Size 18.8 kB
Tags Source
SHA-256 checksum
How to use checksums
99734038f3e962b4fdd64160f5bee646e2b97b1d4602d37342cade400d066ba9
BLAKE2b-256 checksum
How to use checksums
a2f5c29cb2a01012dc0c0a1c8bd00e92447557d4810c6837df6b6620ed3f8f93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / speedle-0.1.0-py3-none-any.whl

Download URL speedle-0.1.0-py3-none-any.whl
Size 22.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
faf2833eb97f9901fa404389f9d83fd9eb036c76d4dd86fa48c37862d6b8560e
BLAKE2b-256 checksum
How to use checksums
14ceb15969c10b73e9a453980693d90f308cd0c7c5a40f5e9ee0d7efba111fa1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Security for speedle 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for speedle-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page