auths-python 0.1.0__cp38-abi3-win_amd64.whl
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.
- auths/__init__.py +147 -0
- auths/__init__.pyi +486 -0
- auths/_client.py +713 -0
- auths/_errors.py +80 -0
- auths/_native.pyd +0 -0
- auths/agent.py +55 -0
- auths/artifact.py +60 -0
- auths/attestation_query.py +141 -0
- auths/audit.py +226 -0
- auths/commit.py +28 -0
- auths/devices.py +162 -0
- auths/doctor.py +109 -0
- auths/git.py +473 -0
- auths/identity.py +221 -0
- auths/jwt.py +253 -0
- auths/org.py +310 -0
- auths/pairing.py +216 -0
- auths/policy.py +382 -0
- auths/py.typed +0 -0
- auths/rotation.py +30 -0
- auths/sign.py +5 -0
- auths/trust.py +169 -0
- auths/verify.py +111 -0
- auths/witness.py +91 -0
- auths_python-0.1.0.dist-info/METADATA +152 -0
- auths_python-0.1.0.dist-info/RECORD +28 -0
- auths_python-0.1.0.dist-info/WHEEL +4 -0
- auths_python-0.1.0.dist-info/sboms/auths-python.cyclonedx.json +14418 -0
auths/devices.py
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""Device resource service — Stripe-style API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
from auths._native import (
|
|
9
|
+
extend_device_authorization_ffi as _extend_device,
|
|
10
|
+
link_device_to_identity as _link_device,
|
|
11
|
+
revoke_device_from_identity as _revoke_device,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from auths._client import Auths
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class Device:
|
|
20
|
+
"""A linked device."""
|
|
21
|
+
|
|
22
|
+
did: str
|
|
23
|
+
"""The device's DID (`did:key:z...`)."""
|
|
24
|
+
attestation_id: str
|
|
25
|
+
"""RID of the attestation linking this device to its identity."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class DeviceExtension:
|
|
30
|
+
"""Result of extending a device's authorization period."""
|
|
31
|
+
|
|
32
|
+
device_did: str
|
|
33
|
+
"""The device's DID (`did:key:z...`)."""
|
|
34
|
+
new_expires_at: str
|
|
35
|
+
"""ISO 8601 timestamp of the new expiry."""
|
|
36
|
+
previous_expires_at: str | None
|
|
37
|
+
"""ISO 8601 timestamp of the previous expiry, or None if none was set."""
|
|
38
|
+
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
return (
|
|
41
|
+
f"DeviceExtension(device='{self.device_did[:20]}...', "
|
|
42
|
+
f"expires='{self.new_expires_at}')"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class DeviceService:
|
|
47
|
+
"""Resource service for device operations.
|
|
48
|
+
|
|
49
|
+
Examples:
|
|
50
|
+
```python
|
|
51
|
+
device = auths.devices.link(identity_did="did:keri:...", capabilities=["sign"])
|
|
52
|
+
auths.devices.revoke(device.did, identity_did="did:keri:...")
|
|
53
|
+
```
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def __init__(self, client: Auths):
|
|
57
|
+
self._client = client
|
|
58
|
+
|
|
59
|
+
def link(
|
|
60
|
+
self,
|
|
61
|
+
identity_did: str,
|
|
62
|
+
capabilities: list[str] | None = None,
|
|
63
|
+
expires_in: int | None = None,
|
|
64
|
+
passphrase: str | None = None,
|
|
65
|
+
) -> Device:
|
|
66
|
+
"""Link a new device to an identity.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
identity_did: The identity to link this device to.
|
|
70
|
+
capabilities: Device capabilities (default: []).
|
|
71
|
+
expires_in: Duration in seconds until expiration (per RFC 6749).
|
|
72
|
+
passphrase: Key passphrase override.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Device with the device DID and attestation ID.
|
|
76
|
+
|
|
77
|
+
Raises:
|
|
78
|
+
IdentityError: If the identity doesn't exist.
|
|
79
|
+
StorageError: If writing the attestation fails.
|
|
80
|
+
|
|
81
|
+
Examples:
|
|
82
|
+
```python
|
|
83
|
+
device = auths.devices.link(identity.did, capabilities=["sign"], expires_in=7_776_000)
|
|
84
|
+
```
|
|
85
|
+
"""
|
|
86
|
+
pp = passphrase or self._client._passphrase
|
|
87
|
+
device_did, attestation_id = _link_device(
|
|
88
|
+
identity_did,
|
|
89
|
+
capabilities or [],
|
|
90
|
+
self._client.repo_path,
|
|
91
|
+
pp,
|
|
92
|
+
expires_in,
|
|
93
|
+
)
|
|
94
|
+
return Device(did=device_did, attestation_id=attestation_id)
|
|
95
|
+
|
|
96
|
+
def extend(
|
|
97
|
+
self,
|
|
98
|
+
device_did: str,
|
|
99
|
+
identity_did: str,
|
|
100
|
+
*,
|
|
101
|
+
days: int = 90,
|
|
102
|
+
passphrase: str | None = None,
|
|
103
|
+
) -> DeviceExtension:
|
|
104
|
+
"""Extend a device's authorization period.
|
|
105
|
+
|
|
106
|
+
Renews the device's expiry without revoking and re-linking.
|
|
107
|
+
Expired devices can be extended (grace period). Revoked devices cannot.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
device_did: The device's DID (`did:key:z...`).
|
|
111
|
+
identity_did: The identity key alias for signing.
|
|
112
|
+
days: Number of days to extend from now (default: 90).
|
|
113
|
+
passphrase: Optional passphrase for keychain access.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
DeviceExtension with the new and previous expiry timestamps.
|
|
117
|
+
|
|
118
|
+
Raises:
|
|
119
|
+
IdentityError: If the device or identity doesn't exist.
|
|
120
|
+
VerificationError: If the device has been revoked.
|
|
121
|
+
|
|
122
|
+
Examples:
|
|
123
|
+
```python
|
|
124
|
+
ext = auths.devices.extend(device.did, identity.did, days=90)
|
|
125
|
+
print(f"Extended until: {ext.new_expires_at}")
|
|
126
|
+
```
|
|
127
|
+
"""
|
|
128
|
+
pp = passphrase or self._client._passphrase
|
|
129
|
+
result = _extend_device(
|
|
130
|
+
device_did, identity_did, days, self._client.repo_path, pp
|
|
131
|
+
)
|
|
132
|
+
return DeviceExtension(
|
|
133
|
+
device_did=result.device_did,
|
|
134
|
+
new_expires_at=result.new_expires_at,
|
|
135
|
+
previous_expires_at=result.previous_expires_at,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
def revoke(
|
|
139
|
+
self,
|
|
140
|
+
device_did: str,
|
|
141
|
+
identity_did: str,
|
|
142
|
+
note: str | None = None,
|
|
143
|
+
passphrase: str | None = None,
|
|
144
|
+
) -> None:
|
|
145
|
+
"""Revoke a device.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
device_did: The device DID to revoke.
|
|
149
|
+
identity_did: The parent identity's DID.
|
|
150
|
+
note: Optional revocation note.
|
|
151
|
+
passphrase: Key passphrase override.
|
|
152
|
+
|
|
153
|
+
Raises:
|
|
154
|
+
IdentityError: If the device or identity doesn't exist.
|
|
155
|
+
|
|
156
|
+
Examples:
|
|
157
|
+
```python
|
|
158
|
+
auths.devices.revoke(device.did, identity_did=identity.did, note="lost laptop")
|
|
159
|
+
```
|
|
160
|
+
"""
|
|
161
|
+
pp = passphrase or self._client._passphrase
|
|
162
|
+
_revoke_device(device_did, identity_did, self._client.repo_path, pp, note)
|
auths/doctor.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from auths._native import run_diagnostics as _run_diagnostics
|
|
8
|
+
from auths._client import _map_error
|
|
9
|
+
from auths._errors import AuthsError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class Check:
|
|
14
|
+
"""A single diagnostic check result."""
|
|
15
|
+
|
|
16
|
+
name: str
|
|
17
|
+
passed: bool
|
|
18
|
+
message: str
|
|
19
|
+
fix_hint: Optional[str]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class DiagnosticReport:
|
|
24
|
+
"""Full health check report.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
checks: Individual check results.
|
|
28
|
+
all_passed: True if every check passed.
|
|
29
|
+
version: Auths CLI/SDK version string (e.g. ``"0.9.0"``).
|
|
30
|
+
Useful for support tickets and compatibility checks.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
checks: list[Check]
|
|
34
|
+
all_passed: bool
|
|
35
|
+
version: str
|
|
36
|
+
"""Auths CLI/SDK version string (e.g. ``"0.9.0"``)."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class DoctorService:
|
|
40
|
+
"""Resource service for system diagnostics."""
|
|
41
|
+
|
|
42
|
+
#: Known diagnostic check names.
|
|
43
|
+
AVAILABLE_CHECKS: list[str] = [
|
|
44
|
+
"git_version",
|
|
45
|
+
"ssh_keygen",
|
|
46
|
+
"git_signing_config",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
def __init__(self, client):
|
|
50
|
+
self._client = client
|
|
51
|
+
|
|
52
|
+
@classmethod
|
|
53
|
+
def available_checks(cls) -> list[str]:
|
|
54
|
+
"""Return the list of known diagnostic check names.
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
```python
|
|
58
|
+
for name in DoctorService.available_checks():
|
|
59
|
+
result = client.doctor.check_one(name)
|
|
60
|
+
```
|
|
61
|
+
"""
|
|
62
|
+
return list(cls.AVAILABLE_CHECKS)
|
|
63
|
+
|
|
64
|
+
def check(
|
|
65
|
+
self,
|
|
66
|
+
repo_path: str | None = None,
|
|
67
|
+
) -> DiagnosticReport:
|
|
68
|
+
"""Run all diagnostic checks.
|
|
69
|
+
|
|
70
|
+
Usage:
|
|
71
|
+
report = client.doctor.check()
|
|
72
|
+
if not report.all_passed:
|
|
73
|
+
for c in report.checks:
|
|
74
|
+
if not c.passed:
|
|
75
|
+
print(f"FAIL: {c.name} - {c.fix_hint}")
|
|
76
|
+
"""
|
|
77
|
+
rp = repo_path or self._client.repo_path
|
|
78
|
+
try:
|
|
79
|
+
raw = _run_diagnostics(rp)
|
|
80
|
+
data = json.loads(raw)
|
|
81
|
+
checks = [
|
|
82
|
+
Check(
|
|
83
|
+
name=c["name"],
|
|
84
|
+
passed=c["passed"],
|
|
85
|
+
message=c.get("message", ""),
|
|
86
|
+
fix_hint=c.get("fix_hint"),
|
|
87
|
+
)
|
|
88
|
+
for c in data["checks"]
|
|
89
|
+
]
|
|
90
|
+
return DiagnosticReport(
|
|
91
|
+
checks=checks,
|
|
92
|
+
all_passed=data["all_passed"],
|
|
93
|
+
version=data.get("version", ""),
|
|
94
|
+
)
|
|
95
|
+
except (ValueError, RuntimeError) as exc:
|
|
96
|
+
raise _map_error(exc, default_cls=AuthsError) from exc
|
|
97
|
+
|
|
98
|
+
def check_one(
|
|
99
|
+
self,
|
|
100
|
+
name: str,
|
|
101
|
+
repo_path: str | None = None,
|
|
102
|
+
) -> Check | None:
|
|
103
|
+
"""Run a single named diagnostic check.
|
|
104
|
+
|
|
105
|
+
Usage:
|
|
106
|
+
git_check = client.doctor.check_one("Git installed")
|
|
107
|
+
"""
|
|
108
|
+
report = self.check(repo_path=repo_path)
|
|
109
|
+
return next((c for c in report.checks if c.name == name), None)
|