tba-protocol-attestation-eat 0.4.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tba_protocol_attestation_eat-0.4.0.dev2/PKG-INFO +19 -0
- tba_protocol_attestation_eat-0.4.0.dev2/pyproject.toml +10 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/__init__.py +71 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/bindings.py +48 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/claims.py +17 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/compatibility.py +27 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/errors.py +20 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/features.py +26 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/migrations.py +16 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/profiles.py +5 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/py.typed +0 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/schemas.py +34 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/submodules.py +5 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/validation.py +5 -0
- tba_protocol_attestation_eat-0.4.0.dev2/src/tba_protocol_attestation_eat/versions.py +25 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tba-protocol-attestation-eat
|
|
3
|
+
Version: 0.4.0.dev2
|
|
4
|
+
Summary:
|
|
5
|
+
Requires-Python: >=3.10,<3.15
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Requires-Dist: tba-concrete-claim-eat-nonce (==0.4.0.dev2)
|
|
13
|
+
Requires-Dist: tba-concrete-claim-eat-profile (==0.4.0.dev2)
|
|
14
|
+
Requires-Dist: tba-concrete-claim-eat-submodules (==0.4.0.dev2)
|
|
15
|
+
Requires-Dist: tba-concrete-claim-issued-at (==0.4.0.dev2)
|
|
16
|
+
Requires-Dist: tba-concrete-claim-ueid (==0.4.0.dev2)
|
|
17
|
+
Requires-Dist: tba-concrete-eat (==0.4.0.dev2)
|
|
18
|
+
Requires-Dist: tba-concrete-eat-evidence (==0.4.0.dev2)
|
|
19
|
+
Requires-Dist: tba-contracts-identity (==0.4.0.dev2)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name="tba-protocol-attestation-eat"
|
|
3
|
+
version="0.4.0.dev2"
|
|
4
|
+
requires-python=">=3.10,<3.15"
|
|
5
|
+
dependencies=["tba-concrete-eat==0.4.0.dev2","tba-contracts-identity==0.4.0.dev2","tba-concrete-eat-evidence==0.4.0.dev2","tba-concrete-claim-eat-profile==0.4.0.dev2","tba-concrete-claim-eat-nonce==0.4.0.dev2","tba-concrete-claim-ueid==0.4.0.dev2","tba-concrete-claim-eat-submodules==0.4.0.dev2","tba-concrete-claim-issued-at==0.4.0.dev2"]
|
|
6
|
+
[build-system]
|
|
7
|
+
requires=["poetry-core>=1.0.0"]
|
|
8
|
+
build-backend="poetry.core.masonry.api"
|
|
9
|
+
[tool.poetry]
|
|
10
|
+
packages=[{include="tba_protocol_attestation_eat",from="src"}]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from .bindings import CAPABILITY_REQUIREMENTS
|
|
2
|
+
from .claims import (
|
|
3
|
+
EAT_CLAIM_CLASSES,
|
|
4
|
+
EatClaimSetPayload,
|
|
5
|
+
EatEncoding,
|
|
6
|
+
compose_eat_claim_set,
|
|
7
|
+
parse_eat_claims,
|
|
8
|
+
)
|
|
9
|
+
from .profiles import EatProfile
|
|
10
|
+
from .submodules import EatSubmodule, parse_submodules
|
|
11
|
+
from .validation import parse_eat, validate_eat_claims
|
|
12
|
+
from .compatibility import COMPATIBILITY_PATHS, EatCompatibility, compatibility
|
|
13
|
+
from .errors import EatProfileBindingError, EatProtocolError, UnsupportedEatCarrierError
|
|
14
|
+
from .features import FEATURES_BY_VERSION, supports
|
|
15
|
+
from .migrations import migrate_claims
|
|
16
|
+
from .schemas import (
|
|
17
|
+
EAT_CARRIERS,
|
|
18
|
+
EAT_CWT_CARRIER,
|
|
19
|
+
EAT_JWT_CARRIER,
|
|
20
|
+
EatCarrier,
|
|
21
|
+
select_carrier,
|
|
22
|
+
)
|
|
23
|
+
from .versions import CURRENT_VERSION, VERSION_HISTORY, EatVersion, select_version
|
|
24
|
+
from tba_contracts_identity.protocol_processing import (
|
|
25
|
+
build_protocol_capability_report as _build_protocol_capability_report,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def capability_report() -> dict[str, object]:
|
|
30
|
+
return _build_protocol_capability_report(
|
|
31
|
+
protocol="eat",
|
|
32
|
+
revision=CURRENT_VERSION.identifier,
|
|
33
|
+
features=tuple(FEATURES_BY_VERSION[CURRENT_VERSION.identifier]),
|
|
34
|
+
evidence_links=("tests/unit/test_versioned_eat_sd_jwt_vc_profiles.py",),
|
|
35
|
+
extra_requirements=CAPABILITY_REQUIREMENTS,
|
|
36
|
+
include_default_artifact_requirements=False,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"CAPABILITY_REQUIREMENTS",
|
|
42
|
+
"COMPATIBILITY_PATHS",
|
|
43
|
+
"CURRENT_VERSION",
|
|
44
|
+
"EAT_CARRIERS",
|
|
45
|
+
"EAT_CLAIM_CLASSES",
|
|
46
|
+
"EatClaimSetPayload",
|
|
47
|
+
"EatEncoding",
|
|
48
|
+
"EatProfile",
|
|
49
|
+
"EatSubmodule",
|
|
50
|
+
"EAT_CWT_CARRIER",
|
|
51
|
+
"EAT_JWT_CARRIER",
|
|
52
|
+
"FEATURES_BY_VERSION",
|
|
53
|
+
"VERSION_HISTORY",
|
|
54
|
+
"EatCarrier",
|
|
55
|
+
"EatCompatibility",
|
|
56
|
+
"EatProfileBindingError",
|
|
57
|
+
"EatProtocolError",
|
|
58
|
+
"EatVersion",
|
|
59
|
+
"UnsupportedEatCarrierError",
|
|
60
|
+
"capability_report",
|
|
61
|
+
"compatibility",
|
|
62
|
+
"compose_eat_claim_set",
|
|
63
|
+
"migrate_claims",
|
|
64
|
+
"parse_eat",
|
|
65
|
+
"parse_eat_claims",
|
|
66
|
+
"parse_submodules",
|
|
67
|
+
"select_carrier",
|
|
68
|
+
"select_version",
|
|
69
|
+
"supports",
|
|
70
|
+
"validate_eat_claims",
|
|
71
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""RFC 9711 wire elements mapped to reportable capabilities."""
|
|
2
|
+
|
|
3
|
+
from tba_contracts_identity.capabilities import ProtocolCapabilityRequirement
|
|
4
|
+
|
|
5
|
+
from .versions import CURRENT_VERSION
|
|
6
|
+
|
|
7
|
+
CAPABILITY_REQUIREMENTS = (
|
|
8
|
+
ProtocolCapabilityRequirement(
|
|
9
|
+
"eat",
|
|
10
|
+
CURRENT_VERSION.identifier,
|
|
11
|
+
"eat-protected-token-verification",
|
|
12
|
+
"application/eat+jwt application/eat+cwt",
|
|
13
|
+
"attestation.appraisal",
|
|
14
|
+
"verify_evidence",
|
|
15
|
+
"attestation-evidence",
|
|
16
|
+
),
|
|
17
|
+
ProtocolCapabilityRequirement(
|
|
18
|
+
"eat",
|
|
19
|
+
CURRENT_VERSION.identifier,
|
|
20
|
+
"eat-reference-backed-appraisal",
|
|
21
|
+
"eat_profile",
|
|
22
|
+
"attestation.appraisal",
|
|
23
|
+
"appraise",
|
|
24
|
+
"verified-attestation-evidence",
|
|
25
|
+
),
|
|
26
|
+
ProtocolCapabilityRequirement(
|
|
27
|
+
"eat",
|
|
28
|
+
CURRENT_VERSION.identifier,
|
|
29
|
+
"eat-reference-resolution",
|
|
30
|
+
"eat_profile",
|
|
31
|
+
"attestation.appraisal",
|
|
32
|
+
"resolve_reference_material",
|
|
33
|
+
"attestation-reference-manifest",
|
|
34
|
+
required=False,
|
|
35
|
+
),
|
|
36
|
+
ProtocolCapabilityRequirement(
|
|
37
|
+
"eat",
|
|
38
|
+
CURRENT_VERSION.identifier,
|
|
39
|
+
"eat-appraisal-recording",
|
|
40
|
+
"appraisal-result",
|
|
41
|
+
"attestation.appraisal",
|
|
42
|
+
"record_result",
|
|
43
|
+
"attestation-result",
|
|
44
|
+
required=False,
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
__all__ = ["CAPABILITY_REQUIREMENTS"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Versioned EAT protocol exports backed by deterministic layer-10 claims."""
|
|
2
|
+
|
|
3
|
+
from tba_concrete_eat.claims import (
|
|
4
|
+
EAT_CLAIM_CLASSES,
|
|
5
|
+
EatClaimSetPayload,
|
|
6
|
+
EatEncoding,
|
|
7
|
+
compose_eat_claim_set,
|
|
8
|
+
parse_eat_claims,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"EAT_CLAIM_CLASSES",
|
|
13
|
+
"EatClaimSetPayload",
|
|
14
|
+
"EatEncoding",
|
|
15
|
+
"compose_eat_claim_set",
|
|
16
|
+
"parse_eat_claims",
|
|
17
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Supported EAT revision compatibility paths."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True, slots=True)
|
|
7
|
+
class EatCompatibility:
|
|
8
|
+
source: str
|
|
9
|
+
target: str
|
|
10
|
+
compatible: bool
|
|
11
|
+
migration_required: bool
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
COMPATIBILITY_PATHS = (
|
|
15
|
+
EatCompatibility("RFC9711", "RFC9711", True, False),
|
|
16
|
+
EatCompatibility("draft-ietf-rats-eat-30", "RFC9711", True, True),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def compatibility(source: str, target: str = "RFC9711") -> EatCompatibility:
|
|
21
|
+
for path in COMPATIBILITY_PATHS:
|
|
22
|
+
if path.source == source and path.target == target:
|
|
23
|
+
return path
|
|
24
|
+
return EatCompatibility(source, target, False, False)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
__all__ = ["COMPATIBILITY_PATHS", "EatCompatibility", "compatibility"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""EAT protocol mapping errors."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class EatProtocolError(ValueError):
|
|
5
|
+
"""Base error for an RFC 9711 mapping failure."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class UnsupportedEatCarrierError(EatProtocolError):
|
|
9
|
+
"""Raised when neither the EAT JWT nor EAT CWT carrier applies."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EatProfileBindingError(EatProtocolError):
|
|
13
|
+
"""Raised when the authenticated profile and evidence profile differ."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"EatProfileBindingError",
|
|
18
|
+
"EatProtocolError",
|
|
19
|
+
"UnsupportedEatCarrierError",
|
|
20
|
+
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
FEATURES_BY_VERSION = {
|
|
2
|
+
"draft-ietf-rats-eat-30": frozenset(
|
|
3
|
+
{"jwt", "cwt", "eat-profile", "nonce", "submodules"}
|
|
4
|
+
),
|
|
5
|
+
"RFC9711": frozenset(
|
|
6
|
+
{
|
|
7
|
+
"jwt",
|
|
8
|
+
"cwt",
|
|
9
|
+
"eat-profile",
|
|
10
|
+
"nonce",
|
|
11
|
+
"submodules",
|
|
12
|
+
"detached-bundles",
|
|
13
|
+
"nested-tokens",
|
|
14
|
+
}
|
|
15
|
+
),
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def supports(feature: str, version: str = "RFC9711") -> bool:
|
|
20
|
+
try:
|
|
21
|
+
return feature in FEATURES_BY_VERSION[version]
|
|
22
|
+
except KeyError as exc:
|
|
23
|
+
raise ValueError(f"unsupported EAT version: {version}") from exc
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
__all__ = ["FEATURES_BY_VERSION", "supports"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from typing import Any, Mapping
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def migrate_claims(
|
|
5
|
+
value: Mapping[str | int, Any], *, source: str, target: str = "RFC9711"
|
|
6
|
+
) -> dict[str | int, Any]:
|
|
7
|
+
if source == target:
|
|
8
|
+
return dict(value)
|
|
9
|
+
if source != "draft-ietf-rats-eat-30" or target != "RFC9711":
|
|
10
|
+
raise ValueError(f"unsupported EAT migration: {source} -> {target}")
|
|
11
|
+
if "eat_profile" not in value and 265 not in value:
|
|
12
|
+
raise ValueError("EAT migration requires an explicit eat_profile")
|
|
13
|
+
return dict(value)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["migrate_claims"]
|
|
File without changes
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""RFC 9711 protected-carrier mappings."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from tba_contracts_identity.tokens import TokenEnvelopeFormat
|
|
6
|
+
|
|
7
|
+
from .errors import UnsupportedEatCarrierError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True, slots=True)
|
|
11
|
+
class EatCarrier:
|
|
12
|
+
media_type: str
|
|
13
|
+
envelope_format: TokenEnvelopeFormat
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
EAT_JWT_CARRIER = EatCarrier("application/eat+jwt", TokenEnvelopeFormat.JWT)
|
|
17
|
+
EAT_CWT_CARRIER = EatCarrier("application/eat+cwt", TokenEnvelopeFormat.CWT)
|
|
18
|
+
EAT_CARRIERS = (EAT_JWT_CARRIER, EAT_CWT_CARRIER)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def select_carrier(media_type: str) -> EatCarrier:
|
|
22
|
+
for carrier in EAT_CARRIERS:
|
|
23
|
+
if carrier.media_type == media_type:
|
|
24
|
+
return carrier
|
|
25
|
+
raise UnsupportedEatCarrierError(f"unsupported EAT media type: {media_type}")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
"EAT_CARRIERS",
|
|
30
|
+
"EAT_CWT_CARRIER",
|
|
31
|
+
"EAT_JWT_CARRIER",
|
|
32
|
+
"EatCarrier",
|
|
33
|
+
"select_carrier",
|
|
34
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclass(frozen=True, slots=True)
|
|
5
|
+
class EatVersion:
|
|
6
|
+
identifier: str
|
|
7
|
+
status: str
|
|
8
|
+
published: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
VERSION_HISTORY = (
|
|
12
|
+
EatVersion("draft-ietf-rats-eat-30", "superseded-draft", "2024-01"),
|
|
13
|
+
EatVersion("RFC9711", "standards-track", "2025-04"),
|
|
14
|
+
)
|
|
15
|
+
CURRENT_VERSION = VERSION_HISTORY[-1]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def select_version(identifier: str = "RFC9711") -> EatVersion:
|
|
19
|
+
for version in VERSION_HISTORY:
|
|
20
|
+
if version.identifier == identifier:
|
|
21
|
+
return version
|
|
22
|
+
raise ValueError(f"unsupported EAT version: {identifier}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
__all__ = ["CURRENT_VERSION", "VERSION_HISTORY", "EatVersion", "select_version"]
|