diff --git a/elydora/__init__.py b/elydora/__init__.py index 8d27a7c..d1743d1 100644 --- a/elydora/__init__.py +++ b/elydora/__init__.py @@ -42,7 +42,10 @@ from .types import ( AuthRegisterResponse, AuthLoginResponse, GetMeResponse, + IssueApiTokenResponse, + RotateApiTokenResponse, IssueTokenResponse, + RotateTokenResponse, HealthResponse, ) @@ -91,6 +94,9 @@ __all__ = [ "AuthRegisterResponse", "AuthLoginResponse", "GetMeResponse", + "IssueApiTokenResponse", + "RotateApiTokenResponse", "IssueTokenResponse", + "RotateTokenResponse", "HealthResponse", ] diff --git a/elydora/async_client.py b/elydora/async_client.py index cae1d40..068de65 100644 --- a/elydora/async_client.py +++ b/elydora/async_client.py @@ -23,7 +23,8 @@ from .types import ( GetMeResponse, GetOperationResponse, HealthResponse, - IssueTokenResponse, + IssueApiTokenResponse, + RotateApiTokenResponse, JWKSResponse, ListAgentsResponse, ListEpochsResponse, @@ -199,13 +200,21 @@ class AsyncElydoraClient: """Get the current user's profile.""" return await self._request("GET", "/v1/auth/me") - async def issue_token(self, ttl_seconds: Optional[int] = None) -> IssueTokenResponse: + async def issue_api_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse: """Issue an API token with an optional TTL.""" body: Dict[str, Any] = {} if ttl_seconds is not None: body["ttl_seconds"] = ttl_seconds return await self._request("POST", "/v1/auth/token", json_body=body) + async def issue_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse: + """Deprecated: Use issue_api_token() instead.""" + return await self.issue_api_token(ttl_seconds=ttl_seconds) + + async def rotate_api_token(self) -> RotateApiTokenResponse: + """Rotate the current API token and keep the old token in 24h grace.""" + return await self._request("POST", "/v1/auth/rotate", json_body={}) + # ----------------------------------------------------------------- # Agent management # ----------------------------------------------------------------- @@ -300,7 +309,7 @@ class AsyncElydoraClient: async def verify_operation(self, operation_id: str) -> VerifyOperationResponse: """Verify an operation's integrity.""" - return await self._request("POST", f"/v1/operations/{operation_id}/verify") + return await self._request("POST", f"/v1/operations/{operation_id}/verify", json_body={}) # ----------------------------------------------------------------- # Audit diff --git a/elydora/client.py b/elydora/client.py index 27c0f72..e04bd9b 100644 --- a/elydora/client.py +++ b/elydora/client.py @@ -22,7 +22,8 @@ from .types import ( GetMeResponse, GetOperationResponse, HealthResponse, - IssueTokenResponse, + IssueApiTokenResponse, + RotateApiTokenResponse, JWKSResponse, ListAgentsResponse, ListEpochsResponse, @@ -190,13 +191,21 @@ class ElydoraClient: """Get the current user's profile.""" return self._request("GET", "/v1/auth/me") - def issue_token(self, ttl_seconds: Optional[int] = None) -> IssueTokenResponse: + def issue_api_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse: """Issue an API token with an optional TTL.""" body: Dict[str, Any] = {} if ttl_seconds is not None: body["ttl_seconds"] = ttl_seconds return self._request("POST", "/v1/auth/token", json_body=body) + def issue_token(self, ttl_seconds: Optional[int] = None) -> IssueApiTokenResponse: + """Deprecated: Use issue_api_token() instead.""" + return self.issue_api_token(ttl_seconds=ttl_seconds) + + def rotate_api_token(self) -> RotateApiTokenResponse: + """Rotate the current API token and keep the old token in 24h grace.""" + return self._request("POST", "/v1/auth/rotate", json_body={}) + # ----------------------------------------------------------------- # Agent management # ----------------------------------------------------------------- @@ -293,7 +302,7 @@ class ElydoraClient: def verify_operation(self, operation_id: str) -> VerifyOperationResponse: """Verify an operation's integrity.""" - return self._request("POST", f"/v1/operations/{operation_id}/verify") + return self._request("POST", f"/v1/operations/{operation_id}/verify", json_body={}) # ----------------------------------------------------------------- # Audit diff --git a/elydora/types.py b/elydora/types.py index 9828c8c..c4accb7 100644 --- a/elydora/types.py +++ b/elydora/types.py @@ -79,8 +79,8 @@ class Operation(TypedDict): issued_at: int ttl_ms: int nonce: str - subject: Dict[str, Any] - action: Dict[str, Any] + subject: str + action: str payload_hash: str prev_chain_hash: str chain_hash: str @@ -305,9 +305,22 @@ class GetMeResponse(TypedDict): user: User -class IssueTokenResponse(TypedDict): +class IssueApiTokenResponse(TypedDict): token: str expires_at: Optional[int] + token_id: str + + +class RotateApiTokenResponse(TypedDict): + token: str + expires_at: Optional[int] + token_id: str + previous_token_grace_until: int + + +# Backward compatibility aliases (deprecated) +IssueTokenResponse = IssueApiTokenResponse +RotateTokenResponse = RotateApiTokenResponse class HealthResponse(TypedDict):