tba-profile-haip 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_profile_haip-0.4.0.dev2/PKG-INFO +15 -0
- tba_profile_haip-0.4.0.dev2/pyproject.toml +11 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/__init__.py +51 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/bindings.py +73 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/claims.py +10 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/compatibility.py +45 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/errors.py +16 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/features.py +36 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/migrations.py +21 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/profile.py +35 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/py.typed +0 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/schemas.py +23 -0
- tba_profile_haip-0.4.0.dev2/src/tba_profile_haip/versions.py +25 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tba-profile-haip
|
|
3
|
+
Version: 0.4.0.dev2
|
|
4
|
+
Summary:
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.10,<3.15
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Dist: tba-contracts-identity (==0.4.0.dev2)
|
|
14
|
+
Requires-Dist: tba-protocol-oid4vci (==0.4.0.dev2)
|
|
15
|
+
Requires-Dist: tba-protocol-oid4vp (==0.4.0.dev2)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name="tba-profile-haip"
|
|
3
|
+
version="0.4.0.dev2"
|
|
4
|
+
requires-python=">=3.10,<3.15"
|
|
5
|
+
license="Apache-2.0"
|
|
6
|
+
dependencies=["tba-protocol-oid4vci==0.4.0.dev2","tba-protocol-oid4vp==0.4.0.dev2","tba-contracts-identity==0.4.0.dev2"]
|
|
7
|
+
[build-system]
|
|
8
|
+
requires=["poetry-core>=1.0.0"]
|
|
9
|
+
build-backend="poetry.core.masonry.api"
|
|
10
|
+
[tool.poetry]
|
|
11
|
+
packages=[{include="tba_profile_haip",from="src"}]
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Versioned High Assurance Interoperability Profile ownership."""
|
|
2
|
+
|
|
3
|
+
from tba_contracts_identity.protocol_processing import (
|
|
4
|
+
build_protocol_capability_report,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from .bindings import CAPABILITY_REQUIREMENTS
|
|
8
|
+
from .claims import HAIP_PROOF_CLAIM_CLASSES
|
|
9
|
+
from .compatibility import COMPATIBILITY_PATHS, HaipCompatibility, compatibility
|
|
10
|
+
from .errors import HaipComponentVersionError, HaipProfileError, HaipTrustBindingError
|
|
11
|
+
from .features import FEATURES_BY_VERSION, supports
|
|
12
|
+
from .migrations import migrate_configuration
|
|
13
|
+
from .profile import HAIP_CREDENTIAL_FORMATS, HaipConfiguration, configure_haip
|
|
14
|
+
from .schemas import HaipComponentVersions, HaipCredentialFormats
|
|
15
|
+
from .versions import CURRENT_VERSION, VERSION_HISTORY, HaipVersion, select_version
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def capability_report() -> dict[str, object]:
|
|
19
|
+
return build_protocol_capability_report(
|
|
20
|
+
protocol="haip",
|
|
21
|
+
revision=CURRENT_VERSION.identifier,
|
|
22
|
+
features=tuple(FEATURES_BY_VERSION[CURRENT_VERSION.identifier]),
|
|
23
|
+
evidence_links=("tests/unit/test_versioned_haip_profile.py",),
|
|
24
|
+
extra_requirements=CAPABILITY_REQUIREMENTS,
|
|
25
|
+
include_default_artifact_requirements=False,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"CAPABILITY_REQUIREMENTS",
|
|
31
|
+
"COMPATIBILITY_PATHS",
|
|
32
|
+
"CURRENT_VERSION",
|
|
33
|
+
"FEATURES_BY_VERSION",
|
|
34
|
+
"HAIP_CREDENTIAL_FORMATS",
|
|
35
|
+
"HAIP_PROOF_CLAIM_CLASSES",
|
|
36
|
+
"VERSION_HISTORY",
|
|
37
|
+
"HaipCompatibility",
|
|
38
|
+
"HaipComponentVersionError",
|
|
39
|
+
"HaipComponentVersions",
|
|
40
|
+
"HaipConfiguration",
|
|
41
|
+
"HaipCredentialFormats",
|
|
42
|
+
"HaipProfileError",
|
|
43
|
+
"HaipTrustBindingError",
|
|
44
|
+
"HaipVersion",
|
|
45
|
+
"capability_report",
|
|
46
|
+
"compatibility",
|
|
47
|
+
"configure_haip",
|
|
48
|
+
"migrate_configuration",
|
|
49
|
+
"select_version",
|
|
50
|
+
"supports",
|
|
51
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""HAIP profile requirements mapped to composed capabilities."""
|
|
2
|
+
|
|
3
|
+
from tba_contracts_identity.capabilities import ProtocolCapabilityRequirement
|
|
4
|
+
|
|
5
|
+
from .versions import CURRENT_VERSION
|
|
6
|
+
|
|
7
|
+
CAPABILITY_REQUIREMENTS = (
|
|
8
|
+
ProtocolCapabilityRequirement(
|
|
9
|
+
"haip",
|
|
10
|
+
CURRENT_VERSION.identifier,
|
|
11
|
+
"haip-credential-issuance",
|
|
12
|
+
"OID4VCI credential response",
|
|
13
|
+
"digital-credential.issuance",
|
|
14
|
+
"issue",
|
|
15
|
+
"haip-credential",
|
|
16
|
+
),
|
|
17
|
+
ProtocolCapabilityRequirement(
|
|
18
|
+
"haip",
|
|
19
|
+
CURRENT_VERSION.identifier,
|
|
20
|
+
"haip-wallet-attestation",
|
|
21
|
+
"wallet attestation",
|
|
22
|
+
"digital-credential.issuance",
|
|
23
|
+
"verify_wallet_attestation",
|
|
24
|
+
"verified-wallet-attestation",
|
|
25
|
+
),
|
|
26
|
+
ProtocolCapabilityRequirement(
|
|
27
|
+
"haip",
|
|
28
|
+
CURRENT_VERSION.identifier,
|
|
29
|
+
"haip-presentation",
|
|
30
|
+
"OID4VP authorization response",
|
|
31
|
+
"digital-credential.presentation",
|
|
32
|
+
"present",
|
|
33
|
+
"haip-presentation-result",
|
|
34
|
+
),
|
|
35
|
+
ProtocolCapabilityRequirement(
|
|
36
|
+
"haip",
|
|
37
|
+
CURRENT_VERSION.identifier,
|
|
38
|
+
"haip-presentation-verification",
|
|
39
|
+
"SD-JWT VC or mdoc presentation",
|
|
40
|
+
"digital-credential.presentation",
|
|
41
|
+
"verify_presentation",
|
|
42
|
+
"verified-haip-presentation",
|
|
43
|
+
),
|
|
44
|
+
ProtocolCapabilityRequirement(
|
|
45
|
+
"haip",
|
|
46
|
+
CURRENT_VERSION.identifier,
|
|
47
|
+
"haip-artifact-validation",
|
|
48
|
+
"SD-JWT VC, KB-JWT, mdoc, or attestation artifact",
|
|
49
|
+
"artifact.processing",
|
|
50
|
+
"validate",
|
|
51
|
+
"verified-haip-artifact",
|
|
52
|
+
),
|
|
53
|
+
ProtocolCapabilityRequirement(
|
|
54
|
+
"haip",
|
|
55
|
+
CURRENT_VERSION.identifier,
|
|
56
|
+
"haip-key-verifier-attestation",
|
|
57
|
+
"key or verifier attestation",
|
|
58
|
+
"attestation.appraisal",
|
|
59
|
+
"verify_evidence",
|
|
60
|
+
"verified-attestation-evidence",
|
|
61
|
+
),
|
|
62
|
+
ProtocolCapabilityRequirement(
|
|
63
|
+
"haip",
|
|
64
|
+
CURRENT_VERSION.identifier,
|
|
65
|
+
"haip-replay-protection",
|
|
66
|
+
"nonce and transaction binding",
|
|
67
|
+
"security.replay-protection",
|
|
68
|
+
"check_and_reserve",
|
|
69
|
+
"haip:presentation-binding",
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
__all__ = ["CAPABILITY_REQUIREMENTS"]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Claim families composed by HAIP from OID4VCI and OID4VP."""
|
|
2
|
+
|
|
3
|
+
from tba_protocol_oid4vci.claims import OID4VCI_PROOF_CLAIM_CLASSES
|
|
4
|
+
from tba_protocol_oid4vp.claims import OID4VP_BINDING_CLAIM_CLASSES
|
|
5
|
+
|
|
6
|
+
HAIP_PROOF_CLAIM_CLASSES = tuple(
|
|
7
|
+
dict.fromkeys(OID4VCI_PROOF_CLAIM_CLASSES + OID4VP_BINDING_CLAIM_CLASSES)
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
__all__ = ["HAIP_PROOF_CLAIM_CLASSES"]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""HAIP revision compatibility paths."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from .versions import CURRENT_VERSION, VERSION_HISTORY
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True, slots=True)
|
|
9
|
+
class HaipCompatibility:
|
|
10
|
+
source: str
|
|
11
|
+
target: str
|
|
12
|
+
compatible: bool
|
|
13
|
+
migration_required: bool
|
|
14
|
+
lossless: bool
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
COMPATIBILITY_PATHS = (
|
|
18
|
+
HaipCompatibility(
|
|
19
|
+
VERSION_HISTORY[0].identifier,
|
|
20
|
+
CURRENT_VERSION.identifier,
|
|
21
|
+
True,
|
|
22
|
+
True,
|
|
23
|
+
False,
|
|
24
|
+
),
|
|
25
|
+
HaipCompatibility(
|
|
26
|
+
CURRENT_VERSION.identifier,
|
|
27
|
+
CURRENT_VERSION.identifier,
|
|
28
|
+
True,
|
|
29
|
+
False,
|
|
30
|
+
True,
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def compatibility(
|
|
36
|
+
source: str,
|
|
37
|
+
target: str = CURRENT_VERSION.identifier,
|
|
38
|
+
) -> HaipCompatibility:
|
|
39
|
+
for path in COMPATIBILITY_PATHS:
|
|
40
|
+
if path.source == source and path.target == target:
|
|
41
|
+
return path
|
|
42
|
+
return HaipCompatibility(source, target, False, False, False)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
__all__ = ["COMPATIBILITY_PATHS", "HaipCompatibility", "compatibility"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""HAIP profile composition errors."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class HaipProfileError(ValueError):
|
|
5
|
+
"""Base error for an HAIP configuration or binding failure."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HaipComponentVersionError(HaipProfileError):
|
|
9
|
+
"""Raised when component protocol revisions are not profile-compatible."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class HaipTrustBindingError(HaipProfileError):
|
|
13
|
+
"""Raised when required wallet/key/verifier trust evidence is unavailable."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["HaipComponentVersionError", "HaipProfileError", "HaipTrustBindingError"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
FEATURES_BY_VERSION = {
|
|
2
|
+
"draft-03": frozenset(
|
|
3
|
+
{
|
|
4
|
+
"oid4vci",
|
|
5
|
+
"oid4vp",
|
|
6
|
+
"sd-jwt-vc",
|
|
7
|
+
"iso-mdoc",
|
|
8
|
+
"wallet-attestation",
|
|
9
|
+
"key-attestation",
|
|
10
|
+
}
|
|
11
|
+
),
|
|
12
|
+
"1.0": frozenset(
|
|
13
|
+
{
|
|
14
|
+
"oid4vci-1.0",
|
|
15
|
+
"oid4vp-1.0",
|
|
16
|
+
"sd-jwt-vc",
|
|
17
|
+
"iso-mdoc",
|
|
18
|
+
"dcql",
|
|
19
|
+
"wallet-attestation",
|
|
20
|
+
"key-attestation",
|
|
21
|
+
"holder-binding",
|
|
22
|
+
"verifier-attestation",
|
|
23
|
+
"encrypted-responses",
|
|
24
|
+
}
|
|
25
|
+
),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def supports(feature: str, version: str = "1.0") -> bool:
|
|
30
|
+
try:
|
|
31
|
+
return feature in FEATURES_BY_VERSION[version]
|
|
32
|
+
except KeyError as exc:
|
|
33
|
+
raise ValueError(f"unsupported HAIP version: {version}") from exc
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = ["FEATURES_BY_VERSION", "supports"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from typing import Any, Mapping
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def migrate_configuration(
|
|
5
|
+
value: Mapping[str, Any], *, source: str, target: str = "1.0"
|
|
6
|
+
) -> dict[str, Any]:
|
|
7
|
+
if source == target:
|
|
8
|
+
return dict(value)
|
|
9
|
+
if source != "draft-03" or target != "1.0":
|
|
10
|
+
raise ValueError(f"unsupported HAIP migration: {source} -> {target}")
|
|
11
|
+
migrated = dict(value)
|
|
12
|
+
if "presentation_definition" in migrated:
|
|
13
|
+
raise ValueError(
|
|
14
|
+
"HAIP draft Presentation Exchange constraints require an explicit DCQL migration"
|
|
15
|
+
)
|
|
16
|
+
migrated["oid4vci_version"] = "1.0"
|
|
17
|
+
migrated["oid4vp_version"] = "1.0"
|
|
18
|
+
return migrated
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = ["migrate_configuration"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from tba_protocol_oid4vci import select_version as select_oid4vci_version
|
|
4
|
+
from tba_protocol_oid4vp import select_version as select_oid4vp_version
|
|
5
|
+
|
|
6
|
+
HAIP_CREDENTIAL_FORMATS = frozenset({"dc+sd-jwt", "mso_mdoc"})
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True, slots=True)
|
|
10
|
+
class HaipConfiguration:
|
|
11
|
+
credential_formats: frozenset[str]
|
|
12
|
+
oid4vci_version: str = "1.0"
|
|
13
|
+
oid4vp_version: str = "1.0"
|
|
14
|
+
wallet_attestation: bool = True
|
|
15
|
+
key_attestation: bool = True
|
|
16
|
+
|
|
17
|
+
def validate(self) -> None:
|
|
18
|
+
select_oid4vci_version(self.oid4vci_version)
|
|
19
|
+
select_oid4vp_version(self.oid4vp_version)
|
|
20
|
+
unsupported = self.credential_formats - HAIP_CREDENTIAL_FORMATS
|
|
21
|
+
if unsupported:
|
|
22
|
+
raise ValueError(
|
|
23
|
+
f"unsupported HAIP credential formats: {sorted(unsupported)}"
|
|
24
|
+
)
|
|
25
|
+
if not self.credential_formats:
|
|
26
|
+
raise ValueError("HAIP requires at least one credential format")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def configure_haip(*, credential_formats: frozenset[str]) -> HaipConfiguration:
|
|
30
|
+
configuration = HaipConfiguration(credential_formats)
|
|
31
|
+
configuration.validate()
|
|
32
|
+
return configuration
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = ["HAIP_CREDENTIAL_FORMATS", "HaipConfiguration", "configure_haip"]
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Typed HAIP component/profile schema descriptors."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from .profile import HAIP_CREDENTIAL_FORMATS, HaipConfiguration
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True, slots=True)
|
|
9
|
+
class HaipComponentVersions:
|
|
10
|
+
oid4vci: str = "1.0"
|
|
11
|
+
oid4vp: str = "1.0"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True, slots=True)
|
|
15
|
+
class HaipCredentialFormats:
|
|
16
|
+
allowed: frozenset[str] = HAIP_CREDENTIAL_FORMATS
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"HaipComponentVersions",
|
|
21
|
+
"HaipConfiguration",
|
|
22
|
+
"HaipCredentialFormats",
|
|
23
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@dataclass(frozen=True, slots=True)
|
|
5
|
+
class HaipVersion:
|
|
6
|
+
identifier: str
|
|
7
|
+
status: str
|
|
8
|
+
published: str
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
VERSION_HISTORY = (
|
|
12
|
+
HaipVersion("draft-03", "superseded-draft", "2025-03"),
|
|
13
|
+
HaipVersion("1.0", "final", "2025-12-24"),
|
|
14
|
+
)
|
|
15
|
+
CURRENT_VERSION = VERSION_HISTORY[-1]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def select_version(identifier: str = "1.0") -> HaipVersion:
|
|
19
|
+
for version in VERSION_HISTORY:
|
|
20
|
+
if version.identifier == identifier:
|
|
21
|
+
return version
|
|
22
|
+
raise ValueError(f"unsupported HAIP version: {identifier}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
__all__ = ["CURRENT_VERSION", "VERSION_HISTORY", "HaipVersion", "select_version"]
|