Status lists
Two encodings behind one interface — W3C Bitstring and IETF Token Status List — plus the issuer-side builders.
Checking
openvc.status.status_list
openvc.status.status_list — check a credential's credentialStatus against a
Bitstring Status List credential.
Transport- and proof-agnostic by design: the caller injects
resolve_status_list — a function that fetches the status-list credential URL
and returns the verified status-list VC as a dict (its signature is the
caller's concern, since the proof format and the SSRF policy for that host are
too). This module then parses the entry, decodes the bitstring, and reads the
bit. So it stays pure stdlib and reusable by any VC profile (OB 3.0, EBSI, EUDI).
Supports BitstringStatusListEntry and the older StatusList2021Entry —
same field names, same bit encoding.
CredentialRevoked
Bases: OpenvcError
Raised by verifiers that treat a set revocation bit as a hard failure.
Source code in src/openvc/status/status_list.py
35 36 | |
CredentialSuspended
Bases: OpenvcError
Raised by verifiers that treat a set suspension bit as a hard failure (a suspended credential is temporarily invalid — not currently usable).
Source code in src/openvc/status/status_list.py
39 40 41 | |
parse_status_entries(credential)
Parse the credential's credentialStatus into typed entries. Entries
whose type is not a recognised status-list entry are skipped (a credential
may carry unrelated status types); a member that is not an object at all (an
array, a string reference, null) or an object with no type raises
:class:~openvc.status.bitstring.StatusListError instead, since its entries
could not be read.
Source code in src/openvc/status/status_list.py
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
check_credential_status(credential, *, resolve_status_list)
Resolve each status-list credential the credential references and read its
bit. Returns a :class:StatusResult; never raises on a set bit (that is a
verifier policy decision) — only on malformed data or a resolve failure.
Source code in src/openvc/status/status_list.py
171 172 173 174 175 176 177 178 179 180 | |
check_credential_status_async(credential, *, resolve_status_list)
async
Async :func:check_credential_status — awaits an async resolve_status_list;
identical decoding, tally, and fail-closed semantics (the bit-reading is the same
pure code).
Source code in src/openvc/status/status_list.py
183 184 185 186 187 188 189 190 191 192 | |
openvc.status.token_status_list
openvc.status.token_status_list — IETF Token Status List
(draft-ietf-oauth-status-list-21; IESG-approved and in the RFC Editor queue as of
2026-07, intended Proposed Standard — no RFC number yet). The codec is pinned
byte-for-byte to the draft §4.1 examples in tests/test_conformance_status_list.
The second status-list encoding, alongside the W3C Bitstring list in
openvc.status.bitstring. The differences that matter:
- Multi-bit statuses. Each referenced token gets
bitsin {1, 2, 4, 8}, so a status is a value (0-255, constrained bybits), not just a set/clear bit.0x00= VALID,0x01= INVALID (revoked),0x02= SUSPENDED; the rest are application-specific. - LSB-first packing. Index 0 occupies the lowest
bitsbits of byte 0 (the W3C list is MSB-first); index 1 the nextbitsup, and so on. - DEFLATE/zlib compression (the W3C list uses gzip).
A referenced token points at a status list with a status claim
{"status_list": {"idx": N, "uri": "..."}}; the status list token at that URI
carries {"status_list": {"bits": B, "lst": "<base64url zlib>"}}. As with the
W3C flow, resolving and verifying that token (its proof and the SSRF policy for
its host) is the caller's concern — injected as resolve_status_list_token —
so this module stays pure stdlib and proof-agnostic.
decode_status_list(lst)
base64url-decode then zlib-inflate a lst value into the packed bytes.
Source code in src/openvc/status/token_status_list.py
60 61 62 63 64 65 66 67 68 69 70 71 | |
encode_status_list(data)
zlib-deflate then base64url (unpadded) — the inverse of
:func:decode_status_list, for issuers and tests. zlib output is
deterministic for a fixed level, so no mtime dance is needed.
Source code in src/openvc/status/token_status_list.py
74 75 76 77 78 | |
new_status_list(size, *, bits=1)
A zeroed (all-VALID) packed list holding at least size statuses of bits each.
size is an int (never a bool or float), and the packed list may not
exceed the 16 MiB openvc decodes: at most
:data:~openvc.status._index.MAX_STATUS_INDEX statuses at 1 bit each, an eighth of
that at 8 bits. Otherwise :class:StatusListError.
Source code in src/openvc/status/token_status_list.py
81 82 83 84 85 86 87 88 89 90 | |
get_status(data, index, *, bits=1)
Return the status value at index for a list packed bits per status
(LSB-first). Raises :class:StatusListError for a bad bits, an index that is not
an int (a bool or float is refused, not read as some other status) or an
out-of-range one.
Source code in src/openvc/status/token_status_list.py
93 94 95 96 97 98 99 100 101 102 103 | |
set_status(data, index, value, *, bits=1)
Set the status value at index in-place (LSB-first). For issuers and
tests. index is held to the same rule as :func:get_status and value must be an
int (a bool is read as 0 or 1); raises if value does not fit in bits.
A bad index type or a negative one is reported first, then value, then an
index past the end of data.
Source code in src/openvc/status/token_status_list.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
parse_token_status_ref(claims)
Parse a referenced token's status.status_list reference, or None if
the token carries no status-list reference. Raises on a malformed reference.
Source code in src/openvc/status/token_status_list.py
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
check_token_status(claims, *, resolve_status_list_token)
Resolve the status list token a referenced token points at and read its status.
Returns None if the token carries no status-list reference. Never raises
on a non-VALID status — turning INVALID/SUSPENDED into a hard failure is the
verifier's policy — only on malformed data or a resolve failure.
Source code in src/openvc/status/token_status_list.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
check_token_status_async(claims, *, resolve_status_list_token)
async
Async :func:check_token_status — awaits an async resolve_status_list_token;
identical decoding and fail-closed semantics (the status-reading is the same
pure code).
Source code in src/openvc/status/token_status_list.py
225 226 227 228 229 230 231 232 233 234 235 236 | |
Issuing
openvc.status.issue
openvc.status.issue — issuer-side status-list construction.
The check side (:func:~openvc.status.status_list.check_credential_status,
:func:~openvc.status.token_status_list.check_token_status) reads a status
list; this is the other half — building the artifacts an issuer publishes and
updates in order to revoke:
- :func:
build_status_list_credential— a W3C BitstringStatusListCredential (the VC that wraps anencodedList), returned UNSIGNED so the caller secures it with whichever proof suite it already uses (VcJwtProofSuite.signorDataIntegrityProofSuite.add_proof): the status list is an ordinary VC. - :func:
build_status_list_token/ :func:verify_status_list_token— an IETF status-list token (typ: statuslist+jwt), signed and verified through the shared JOSE path (allow-listed{ES256, ES384, EdDSA, Ed25519}). - :func:
build_status_list_entry/ :func:build_token_status_reference— the tiny pointer an issuer embeds in each issued credential/token so a verifier knows which list bit to read.
A revocation flow: allocate a list (:func:~openvc.status.bitstring.new_bitstring
or :func:~openvc.status.token_status_list.new_status_list), set the revoked
indices (set_status_bit / set_status), build + sign the artifact, serve it
at the URL the credentials point at, and re-issue it when a revocation changes.
The builders hold the pointer and the list to the rules the verifier applies, so openvc
never mints one that its own check side then refuses: an index follows
:func:~openvc.status._index.status_index (an int, never a bool or float,
below MAX_STATUS_INDEX), the pointer strings are non-empty strings, and a list is
a bytes, bytearray, memoryview or array.array (wrap any other buffer in
memoryview()) of at most the 16 MiB the verifier inflates. Anything else is a
:class:~openvc.status.bitstring.StatusListError, raised at build time.
The time inputs and ttl follow the verifier's shape rules too. valid_from and
valid_until are a datetime or None; issued_at and expires are a
datetime or a finite number of epoch seconds (the NumericDate rule
:func:~openvc.proof._verify_common.is_numeric_date, so never a bool, a digit
string, NaN or a bignum). A datetime is read the one way every openvc clock
check reads it: a naive value is UTC, never the host's local time, and a value with
no UTC equivalent is refused. ttl is None or a positive int, never a bool.
The ordering of a window (expires before issued_at, a past valid_until) is the
verifier's call at read time and is not checked here.
The strings an artefact names are held to what the verifier reads too, so that the
proof lane you sign with does not decide whether they mattered. The credential's issuer is
a non-empty str, or an object whose id is a non-empty str and which carries no
@id (id is the one spelling every lane reads the same; the object's other members
are the caller's and are not inspected). subject_id, an entry's id and the token's
issuer are None (the default) or a non-empty str: None is the only way to ask
for the default (a subject of <id>#list, no entry id, no iss), and an empty or
falsy value is an error. contexts is None (the VC 2.0 context) or a non-empty list
or tuple whose first entry is a VC base context (https://www.w3.org/ns/credentials/v2
or https://www.w3.org/2018/credentials/v1) and whose other entries are a non-empty
str or an object. An identifier's URI shape is not checked: key resolution refuses an
issuer it cannot resolve, and only the RDF suites require an IRI. The first-entry rule is
a shape rule, the one the RDF suites apply, not a promise that the list verifies on every
lane: only the VC 2.0 context defines the terms of a BitstringStatusListCredential and
only it is bundled with openvc (see :func:build_status_list_credential). Every string
the builders take is copied to an exact str before it is tested, and the copy is what
is emitted (:func:~openvc.status._index.plain_str). The members of an issuer or
inline context object besides the ones named here are the caller's, with two exceptions,
both rules of the VC-JWT lane that reads the list back. None of them, at any depth, may be
an SD-JWT marker (a member named _sd, _sd_alg or ...): the lane reads a payload
that carries one as an SD-JWT issuer JWT and refuses it (#189, #291). And the object may not
nest past MAX_DEPTH - 2 levels (issuer) or MAX_DEPTH - 3 levels (an inline
context object), the object itself counting as level 1: the lane decodes the payload
through the bounded loader, which refuses nesting past MAX_DEPTH (100, #213) in the
whole payload, and the object sits two or three containers inside it. A builder cannot know
which lane will secure the list, so such an object is refused at build time on every lane
(:func:_refuse_unreadable, which runs the lane's own test on the JSON the object encodes
to; eddsa-jcs-2022 would take one more level in each field, and the builder holds it to
the VC-JWT limit all the same). The marker as a value ({"name": "..."}) is fine: only
member names are read.
This is the only :mod:openvc.status module that touches :mod:openvc.proof (to
sign/verify the token); the codecs and the check side stay pure stdlib.
build_status_list_credential(*, id, issuer, bitstring, status_purpose='revocation', valid_from=None, valid_until=None, subject_id=None, ttl=None, contexts=None)
Build an UNSIGNED W3C BitstringStatusListCredential wrapping bitstring.
id is the URL a credential's statusListCredential points at; bitstring
is the raw bits (from :func:~openvc.status.bitstring.new_bitstring +
set_status_bit). status_purpose must match the entries that reference this
list. The result is a plain VC — sign it with any suite before publishing.
The inputs are not mutated.
bitstring is a bytes, bytearray, memoryview or array.array (wrap
any other buffer in memoryview()); it contributes the bytes it exposes
(view.tobytes()), so a non-contiguous memoryview is read as it shows.
valid_from and valid_until are a datetime or None, written as a UTC
...Z string. A naive datetime is UTC, as on every openvc clock check, not
the host's local time; an aware one is converted. ttl is None or a positive
int (the W3C list gives it in milliseconds).
issuer is a non-empty string (a DID, say) or an object with a non-empty string
id and no @id; other members of the object (name) are carried as given, but
none, at any depth, may be named _sd, _sd_alg or ... (the SD-JWT markers: the
VC-JWT lane refuses a payload that holds one, so the list would be signed and then not
read back), and the object may not nest past 98 levels (MAX_DEPTH - 2, the object
itself being level 1: the bounded loader that reads the list back stops at 100 levels
of the whole payload, and the issuer sits two containers inside it).
subject_id is the credentialSubject.id: None gives <id>#list, and an explicit
value is a non-empty string. contexts is the @context: None gives
["https://www.w3.org/ns/credentials/v2"], and an explicit value is a non-empty list
or tuple that starts with a VC base context, followed by context URLs or inline context
objects (whose members are not inspected, except for the same marker names and a nesting
past 97 levels, MAX_DEPTH - 3: one that is not JSON fails when the credential is
signed). The limits are the VC-JWT lane's; eddsa-jcs-2022 takes one more level in each
field, which the builder, not knowing the lane, does not use. Pass the VC 2.0 context first
unless you have a reason: it is the one that defines BitstringStatusListCredential,
encodedList and statusPurpose, and the only one bundled. The VC 1.1 context is
accepted as a base context (the shape the RDF suites accept) and builds; VC-JWT and
eddsa-jcs-2022 read no context, while eddsa-rdfc-2022 refuses it with
DocumentLoaderError (it is not bundled, and it does not define those terms). A context
URL that is not bundled needs extra_contexts on the eddsa-rdfc-2022 suite.
Raises :class:~openvc.status.bitstring.StatusListError for an id or
status_purpose that is not a non-empty string, for an issuer that is not a
non-empty string or an object whose id is one and which has no @id, for an
issuer object or an inline context object that carries an SD-JWT marker member (_sd,
_sd_alg, ...) at any depth, that is nested past the loader's cap (more than 98
levels for the issuer, 97 for a context object) or that cannot be read as JSON (a cycle, a
key that is no scalar), for a subject_id that is neither None nor a non-empty string
("", 0, [] and {} are errors, not the default), for contexts that is
neither None nor a non-empty list / tuple of that shape (a str, a dict,
an iterator, an empty list, a first entry that is not a VC base context, an entry that is
not a non-empty string or an object), for a bitstring that is not a buffer or is longer
than the 16 MiB the verifier inflates, for a valid_from / valid_until that is not a
datetime (a string, an epoch number, a date), has a tzinfo that raises or has
no UTC equivalent (year 1 at +01:00), and for a ttl that is a bool, a float
(NaN included), a string, zero, negative or an integer no float holds.
Source code in src/openvc/status/issue.py
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | |
build_status_list_entry(*, status_list_credential, index, status_purpose='revocation', id=None)
Build a BitstringStatusListEntry for a credential's credentialStatus.
Add the return value to each credential you issue; toggling the same index in
the published list (:func:build_status_list_credential) then flips that
credential's status. status_purpose must match the list's.
index is an int below :data:~openvc.status._index.MAX_STATUS_INDEX — the
verifier's own rule, so it reads back exactly what you wrote; the entry carries it
as the base-10 string the spec asks for. A bool, a float (NaN
included), a string, a negative or an oversized index, or a status_list_credential
/ status_purpose that is not a non-empty string, raises
:class:~openvc.status.bitstring.StatusListError.
id is the entry's own identifier: None (the default) leaves it out, and an
explicit value is a non-empty string ("", 0 and [] raise, they are not
"absent"). Nothing reads it back, so it is not checked for a URI shape.
Source code in src/openvc/status/issue.py
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | |
build_status_list_token(*, signing_key, uri, status_list, bits=1, issued_at=None, expires=None, ttl=None, issuer=None)
Build and sign an IETF status-list token (typ: statuslist+jwt).
uri (the sub claim, the list's own URL) is what a referenced token's
status.status_list.uri points at; status_list is the packed multi-bit
list (from :func:~openvc.status.token_status_list.new_status_list +
set_status). Signed via the allow-listed {ES256, ES384, EdDSA, Ed25519} path, so an
HSM/Vault key works.
issued_at (iat, default the current time) and expires (exp, default
none) take a datetime or a finite number of epoch seconds, such as
time.time(), truncated to whole seconds. A naive datetime is UTC, as on
every openvc clock check, not the host's local time. ttl is None or a positive
int of seconds.
issuer (iss) is None or a non-empty string, which is what
:func:~openvc.resolvers.default_status_list_token_resolver needs to find the key.
None is allowed and leaves the claim out, but a token without iss is refused
by that resolver (StatusListError): pass it unless the caller resolves the key
some other way.
status_list is a bytes, bytearray, memoryview or array.array (wrap
any other buffer in memoryview()), read as in
:func:build_status_list_credential. Raises
:class:~openvc.status.bitstring.StatusListError for a uri or an issuer that is
not a non-empty string (None aside, for issuer), a bad bits, a status_list
that is not a buffer or is longer than the 16 MiB the verifier inflates, an
issued_at / expires that is neither a datetime nor a finite number (a bool,
a string, a date, NaN, inf, an integer no float holds), a datetime
whose tzinfo raises or that has no UTC equivalent (year 1 at +01:00, as for
valid_from), and a ttl that is a bool, a float (NaN included), a
string, zero, negative or an integer no float holds. Every input is checked before
anything is signed.
Source code in src/openvc/status/issue.py
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | |
verify_status_list_token(token, *, public_key_jwk, expected_uri=None, leeway_s=60, now=None)
Verify a status-list token and return its claims.
Allow-lists the algorithm, requires typ: statuslist+jwt, verifies the
signature, checks exp / nbf / iat (finite numbers when present, null
included; within leeway_s of now), and — when expected_uri is
given — that sub equals the URL it was fetched from (the IETF anti-swap
check). The returned dict carries the status_list member, so it can be
handed straight to :func:~openvc.status.token_status_list.check_token_status
as the resolver's result.
leeway_s is a whole number of seconds from 0 to one day (86 400); anything else
is a :class:~openvc.status.bitstring.StatusListError, raised before the token
is read.
Source code in src/openvc/status/issue.py
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | |
build_token_status_reference(*, uri, index)
Build the status claim a referenced token carries to point at an IETF
status-list token — merge it into the token's claims when you issue it.
index follows the same rule as :func:build_status_list_entry, and the IETF
draft makes it a JSON integer, so a string is refused too; uri must be a non-empty
string. :class:~openvc.status.bitstring.StatusListError otherwise.
Source code in src/openvc/status/issue.py
643 644 645 646 647 648 649 650 651 652 | |
Resolver factories
The batteries-included status-list resolvers the pipeline accepts (and their async twins), which fetch and verify a referenced status list before reading its bits.
openvc.resolvers
openvc.resolvers — blessed, SSRF-guarded default resolvers for the status and schema fetch paths.
:func:~openvc.verify.verify_credential's resolve_status_list,
resolve_status_list_token and resolve_credential_schema are caller-injected:
the transport, the SSRF policy for each issuer-named host, and — for status — the
proof verification of the fetched list are the caller's concern, so
openvc.fetch's guard protects these URLs only if you pass a guarded fetch. That
makes the secure path the opt-in path.
These factories are the safe drop-in that makes the secure path the easy path:
they fetch through the SSRF-guarded https fetch (openvc.fetch: https-only,
private/loopback/link-local blocked, redirects refused, connection pinned to the
validated IP) and — for status — verify the fetched status list through the
pipeline before trusting it. Pass one of these to verify_credential; a custom
resolver deliberately opts out of the guard.
from openvc import verify_credential
from openvc.resolvers import (default_status_list_resolver,
default_credential_schema_resolver)
verify_credential(
cred, resolver=reg,
resolve_status_list=default_status_list_resolver(resolver=reg),
resolve_credential_schema=default_credential_schema_resolver())
Caching for high-volume verification. A default status resolver fetches and
re-verifies the status list on every call — a batch of N credentials from one issuer
would otherwise download and verify one shared list N times. :func:openvc.verify.verify_many
(and its async twin) already deduplicate this within a call via
:func:openvc.cache.batch_resolvers (each distinct issuer / status list resolved once). For
repeated single verify_credential calls in a long-lived verifier, wrap your resolvers
with :func:openvc.cache.cached_resolve (a short-TTL memo) and your DID resolver with
:class:openvc.cache.CachingDidResolver, so a hot status list / DID document is not refetched
per credential.
default_credential_schema_resolver(*, fetch=https_bytes_fetch)
A resolve_credential_schema that fetches the raw schema bytes over the
SSRF-guarded https fetch. Returning bytes lets the pipeline verify a
credentialSchema.digestSRI over the exact response before parsing.
Source code in src/openvc/resolvers.py
62 63 64 65 66 67 68 69 70 | |
default_type_metadata_resolver(*, fetch=https_bytes_fetch)
A resolve for :func:openvc.type_metadata.validate_type_metadata that
fetches the raw Type Metadata bytes from a vct / extends URL over the
SSRF-guarded https fetch. Returning the exact bytes lets vct#integrity /
extends#integrity be verified over the response before parsing.
Source code in src/openvc/resolvers.py
73 74 75 76 77 78 79 80 81 82 | |
default_status_list_resolver(*, resolver=None, jwt_vc_issuer_fetch=None, leeway_s=60, extra_contexts=None, fetch=https_text_fetch, expected_issuer=None)
A resolve_status_list (W3C Bitstring) that fetches the status-list
credential over the SSRF-guarded https fetch and verifies it through the
pipeline before returning it — a fetched-but-unverified status list would let a
forged one clear revocation. Status-of-status recursion is turned off
(require_status=False); resolver resolves the status issuer's key.
The returned body names its issuer: a list whose body names a different one than its
signer is refused (ClaimsInvalid on a VC-JWT or vc+sd-jwt list, where the
pipeline reconciles iss and issuer first; StatusListError on a
dc+sd-jwt list, where it does not), and one whose body names no one (the issuer is
in the JWT iss only) gets the verified signer filled in, on a copy, so
require_status_issuer_binding can bind it (ADR-0006, #226).
Source code in src/openvc/resolvers.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
default_status_list_token_resolver(*, resolver=None, jwt_vc_issuer_fetch=None, leeway_s=60, fetch=https_text_fetch, expected_issuer=None)
A resolve_status_list_token (IETF) that fetches the statuslist+jwt
token over the SSRF-guarded https fetch, resolves the issuer key, verifies the
token (typ + signature + exp + sub == the fetched URI, the IETF
anti-swap check), and returns its claims.
Source code in src/openvc/resolvers.py
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
default_credential_schema_resolver_async(*, fetch=https_bytes_fetch_async)
Async :func:default_credential_schema_resolver — fetches the raw schema
bytes over the SSRF-guarded async https fetch.
Source code in src/openvc/resolvers.py
248 249 250 251 252 253 254 255 | |
default_status_list_resolver_async(*, resolver=None, jwt_vc_issuer_fetch=None, leeway_s=60, extra_contexts=None, fetch=https_text_fetch_async, expected_issuer=None)
Async :func:default_status_list_resolver — fetches the status-list credential
over the SSRF-guarded async fetch and verifies it through the async pipeline
before returning it. resolver is an :class:AsyncDidResolver. The returned body
names its issuer exactly as :func:default_status_list_resolver's does.
Source code in src/openvc/resolvers.py
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
default_status_list_token_resolver_async(*, resolver=None, jwt_vc_issuer_fetch=None, leeway_s=60, fetch=https_text_fetch_async, expected_issuer=None)
Async :func:default_status_list_token_resolver — fetches the statuslist+jwt
over the SSRF-guarded async fetch, resolves the issuer key via the async pipeline,
and verifies the token (typ + signature + exp + sub == the fetched URI).
Source code in src/openvc/resolvers.py
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | |