@witnium-tech/witniumchain 0.3.0 → 0.5.0

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.
package/README.md CHANGED
@@ -1,25 +1,43 @@
1
1
  # @witnium-tech/witniumchain
2
2
 
3
- TypeScript SDK for the WitniumChain accounts service identity, billing,
4
- organisation administration, OAuth sessions, and delegated-signing-key
5
- management.
3
+ TypeScript SDK for WitniumChain — the canonical single client for both the
4
+ accounts service (identity, billing, OAuth, delegated keys, witness writes)
5
+ and the chain-api read surfaces (contract info, witness lookup, wallet
6
+ balance, dashboards). The two-service backend is hidden behind one
7
+ `WitniumchainClient` class; you give it one OAuth access token and it knows
8
+ where each call belongs.
6
9
 
7
10
  ## Status
8
11
 
9
- **v0.1low-level "shell" client.** One method per OpenAPI route, five
10
- auth modes selectable on a single client. Thread 4 of Phase C will layer
11
- three higher-level clients on top:
12
-
13
- - `WitniumchainClient` (end-user) wraps signup, login, subscriptions,
14
- delegated-key one-call provisioning, account management.
15
- - `WitniumchainOrgClient` (org admin) wraps user provisioning, Stripe
16
- Connect onboarding.
17
- - `WitniumchainAdminClient` (sysadmin) wraps org lifecycle, key
18
- rotation, credit adjustment.
19
-
20
- For now, this shell client is what's published. Every type comes from the
21
- OpenAPI spec via `openapi-typescript`; a CI drift test in the parent repo
22
- gates regeneration on every change.
12
+ **v0.5adds OAuth 2.1 + PKCE login helpers** on top of the v0.4 surface:
13
+
14
+ - All 41 accounts routes (five auth modes: session / OAuth / org / admin / signed)
15
+ - 9 chain-api read methods, routed to `chainBaseUrl`, reusing the same OAuth
16
+ `accessToken` (accounts mints tokens with `aud=https://api.witniumchain.com`,
17
+ so they're valid against both services unchanged)
18
+ - Three layered clients on top: `WitniumchainClient` (end-user),
19
+ `WitniumchainOrgClient` (org admin), `WitniumchainAdminClient` (sysadmin)
20
+ - **`beginOAuthLogin` / `completeOAuthLogin` / `refreshAccessToken` / `signOut`**
21
+ browser-side Authorization-Code + PKCE login flow. Discovery-driven
22
+ endpoint resolution (`/.well-known/openid-configuration`), PKCE verifier
23
+ in `sessionStorage`, access token held in memory only, transparent 401-retry
24
+ with single-flight refresh-token rotation. Refresh tokens are delivered as
25
+ an HttpOnly `wac_refresh` cookie scoped to `Path=/token` — JavaScript never
26
+ touches them. Non-browser callers (Node SSR, native apps without a cookie
27
+ jar) fall back to in-band refresh-token delivery; the SDK handles both.
28
+ - **`client.mfa.totp.enroll/confirm/disable` + `client.mfa.recoveryCodes.regenerate`** —
29
+ TOTP MFA self-management. `enroll` returns the secret + otpauth URL (render
30
+ as a QR code in your dashboard with any QR lib); `confirm` validates the
31
+ first code and returns 10 single-use recovery codes (shown ONCE).
32
+
33
+ What's NOT exposed (by design): chain-api v5 writes — those are proxied by
34
+ accounts' v5 surface which adds credit reservation + idempotency + scope
35
+ checks. Calling chain-api writes directly would burn credits without
36
+ billing them. See `docs/PLAN-PHASE-SDK-UNIFIED.md` for the routing rules.
37
+
38
+ Every type comes from the published OpenAPI specs of both services via
39
+ `openapi-typescript`. `npm run openapi:check` regenerates and fails on
40
+ diff; it runs ahead of every `npm publish`.
23
41
 
24
42
  ## Install
25
43
 
@@ -29,14 +47,14 @@ npm install @witnium-tech/witniumchain
29
47
 
30
48
  ## Auth model
31
49
 
32
- The accounts service accepts five distinct credentials. Configure whichever
50
+ The SDK accepts five distinct credentials. Configure whichever
33
51
  you need on the client; methods that require a credential you didn't supply
34
52
  throw at call time.
35
53
 
36
54
  | Credential | Header / Cookie | Used by |
37
55
  |---|---|---|
38
56
  | `sessionCookie` | `Cookie: wac_session=…` | `/v1/auth/logout`, `/v1/account/*`, `/v1/billing/*`, `/v1/keys/*`, `/v1/contracts/{pause,unpause}`, `/v1/oauth/sessions*` |
39
- | `accessToken` | `Authorization: Bearer <JWT>` | `/v1/users/me/delegated-keys/*`, `/v1/sign` |
57
+ | `accessToken` | `Authorization: Bearer <JWT>` | `/v1/users/me/delegated-keys/*`, `/v1/sign`, **all chain-api reads** |
40
58
  | `orgApiKey` | `Authorization: Bearer wcorg_live_…` | `/v1/orgs/me/*` |
41
59
  | `adminToken` | `Authorization: Bearer <ADMIN_TOKEN>` | `/v1/admin/*` |
42
60
  | `signedRequest` | `X-Witnium-Key/Timestamp/Signature` | `/v1/contracts/{addr}/witnesses/{propose,sign,finalize,revoke}` |
@@ -45,6 +63,30 @@ Public routes need no credential (`/v1/auth/{signup,verify,login,…}`,
45
63
  `/v1/contracts/provision`, `GET /v1/contracts/{addr}/witnesses/{id}`,
46
64
  `/health/*`).
47
65
 
66
+ ## Two services, one client
67
+
68
+ Accounts and chain-api are separate services today (consolidation is a
69
+ later phase). The SDK hides that:
70
+
71
+ ```ts
72
+ const client = new WitniumchainClient({
73
+ baseUrl: 'https://auth.witniumchain.com', // accounts
74
+ chainBaseUrl: 'https://api.witniumchain.com', // chain-api (omit if you only need accounts)
75
+ accessToken: oauthBearerJwt,
76
+ });
77
+
78
+ // Writes / billing / auth → accounts (baseUrl)
79
+ await client.proposeWitnessV5('0xabc', { ... });
80
+
81
+ // Reads of on-chain state → chain-api (chainBaseUrl)
82
+ const witness = await client.getWitnessV5('0xabc', witnessId);
83
+ const balance = await client.getWalletBalance('0xabc');
84
+ ```
85
+
86
+ If you call a chain-api method without `chainBaseUrl` configured, the SDK
87
+ throws a clear `WitniumchainApiError` at call time naming the missing
88
+ config — no silent fallback to a wrong base URL.
89
+
48
90
  ## Examples
49
91
 
50
92
  ### End-user signup + login
@@ -97,6 +139,40 @@ const { organization, apiKey } = await sys.createOrganization({
97
139
  // `apiKey` is shown ONCE — store it now.
98
140
  ```
99
141
 
142
+ ### Sign in with Witnium (Authorization Code + PKCE)
143
+
144
+ For a browser SPA (e.g. a Lovable app) that wants to authenticate end-users
145
+ against a Witnium org. No backend required.
146
+
147
+ ```ts
148
+ const client = new WitniumchainClient({
149
+ baseUrl: 'https://auth.witniumchain.com',
150
+ oauthClientId: 'your-registered-client-id',
151
+ });
152
+
153
+ // 1. Kick off login. The SDK generates a PKCE pair, stashes the verifier in
154
+ // sessionStorage, and returns the URL to send the user to.
155
+ const { authorizationUrl } = await client.beginOAuthLogin({
156
+ redirectUri: 'https://your-app.example/callback',
157
+ });
158
+ window.location.assign(authorizationUrl);
159
+
160
+ // 2. On the callback page, complete the exchange. Returns the access token
161
+ // (the SDK ALSO holds it in memory; subsequent BearerJWT calls Just Work).
162
+ const { accessToken, expiresAt } = await client.completeOAuthLogin(
163
+ window.location.href,
164
+ );
165
+ window.history.replaceState({}, '', window.location.pathname); // strip ?code=…
166
+
167
+ // 3. Use the SDK normally. When the access token expires, the SDK refreshes
168
+ // transparently on the next call. You only need to redirect to login if
169
+ // refresh itself fails (refresh token revoked or expired).
170
+ const { keys } = await client.listDelegatedKeys();
171
+
172
+ // 4. Sign-out clears in-memory tokens.
173
+ client.signOut();
174
+ ```
175
+
100
176
  ### OAuth API — delegated-key + sign
101
177
 
102
178
  ```ts