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.
@@ -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"]
@@ -0,0 +1,5 @@
1
+ """Versioned EAT protocol export for the deterministic profile value."""
2
+
3
+ from tba_concrete_eat.profiles import EatProfile
4
+
5
+ __all__ = ["EatProfile"]
@@ -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,5 @@
1
+ """Versioned EAT protocol exports backed by deterministic submodule values."""
2
+
3
+ from tba_concrete_eat.submodules import EatSubmodule, parse_submodules
4
+
5
+ __all__ = ["EatSubmodule", "parse_submodules"]
@@ -0,0 +1,5 @@
1
+ """Versioned EAT protocol exports backed by deterministic validation."""
2
+
3
+ from tba_concrete_eat.validation import parse_eat, validate_eat_claims
4
+
5
+ __all__ = ["parse_eat", "validate_eat_claims"]
@@ -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"]