You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The grace period (running on the signed session until the TTL expires) is now the default and needs no configuration. Online check-ins are opt-in via authforge::OnlineHeartbeat::On. Legacy heartbeat mode values still work behind a deprecation shim: LOCAL maps to the default, SERVER maps to online check-ins. README and AGENTS rewritten with the new vocabulary and a migration section. Version bumped to 1.1.0.
Copy file name to clipboardExpand all lines: AGENTS.md
+38-20Lines changed: 38 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,11 @@
1
-
# AuthForge SDK — AI Agent Reference
1
+
# AuthForge SDK: AI Agent Reference
2
2
3
3
> This file is optimized for AI coding agents (Cursor, Copilot, Claude Code, etc.).
4
4
> It contains everything needed to correctly integrate AuthForge licensing into a project.
5
5
6
6
## What AuthForge does
7
7
8
-
AuthForge is a license key validation service. Your app sends a license key + hardware ID to the AuthForge API, gets back a cryptographically signed response, and runs background heartbeats to maintain the session. If the license is revoked or expired, the heartbeat fails and you handle it (typically exit the app).
8
+
AuthForge is a license key validation service. Your app activates a license key online: it sends the key plus a hardware ID to `POST /auth/validate`, and the server checks revocation, expiry, HWID binding, and credits, then returns an Ed25519-signed session with a TTL. By default the app then runs through the grace period: it keeps running on that signed session without contacting AuthForge (the SDK re-verifies the signed session locally in the background) until the TTL expires. Optionally, you can enable online check-ins: periodic calls to `POST /auth/heartbeat` for fast revocation and concurrent-use detection. If the license is revoked or the session becomes invalid, the background check fails and you handle it (typically exit the app).
9
9
10
10
## Installation
11
11
@@ -20,10 +20,14 @@ Add `authforge_sdk.h` and `authforge_sdk.cpp` to your project, or consume the li
20
20
#include<string>
21
21
22
22
intmain() {
23
+
// Default policy: activate online once, then run through the grace period
24
+
// (no network until the session TTL expires). To enable online check-ins,
25
+
// pass authforge::OnlineHeartbeat::On as the 4th argument.
23
26
authforge::AuthForgeClient client(
24
27
"YOUR_APP_ID",
25
28
"YOUR_APP_SECRET",
26
-
"SERVER",
29
+
"YOUR_PUBLIC_KEY", // required: base64 Ed25519 key from the dashboard
|`publicKey`|`std::string` / `std::vector<std::string>`| yes | none | Base64 Ed25519 public key from the dashboard (3rd positional arg). The string overload accepts a comma-separated trust list; a `std::vector<std::string>` overload takes a rotation set. The SDK trusts a signature matching **any** key |
64
+
|`onlineHeartbeat`|`authforge::OnlineHeartbeat`| no |`OnlineHeartbeat::Off`|`Off` (default): after activation, run through the grace period on the signed session with no network calls. `On`: enable online check-ins via `/auth/heartbeat` for fast revocation and concurrent-use detection |
65
+
|`heartbeatInterval`|`int`| no |`900`| Seconds between background checks (minimum `10`). With online check-ins enabled, revocations apply on the next check-in |
61
66
|`apiBaseUrl`|`std::string`| no |`kDefaultApiBaseUrl` (`https://auth.authforge.cc`) | API base URL |
62
-
|`onFailure`|`std::function<void(const std::string&, const std::exception*)>`| no |`nullptr`| Failure callback for `Login` / heartbeat; if null, `std::exit(1)` (not used by `ValidateLicense`) |
67
+
|`onFailure`|`std::function<void(const std::string&, const std::exception*)>`| no |`nullptr`| Failure callback for `Login` / background checks; if null, `std::exit(1)` (not used by `ValidateLicense`) |
63
68
|`requestTimeout`|`int`| no |`15`| HTTP timeout (seconds) |
64
-
|`ttlSeconds`|`int`| no |`0` (server default: 86400) | Requested session token lifetime. `0` means "server default". Server clamps to `[3600, 604800]`; preserved across heartbeat refreshes. |
69
+
|`ttlSeconds`|`int`| no |`0` (server default: 86400) | Requested grace period duration in seconds (the session token lifetime). `0` means "server default" (24h). Server clamps to `[3600, 604800]` (1h to 7d); preserved across heartbeat refreshes. |
65
70
|`hwidOverride`|`std::string`| no |`""`| Optional custom HWID/subject string. When non-empty (for example `tg:123456789`), the SDK sends it instead of generating a machine fingerprint. |
66
71
67
72
For Telegram/Discord bot flows, prefer immutable IDs (`tg:<user_id>`, `discord:<user_id>`) instead of usernames.
68
73
74
+
## Migrating from heartbeatMode
75
+
76
+
Earlier versions took a `std::string heartbeatMode` (`"LOCAL"` or `"SERVER"`) as the 4th constructor parameter:
77
+
78
+
-`"LOCAL"` maps to the default (grace period behavior): drop the argument entirely.
79
+
-`"SERVER"` maps to `authforge::OnlineHeartbeat::On`.
80
+
81
+
The old string-mode constructors still work and behave exactly as before, but they emit a deprecation warning at compile time. Never describe the grace period as a "LOCAL mode" or "offline mode"; it is the default behavior of every activated session.
82
+
69
83
## Billing model
70
84
71
85
- Each `Login()` or `ValidateLicense()` calls `/auth/validate` and costs **1 credit**.
72
-
- Heartbeats cost **1 credit per 10 successful calls** (billed on every 10th heartbeat).
73
-
- Keep heartbeat interval at or above 10 seconds. `/auth/heartbeat` is limited to 6 requests/minute per license key; cost still scales with how many heartbeats you send.
74
-
- Revocations take effect on the **next** heartbeat regardless of interval.
86
+
- Online check-ins cost **1 credit per 10 successful calls** (billed on every 10th heartbeat).
87
+
- The default grace period policy makes no network calls after activation and costs nothing until the next activation.
88
+
- Keep the check-in interval at or above 10 seconds. `/auth/heartbeat` is limited to 6 requests/minute per license key; cost still scales with how many check-ins you send.
89
+
- Revocations take effect on the **next** check-in regardless of interval.
75
90
76
91
## Methods
77
92
78
93
| Method | Returns | Description |
79
94
|--------|---------|-------------|
80
-
|`Login(const std::string&)`|`bool`|Validates license and starts heartbeat|
81
-
|`ValidateLicense(const std::string&)`|`ValidateLicenseResult`| Same validate + signatures; no session/heartbeat; **never** calls `onFailure` or `std::exit`|
82
-
|`Logout()`|`void`| Stops heartbeat and clears state |
95
+
|`Login(const std::string&)`|`bool`|Activates the license online and starts the background check loop|
96
+
|`ValidateLicense(const std::string&)`|`ValidateLicenseResult`| Same validate + signatures; no session/background checks; **never** calls `onFailure` or `std::exit`|
97
+
|`Logout()`|`void`| Stops background checks and clears state |
-`replay_detected` is validate-only. `rate_limited` can be returned by `/auth/validate` and `/auth/heartbeat` (heartbeat is license-limited at 6/min and has no app-layer IP limit).
109
+
-`app_burn_cap_reached` means the app's configured credit burn cap is hit; `revoke_requires_session` means a pre-session self-ban tried to revoke a license (only session-authenticated self-ban can revoke).
110
+
-`session_expired` is what the default background check reports when the grace period ends; the app must activate online again.
94
111
95
112
## Common patterns
96
113
@@ -116,7 +133,8 @@ Use the `onFailure` callback; distinguish `reason` (`login_failed`, `heartbeat_f
116
133
117
134
## Do NOT
118
135
119
-
- Do not hardcode the app secret as a plain string literal in source — use environment variables or encrypted config
120
-
- Do not omit `onFailure` — without it, failures call `std::exit(1)` without your cleanup
121
-
- Do not call `Login` on every app action — call once at startup; heartbeats handle the rest
122
-
- Do not use `heartbeatMode``"LOCAL"` unless the app has no internet after initial auth
136
+
- Do not hardcode the app secret as a plain string literal in source; use environment variables or encrypted config
137
+
- Do not omit `onFailure`; without it, failures call `std::exit(1)` without your cleanup
138
+
- Do not call `Login` on every app action; call once at startup, the background checks handle the rest
139
+
- Do not pass the deprecated `heartbeatMode` strings (`"LOCAL"` / `"SERVER"`) in new code; use the default for grace period behavior or `authforge::OnlineHeartbeat::On` for online check-ins
140
+
- Do not enable online check-ins if the app loses internet access after initial activation; the default grace period behavior covers that case within the session TTL
0 commit comments