AXIAM C++ SDK 1.0.0-alpha8
Authentication, authorization, JWKS & route guards (REST + mTLS)
Loading...
Searching...
No Matches
client.hpp
Go to the documentation of this file.
1// axiam::Client — the SDK's REST surface. Built via a fluent builder that
2// enforces the §5 tenant-context requirement, wires strict TLS (§6) and optional
3// mTLS (§6.1), captures/echoes CSRF (§3), persists cookies (§4), injects the
4// tenant header on every request (§5), and performs single-flight token
5// refresh (§9). Method names are snake_case per §1.
6#pragma once
7
8#include <chrono>
9#include <functional>
10#include <future>
11#include <memory>
12#include <optional>
13#include <string>
14#include <vector>
15
16#include "axiam/errors.hpp"
17#include "axiam/jwks.hpp"
18#include "axiam/telemetry.hpp"
19#include "axiam/transport.hpp"
20#include "axiam/types.hpp"
21
22namespace axiam {
23
24class Client {
25public:
26 class Builder {
27 public:
31 Builder& base_url(std::string url);
32 Builder& tenant_slug(std::string slug);
33 Builder& tenant_id(std::string id);
34 Builder& org_slug(std::string slug);
35 Builder& org_id(std::string id);
36
39 Builder& with_custom_ca(std::string ca_pem);
40
43 Builder& with_client_cert(std::string cert_pem, std::string key_pem);
44
45 Builder& connect_timeout(std::chrono::milliseconds ms);
46 Builder& request_timeout(std::chrono::milliseconds ms);
47
59
63
73 Builder& retry_enabled(bool enabled);
74
87 Builder& decision_memo_ttl(std::chrono::milliseconds ttl);
88
93
99
100 private:
101 friend class Client;
102 std::string base_url_;
103 std::optional<std::string> tenant_slug_;
104 std::optional<std::string> tenant_id_;
105 std::optional<std::string> org_slug_;
106 std::optional<std::string> org_id_;
107 unsigned max_concurrent_requests_ = 16;
108 std::string custom_ca_pem_;
109 std::string client_cert_pem_;
110 std::string client_key_pem_;
111 std::chrono::milliseconds connect_timeout_{10000};
112 std::chrono::milliseconds request_timeout_{30000};
113 Transport transport_; // empty => default libcurl
114 bool retry_enabled_ = true; // §16.1: the switch MUST default to on
115 // Stored UNCLAMPED, so the §19 config_clamped event can report what the
116 // caller actually asked for rather than the value it was turned into.
117 std::chrono::milliseconds decision_memo_ttl_{0};
118 TelemetryHook telemetry_hook_;
119 };
120
121 static Builder builder();
122
123 // ---- §1 canonical operations (snake_case) ----
124 LoginResult login(const std::string& username_or_email, const std::string& password);
128 const std::string& totp_code);
131 LoginResult verify_mfa(const std::string& challenge_token, const std::string& totp_code);
133 void logout();
134 AccessDecision check_access(const std::string& action, const std::string& resource_id,
135 std::optional<std::string> scope = std::nullopt,
136 std::optional<std::string> subject_id = std::nullopt);
137 AccessDecision can(const std::string& action, const std::string& resource_id,
138 std::optional<std::string> scope = std::nullopt,
139 std::optional<std::string> subject_id = std::nullopt);
140 std::vector<AccessDecision> batch_check(const std::vector<AccessCheck>& checks);
141
145
146 // ---- Accepted per-language async twins (§1, C++ row: std::future) ----
147 std::future<LoginResult> login_async(std::string username_or_email, std::string password);
148 std::future<TokenPair> refresh_async();
149 std::future<AccessDecision> check_access_async(std::string action, std::string resource_id,
150 std::optional<std::string> scope = std::nullopt,
151 std::optional<std::string> subject_id = std::nullopt);
152 std::future<std::vector<AccessDecision>> batch_check_async(std::vector<AccessCheck> checks);
153
154 // ---- Introspection (used by tests / middleware) ----
157
165 void _set_retry_test_seams(std::function<double()> jitter,
166 std::function<void(std::chrono::milliseconds)> sleeper);
168 std::optional<std::string> csrf_token() const;
170 bool has_session() const;
174 const std::string& tenant_header() const;
175
195 void close();
196
197private:
198 struct Impl;
199 std::shared_ptr<Impl> p_;
200 explicit Client(std::shared_ptr<Impl> impl);
201};
202
203} // namespace axiam
Definition client.hpp:26
Builder & tenant_id(std::string id)
Builder & request_timeout(std::chrono::milliseconds ms)
Builder & telemetry_hook(TelemetryHook hook)
§19: install a telemetry sink.
Builder & with_custom_ca(std::string ca_pem)
§6: add a custom CA (PEM) to the trust chain.
Builder & connect_timeout(std::chrono::milliseconds ms)
Builder & retry_enabled(bool enabled)
§16: enable or disable the bounded read-only retry policy.
Client build()
Validates required fields and constructs the client.
Builder & base_url(std::string url)
Server base URL.
Builder & transport(Transport t)
Override the HTTP transport (test seam).
Builder & decision_memo_ttl(std::chrono::milliseconds ttl)
§17: enable the client-side decision memo with a TTL.
Builder & tenant_slug(std::string slug)
Builder & org_slug(std::string slug)
Builder & max_concurrent_requests(unsigned n)
How many requests this client may have in flight at once (default 16).
Builder & org_id(std::string id)
Builder & with_client_cert(std::string cert_pem, std::string key_pem)
§6.1: present a client identity certificate (PEM chain + PEM key) for mutual TLS.
Definition client.hpp:24
const std::string & tenant_header() const
Tenant identifier injected as X-Tenant-ID on every request (§5).
LoginResult login(const std::string &username_or_email, const std::string &password)
JwksVerifier & jwks()
Shared JWKS verifier bound to this client's transport + base URL.
AccessDecision can(const std::string &action, const std::string &resource_id, std::optional< std::string > scope=std::nullopt, std::optional< std::string > subject_id=std::nullopt)
TokenPair refresh()
void close()
Deterministic shutdown (CONTRACT.md §18).
std::future< LoginResult > login_async(std::string username_or_email, std::string password)
LoginResult verify_mfa(const Sensitive< std::string > &challenge_token, const std::string &totp_code)
Complete an MFA challenge.
int refresh_call_count() const
Number of times a network refresh call was actually issued (§9 assertion).
std::future< std::vector< AccessDecision > > batch_check_async(std::vector< AccessCheck > checks)
AccessDecision check_access(const std::string &action, const std::string &resource_id, std::optional< std::string > scope=std::nullopt, std::optional< std::string > subject_id=std::nullopt)
std::future< TokenPair > refresh_async()
LoginResult verify_mfa(const std::string &challenge_token, const std::string &totp_code)
Overload for a challenge token obtained out of band (e.g.
std::optional< std::string > csrf_token() const
Currently-stored CSRF token, if any (§3).
static Builder builder()
DeviceAuth authenticate_device()
§6.1 device / service-account authentication via the configured mTLS client certificate (POST /api/v1...
bool has_session() const
Whether a session has been established (login/verify_mfa succeeded).
std::future< AccessDecision > check_access_async(std::string action, std::string resource_id, std::optional< std::string > scope=std::nullopt, std::optional< std::string > subject_id=std::nullopt)
void _set_retry_test_seams(std::function< double()> jitter, std::function< void(std::chrono::milliseconds)> sleeper)
Test seam: replace the §16 jitter source and the sleep.
std::vector< AccessDecision > batch_check(const std::vector< AccessCheck > &checks)
Definition jwks.hpp:43
Wraps secret material (access tokens, mTLS private keys).
Definition sensitive.hpp:26
Definition authenticator.hpp:40
std::function< HttpResponse(const HttpRequest &)> Transport
The transport seam. Injectable; defaults to the libcurl implementation.
Definition transport.hpp:56
std::function< void(const TelemetryEvent &)> TelemetryHook
A caller-supplied telemetry sink (§19).
Definition telemetry.hpp:134
Result of an access check (CheckAccessResponse).
Definition types.hpp:86
mTLS device authentication result (POST /api/v1/auth/device).
Definition types.hpp:51
Result of login / verify_mfa.
Definition types.hpp:27
Result of a token refresh (§9).
Definition types.hpp:45