The Status List Server is an HTTP service that publishes and manages status lists for verifiable credential issuers and relying parties. It implements the IETF OAuth Token Status List specification.
- Standard Compliance: Implements OAuth Token Status List with JWT and CWT formats, gzip compression on JWT responses, and optional historical status resolution (
?time=). See the Compliance Matrix for detailed spec alignment. - In-Memory Local Mode: Runs with checked-in development signing material, without a database or cloud services.
- Pluggable Persistence: Supports SQL databases (PostgreSQL, MySQL, SQLite) as well as an in-memory repository for development. See Database Backends.
- Pluggable Status-List Cache: Select an in-memory or Redis cache backend at runtime for local or multi-replica deployments.
- Cloud Secret Management: Fetches server signing keys from AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault or loads them statically from local files. See Secret Backends.
- Automated Token Signing Certificates: Provisions and automatically renews X.509 token signing certificates via ACME DNS-01 challenges (Route53, Cloudflare, Google Cloud DNS, Azure DNS, ACME-DNS, Pebble), or loads certificates statically from local files. See DNS Providers.
- Cloud-Native Observability: OpenTelemetry distributed tracing (OTLP gRPC), Prometheus metrics, structured JSON logging, and Kubernetes health probes. See Observability.
- Hardened Security: JWT-based issuer authentication, tiered token-bucket rate limiting, request body size enforcement, and container image supply chain verification (SBOM and SLSA provenance).
Run the server locally with in-memory storage and the checked-in development signing certificate and key:
git clone https://github.com/adorsys/status-list-server.git
cd status-list-server
APP_SERVER__CERT__STORE__CERTIFICATE_PATH=test_data/certs/dev.crt \
APP_SERVER__CERT__STORE__SIGNING_KEY_PATH=test_data/certs/dev.key \
cargo runThese files are public test fixtures for local development only.
The server binds to http://localhost:8000 with no database or cloud configuration required.
Verify that the service is running:
curl -i http://localhost:8000/health/liveStart the server with in-memory storage and the checked-in local test certificate. Profiles start optional services beside the server; using one from the application also requires its matching build feature and configuration:
docker compose up --build # Server only
docker compose --profile postgres up -d # Server + PostgreSQL
docker compose --profile mysql up -d # Server + MySQL
docker compose --profile redis up -d # Server + Redis
APP_TELEMETRY__ENABLED=true \
docker compose --profile observability up -d # Server + telemetry stackSet GRAFANA_ADMIN_PASSWORD before starting the observability profile. To use PostgreSQL, ACME, AWS, and telemetry in the server, select those profiles and their matching application settings. The compiled database feature selects the default database backend:
FEATURES=postgres,aws APP_TELEMETRY__ENABLED=true \
docker compose -f docker-compose.yml -f compose/postgres.yml \
--profile postgres --profile acme --profile aws \
--profile observability up -d --buildThe aws feature includes ACME certificate provisioning, so local AWS builds need both the aws and acme profiles.
See the Local Deployment Guide for all profiles, including MySQL and filesystem certificates.
The server exposes endpoints for authenticated issuer status-list publishing and updates, public status list resolution, and list aggregation. Issuers are provisioned through the operator-managed registry; see the issuer migration guide.
Relying parties retrieve status list tokens using the following endpoint:
GET /api/v1/status-lists/{list_id}curl -i http://localhost:8000/api/v1/status-lists/477121aa-b598-419e-916f-1e74654ff38b \
-H "Accept: application/statuslist+jwt" \
-H "Accept-Encoding: gzip"Accept: Requested token representation:application/statuslist+jwt(default): Signed JWT containing the base64url-encoded status list bitstring.application/statuslist+cwt: COSE_Sign1 signed binary CWT token.
Accept-Encoding: gzip: Compresses JWT responses using gzip. CWT tokens are binary and not gzip-compressed.?time=<unix-timestamp>: Optional query parameter for historical status resolution.
The complete OpenAPI 3.1 REST API specification is available at OpenAPI Specification.
The server compiles with modular feature flags to gate database drivers and cloud secret providers:
| Feature | Description | Default |
|---|---|---|
memory |
In-memory repository storage, in-process cache, and file certificates | ✅ Default |
postgres |
PostgreSQL database driver and migration runner | ❌ Opt-in |
sqlite |
SQLite database driver and migration runner | ❌ Opt-in |
mysql |
MySQL database driver and migration runner | ❌ Opt-in |
aws |
AWS Secrets Manager and Route53 DNS provider | ❌ Opt-in |
gcp |
GCP Secret Manager and Google Cloud DNS provider | ❌ Opt-in |
azure |
Azure Key Vault and Azure DNS provider | ❌ Opt-in |
vault |
HashiCorp Vault / OpenBao secret backend | ❌ Opt-in |
redis |
Redis status-list cache backend | ❌ Opt-in |
Examples:
# Build with PostgreSQL support and filesystem key + certificate chain loading
cargo run --features postgres
# Build with PostgreSQL and AWS integration
cargo run --features postgres,awsThe server reads configuration from environment variables (or an optional .env file in the working directory):
- Prefix: All application settings are prefixed with
APP_. - Hierarchy: Nested settings use a double underscore (
__) as a delimiter. For example,APP_SERVER__PORT=8000sets the server port, andAPP_DATABASE__BACKEND=postgresselects the database driver. - Defaults: The default database backend is in-memory. Native runs must configure a signing certificate and key, as shown in the quick start.
Refer to .env.template for the complete configuration dictionary, data types, and default values. For backend-specific configuration, see Database Backends, Secret Backends, and DNS Providers.
For production deployments:
- Kubernetes: Refer to the Helm Chart Guide for deploying with the official Helm chart, configuring Workload Identity (if you use AWS, GCP or Azure), and setting resource limits.
- Operations and Runbooks: Refer to the Deployment Runbook for production checklists, database migrations, backup and restore procedures, and zero-downtime maintenance.
- Troubleshooting: Refer to the Troubleshooting Guide for fail-fast error descriptions and common operator error codes.
- Container Supply Chain: Official container images are published with SBOMs and SLSA provenance, and scanned for vulnerabilities by digest. See the Supply Chain Guide.
- Architecture Guide: Project organization and modularity, service container composition, and token signing workflows.
- Compliance Matrix: Implementation status against OAuth Token Status List draft-21 requirements.
- OpenAPI Specification: Complete REST API contract, request schemas, and error codes.
- Database Backends: PostgreSQL, MySQL, and SQLite connection pooling, drivers, and isolation levels.
- Secret Backends: Storing and rotating token-signing keys with Vault, AWS Secrets Manager, GCP Secret Manager, and Azure Key Vault.
- DNS Providers: Configuring ACME DNS-01 challenge solvers for automated certificate issuance.
- Helm Chart Guide: Kubernetes packaging, pod autoscaling, ingress, and Workload Identity configuration.
- Deployment Runbook: Production operational procedures, migrations, and disaster recovery.
- Troubleshooting Guide: Diagnosing runtime failures and common operator errors.
- Observability Guide: OpenTelemetry collector setup, Prometheus metrics, and distributed tracing.
- Container Supply Chain: Image provenance, SBOM verification, and vulnerability triage.
The repository provides a standard Cargo xtask entry point for common workflows:
cargo xtask check-profiles
cargo xtask build # defaults to postgres
cargo xtask build --profile sqlite --release
cargo xtask test --profile minimal
cargo xtask test --profile sqlite -- my_test --exact
cargo xtask lint
cargo xtask compose --profile redis
cargo xtask cibuild, test, and compose accept --profile <name>. The supported profiles and their Cargo features are:
| Profile | Cargo feature selection | Compose services |
|---|---|---|
minimal |
--no-default-features --features memory |
app only |
postgres |
postgres |
app and PostgreSQL |
mysql |
mysql |
app and MySQL |
sqlite |
sqlite |
app and SQLite volume initialization |
aws |
postgres,aws |
app, PostgreSQL, and AWS |
vault |
postgres,vault |
app and PostgreSQL |
gcp |
postgres,gcp |
app and PostgreSQL |
azure |
postgres,azure |
app and PostgreSQL |
redis |
postgres,redis |
app, PostgreSQL, and Redis |
Vault, GCP, and Azure use externally configured provider endpoints and credentials, so those profiles do not start provider emulators. Configure them in .env before starting the profile.
check-profiles checks each library with --no-default-features and the listed features to detect dependence on other default features. It also checks all supported targets with the normal profile selection. Non-minimal builds and tests retain the default memory feature, which the binary and existing test helpers require. Every check runs, and failures are summarized at the end. The required CI profile-check job and the full local CI pipeline run these checks. Default local CI retains the quick memory-only check; run ./local-ci.sh --gate profiles to check the full matrix separately.
test adds postgres-tests to every PostgreSQL-backed profile and also adds
redis-tests to the Redis profile. These profiles and MySQL require a running
Docker daemon for their container tests. minimal and SQLite tests need no
database containers. Cloud integration tests may require additional provider
configuration; see the contributing guide.
test uses installed cargo-nextest with the repository's test groups and timeouts, then runs doctests separately. If nextest is absent, it uses cargo test; that fallback has no nextest timeouts or process isolation.
A failing nextest run does not trigger a fallback. Arguments after -- are passed to the selected runner and doctests; use options supported by both. For the same nextest version as CI, run cargo install --locked cargo-nextest --version 0.9.101.
lint runs formatting, Clippy for all targets and features, cargo audit, and
cargo machete, then summarizes all failures. Install its tools first:
rustup component add rustfmt clippy
cargo install --locked cargo-audit --version 0.22.2
cargo install --locked cargo-machete --version 0.9.2compose selects the PostgreSQL, MySQL, SQLite, or Redis override file when needed. MySQL uses MYSQL_USER, MYSQL_PASSWORD, and MYSQL_DATABASE from the shell or .env for both the database service and application. SQLite stores its database in the sqlitedata named volume, preserving lists across container restarts; down --volumes deletes that data. Plain Compose reads runtime values from .env. The overrides can also be used directly:
docker compose -f docker-compose.yml -f compose/postgres.yml --profile postgres up -d --build
docker compose -f docker-compose.yml -f compose/mysql.yml --profile mysql up -d --build
docker compose -f docker-compose.yml -f compose/sqlite.yml up -d --buildThese local overrides select their connection mode. Remove incompatible
APP_DATABASE__URL or APP_DATABASE__PASSWORD_FILE entries from .env before using the PostgreSQL or MySQL override, and password-file entries before using SQLite.
ci delegates to the full local-ci.sh pipeline.
You can still invoke individual Cargo commands directly. For example, run unit and integration tests or verify the zero-infrastructure in-memory build with:
cargo test
cargo check --no-default-features --features memoryRun the daily local CI checks (formatting, builds, Clippy, tests, and documentation):
./local-ci.sh
# Add security, configuration, container, and coverage gates:
./local-ci.sh --fullMissing tools are bootstrapped locally. See Local CI for prerequisites, the complete command inventory, and verification instructions.
Run markdown linting:
npx --yes markdownlint-cli2 README.mdThis project uses release-plz with Conventional Commits to automate semantic versioning and changelog generation. See Changelog for release notes.
Contributions are welcome. Please read the Contributing Guide and review the Architecture Guide before submitting pull requests.
Licensed under either of Apache License, Version 2.0 or MIT License at your option.