@certysign/sdk 2.3.0 → 2.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
@@ -19,6 +19,7 @@ Official Node.js SDK for **CertySign Trust Services** — hash-based digital sig
19
19
  - [client.hasher — Local Document Hashing](#clienthasher--local-document-hashing)
20
20
  - [client.embedder — Local Signature Embedding](#clientembedder--local-signature-embedding)
21
21
  - [client.dashboard — SDK Analytics](#clientdashboard--sdk-analytics)
22
+ - [client.identity — Identity Verification](#clientidentity--identity-verification)
22
23
  - [client.certificates — X.509 Certificate Management](#clientcertificates--x509-certificate-management)
23
24
  - [client.pki — PKI Infrastructure](#clientpki--pki-infrastructure)
24
25
  - [client.envelopes — Envelope Management](#clientenvelopes--envelope-management)
@@ -862,6 +863,81 @@ const { data } = await client.dashboard.getDocuments({
862
863
 
863
864
  ---
864
865
 
866
+ ### `client.identity` — Identity Verification
867
+
868
+ Verify a national ID against the issuing authority (IPRS for Kenya) and get the
869
+ biographic record — the same pipeline CertySign uses to onboard its own signers.
870
+
871
+ **Registry-first:** an ID already verified anywhere on the CertySign network is served
872
+ from our registry (`source: 'registry'`) with no authority call. A *rejected* ID is
873
+ cached briefly too, so repeated lookups of the same bad number don't incur repeated
874
+ charges. Pass `forceRefresh: true` to bypass both.
875
+
876
+ Requires the **`identity:verify`** scope, which is **not granted by default** — enable it
877
+ under *Settings → Security → SDK API Keys → Permissions*.
878
+
879
+ > **Consent is mandatory.** This processes another person's personal data, so
880
+ > `consent.obtained: true` is required — the SDK throws *before* making the call if it's
881
+ > missing. Your attestation, API key and IP are written to your tenant's audit trail on
882
+ > every call, evidencing a lawful basis under the Kenya Data Protection Act 2019.
883
+ > Store the returned `identityReference` instead of the raw ID number — the full number
884
+ > is never returned to you.
885
+
886
+ #### `verify(params)` — Verify a national ID
887
+
888
+ ```js
889
+ const { data } = await client.identity.verify({
890
+ country: 'KE',
891
+ idNumber: '12345678',
892
+ idType: 'NATIONAL_ID', // optional — this is the default
893
+ consent: {
894
+ obtained: true, // REQUIRED
895
+ reference: 'loan-app-8821', // optional — your own consent record id
896
+ purpose: 'KYC onboarding' // optional
897
+ },
898
+ // Optional cross-check hints: firstName, lastName, dob
899
+ // forceRefresh: true // skip caches, go straight to the authority
900
+ });
901
+
902
+ // data.verified — true when the authority confirmed the ID
903
+ // data.decision — 'verified' | 'rejected' | 'provisional' | 'unknown'
904
+ // data.identityReference — privacy-preserving reference; store THIS
905
+ // data.idLast4 — last 4 digits only
906
+ // data.person — fullName, firstName, middleName, lastName,
907
+ // dob, gender, nationality
908
+ // data.source — 'registry' (cached) | 'authority' (fresh lookup)
909
+ // data.cached — true when served without an authority call
910
+ // data.resultCode — authority code, e.g. '1012' = valid ID
911
+ // data.checkedAt — ISO timestamp
912
+ ```
913
+
914
+ #### `isVerified(params)` — Boolean convenience wrapper
915
+
916
+ ```js
917
+ const ok = await client.identity.isVerified({
918
+ country: 'KE', idNumber: '12345678',
919
+ consent: { obtained: true, purpose: 'KYC onboarding' }
920
+ });
921
+ ```
922
+
923
+ > A thrown error means **"we couldn't check"**, which is *not* the same as
924
+ > **"not verified"**. Never collapse the two — treat an error as retry/escalate,
925
+ > not as a failed identity.
926
+
927
+ #### Errors
928
+
929
+ | Code | HTTP | Meaning |
930
+ |---|---|---|
931
+ | `CONSENT_REQUIRED` | 403 | Consent attestation missing |
932
+ | `INSUFFICIENT_BALANCE` | 402 | Checked *before* any authority call — you're never charged for a lookup you couldn't afford |
933
+ | `COUNTRY_NOT_SUPPORTED` / `ID_TYPE_NOT_SUPPORTED` | 422 | Only `KE` / `NATIONAL_ID` today |
934
+ | `VERIFICATION_UNAVAILABLE` | 502 | Authority unreachable — not billed, retry later |
935
+
936
+ **Billing:** one `ekyc_check` per distinct ID per day. A *negative* result is billable
937
+ (the authority was queried); an *outage* is never billed.
938
+
939
+ ---
940
+
865
941
  ### `client.certificates` — X.509 Certificate Management
866
942
 
867
943
  #### `getActive()` — Get your tenant's active signing certificate
package/package.json CHANGED
@@ -1,54 +1,54 @@
1
- {
2
- "name": "@certysign/sdk",
3
- "version": "2.3.0",
4
- "description": "Official Node.js SDK for CertySign — hash-based digital signing, X.509 certificates, and PKI services. Documents never leave your system.",
5
- "main": "src/index.js",
6
- "types": "src/index.d.ts",
7
- "files": [
8
- "src/",
9
- "README.md"
10
- ],
11
- "scripts": {
12
- "test": "jest --coverage",
13
- "lint": "eslint src/**/*.js",
14
- "build:types": "npx tsc --emitDeclarationOnly"
15
- },
16
- "keywords": [
17
- "certysign",
18
- "digital-signature",
19
- "pki",
20
- "x509",
21
- "pdf-signing",
22
- "document-signing",
23
- "hash-based-signing",
24
- "kenya",
25
- "pades",
26
- "xmldsig",
27
- "otp"
28
- ],
29
- "author": "CertySign Limited <sdk@certysign.io>",
30
- "license": "MIT",
31
- "engines": {
32
- "node": ">=18.0.0"
33
- },
34
- "dependencies": {
35
- "axios": "^1.6.0",
36
- "form-data": "^4.0.0",
37
- "node-forge": "^1.3.3",
38
- "pdf-lib": "^1.17.1"
39
- },
40
- "devDependencies": {
41
- "jest": "^29.7.0"
42
- },
43
- "repository": {
44
- "type": "git",
45
- "url": "git+https://github.com/certysign/sdk-node.git"
46
- },
47
- "homepage": "https://docs.certysign.io/sdk",
48
- "bugs": {
49
- "url": "https://github.com/certysign/sdk-node/issues"
50
- },
51
- "publishConfig": {
52
- "access": "public"
53
- }
54
- }
1
+ {
2
+ "name": "@certysign/sdk",
3
+ "version": "2.5.0",
4
+ "description": "Official Node.js SDK for CertySign — hash-based digital signing, X.509 certificates, and PKI services. Documents never leave your system.",
5
+ "main": "src/index.js",
6
+ "types": "src/index.d.ts",
7
+ "files": [
8
+ "src/",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "test": "jest --coverage",
13
+ "lint": "eslint src/**/*.js",
14
+ "build:types": "npx tsc --emitDeclarationOnly"
15
+ },
16
+ "keywords": [
17
+ "certysign",
18
+ "digital-signature",
19
+ "pki",
20
+ "x509",
21
+ "pdf-signing",
22
+ "document-signing",
23
+ "hash-based-signing",
24
+ "kenya",
25
+ "pades",
26
+ "xmldsig",
27
+ "otp"
28
+ ],
29
+ "author": "CertySign Limited <sdk@certysign.io>",
30
+ "license": "MIT",
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "dependencies": {
35
+ "axios": "^1.6.0",
36
+ "form-data": "^4.0.0",
37
+ "node-forge": "^1.3.3",
38
+ "pdf-lib": "^1.17.1"
39
+ },
40
+ "devDependencies": {
41
+ "jest": "^29.7.0"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/certysign/sdk-node.git"
46
+ },
47
+ "homepage": "https://docs.certysign.io/sdk",
48
+ "bugs": {
49
+ "url": "https://github.com/certysign/sdk-node/issues"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ }
54
+ }
package/src/index.js CHANGED
@@ -1,214 +1,228 @@
1
- /**
2
- * @fileoverview CertySign SDK for Node.js
3
- *
4
- * Official client library for CertySign Trust Services — digital document
5
- * signing, X.509 certificate issuance, and PKI operations for East Africa.
6
- *
7
- * @example Basic setup
8
- * ```js
9
- * const { CertySignClient } = require('@certysign/sdk');
10
- *
11
- * const client = new CertySignClient({
12
- * publicKey: 'cs_pk_...',
13
- * secretKey: 'cs_sk_...'
14
- * });
15
- * ```
16
- */
17
-
18
- 'use strict';
19
-
20
- const { HttpClient, CertySignError } = require('./lib/HttpClient');
21
- const { SigningResource } = require('./lib/SigningResource');
22
- const { HashSigningResource } = require('./lib/HashSigningResource');
23
- const { CertificateResource } = require('./lib/CertificateResource');
24
- const { PkiResource } = require('./lib/PkiResource');
25
- const { EnvelopeResource } = require('./lib/EnvelopeResource');
26
- const { SigningSessionResource } = require('./lib/SigningSessionResource');
27
- const { DashboardResource } = require('./lib/DashboardResource');
28
- const { DocumentHasher } = require('./lib/DocumentHasher');
29
- const { SignatureEmbedder } = require('./lib/SignatureEmbedder');
30
-
31
- /**
32
- * CertySign API client.
33
- *
34
- * Resources are accessed as properties:
35
- * - client.sign — hash-based document signing (documents stay local)
36
- * - client.sessions — multi-recipient signing sessions with OTP verification
37
- * - client.dashboard — SDK usage analytics (stats, recipients, documents)
38
- * - client.certificates — X.509 certificate lifecycle (issue, verify, status, getActive)
39
- * - client.pki — PKI infrastructure (CRL, OCSP, CA chain, info)
40
- * - client.envelopes — envelope management (create, upload, send, sign, audit)
41
- * - client.hasher — local document hashing utility
42
- * - client.embedder — local signature embedding (PDF, XML, JSON)
43
- * - client.legacySign — legacy file-upload signing (deprecated)
44
- *
45
- * @example Hash-based signing (documents never leave your system)
46
- * const { CertySignClient } = require('@certysign/sdk');
47
- *
48
- * const client = new CertySignClient({
49
- * publicKey: process.env.CERTYSIGN_PUBLIC_KEY,
50
- * secretKey: process.env.CERTYSIGN_SECRET_KEY,
51
- * environment: 'production'
52
- * });
53
- *
54
- * // 1. Hash locally → sign remotely → embed locally
55
- * const result = await client.sign.hashAndSign({
56
- * document: fs.readFileSync('./contract.pdf'),
57
- * fileName: 'contract.pdf',
58
- * reason: 'Contract approval'
59
- * });
60
- *
61
- * // 2. Embed signature into the PDF on your system
62
- * const signedPdf = await client.embedder.embedInPdf(
63
- * fs.readFileSync('./contract.pdf'),
64
- * {
65
- * signature: result.data.signature,
66
- * certificate: result.data.certificate,
67
- * chain: result.data.chain,
68
- * signerName: 'Dr. Amina Okonkwo',
69
- * reason: 'Contract approval',
70
- * certSerialNumber: result.data.certSerialNumber
71
- * }
72
- * );
73
- * fs.writeFileSync('./contract-signed.pdf', signedPdf);
74
- */
75
- class CertySignClient {
76
- /**
77
- * @param {ClientOptions} options
78
- */
79
- constructor(options = {}) {
80
- const {
81
- publicKey,
82
- secretKey,
83
- baseUrl,
84
- environment = 'production',
85
- timeout,
86
- retries,
87
- debug = false,
88
- tsaUrl,
89
- } = options;
90
-
91
- if (!publicKey) throw new Error('CertySignClient: publicKey is required');
92
- if (!secretKey) throw new Error('CertySignClient: secretKey is required');
93
-
94
- // Resolve base URL from environment if not explicitly provided
95
- const resolvedBaseUrl = baseUrl ?? CertySignClient.BASE_URLS[environment];
96
- if (!resolvedBaseUrl) {
97
- throw new Error(
98
- `CertySignClient: unknown environment "${environment}". ` +
99
- `Expected one of: ${Object.keys(CertySignClient.BASE_URLS).join(', ')} ` +
100
- `or provide baseUrl directly.`
101
- );
102
- }
103
-
104
- this._http = new HttpClient({
105
- publicKey,
106
- secretKey,
107
- baseUrl: resolvedBaseUrl,
108
- timeout,
109
- retries,
110
- debug
111
- });
112
-
113
- // ── Resource objects ──
114
- this.sign = new HashSigningResource(this._http); // Hash-based signing (documents stay local)
115
- this.legacySign = new SigningResource(this._http); // Legacy file-upload signing
116
- this.certificates = new CertificateResource(this._http);
117
- this.pki = new PkiResource(this._http);
118
- this.envelopes = new EnvelopeResource(this._http);
119
- this.sessions = new SigningSessionResource(this._http); // Multi-recipient signing sessions
120
- this.dashboard = new DashboardResource(this._http); // SDK usage analytics
121
- this.hasher = new DocumentHasher(); // Local document hashing
122
-
123
- // TSA URL: explicit > environment-derived
124
- const resolvedTsaUrl = tsaUrl ?? CertySignClient.TSA_URLS[environment] ?? null;
125
- this.embedder = new SignatureEmbedder({ tsaUrl: resolvedTsaUrl }); // PAdES-T when TSA URL available
126
-
127
- this.publicKey = publicKey;
128
- this.environment = environment;
129
- this.baseUrl = resolvedBaseUrl;
130
- this.tsaUrl = resolvedTsaUrl;
131
- }
132
-
133
- /**
134
- * Environment → base URL mapping.
135
- * Override any entry via the `baseUrl` constructor option.
136
- */
137
- static get BASE_URLS() {
138
- return {
139
- production: 'https://core.certysign.io',
140
- staging: 'https://service.certysign.io',
141
- development: 'http://localhost:8000',
142
- test: 'http://localhost:8000'
143
- };
144
- }
145
-
146
- /**
147
- * Environment → TSA URL mapping.
148
- * Override via the `tsaUrl` constructor option.
149
- */
150
- static get TSA_URLS() {
151
- return {
152
- production: 'https://tsa.certysign.io',
153
- staging: 'https://tsa-staging.certysign.io',
154
- development: 'http://localhost:5015',
155
- test: 'http://localhost:5015'
156
- };
157
- }
158
-
159
- /**
160
- * Verify that the API key is valid and return the key metadata.
161
- * Useful as a "ping" / health check at startup.
162
- *
163
- * @returns {Promise<{ success: boolean, data: { keyName, permissions, environment, tenantId } }>}
164
- *
165
- * @example
166
- * const { data } = await client.ping();
167
- * console.log('Connected as:', data.keyName);
168
- * console.log('Permissions:', data.permissions);
169
- */
170
- async ping() {
171
- // Issue a lightweight request; GET /pki/info is cheap and requires pki:info
172
- try {
173
- const result = await this._http.get('/sdk/v1/pki/info');
174
- return {
175
- success: true,
176
- data: {
177
- keyName: result.data?.keyName,
178
- permissions: result.data?.permissions,
179
- environment: result.data?.environment ?? this.environment,
180
- tenantId: result.data?.tenantId,
181
- caInitialized: result.data?.status?.initialized
182
- }
183
- };
184
- } catch (err) {
185
- return { success: false, error: err.message, code: err.code };
186
- }
187
- }
188
- }
189
-
190
- /**
191
- * @typedef {Object} ClientOptions
192
- * @property {string} publicKey - API public key (cs_pk_...)
193
- * @property {string} secretKey - API secret key (cs_sk_...)
194
- * @property {'production'|'staging'|'development'|'test'} [environment] - Target environment (default: 'production')
195
- * @property {string} [baseUrl] - Override the API base URL (e.g. for self-hosted)
196
- * @property {number} [timeout] - Request timeout in ms (default: 30000)
197
- * @property {number} [retries] - Max retries on transient errors (default: 3)
198
- * @property {boolean} [debug] - Log HTTP requests/responses (default: false)
199
- */
200
-
201
- module.exports = {
202
- CertySignClient,
203
- CertySignError,
204
- DocumentHasher,
205
- SignatureEmbedder,
206
- HashSigningResource,
207
- SigningSessionResource,
208
- DashboardResource,
209
- // Legacy exports
210
- SigningResource,
211
- CertificateResource,
212
- PkiResource,
213
- EnvelopeResource
214
- };
1
+ /**
2
+ * @fileoverview CertySign SDK for Node.js
3
+ *
4
+ * Official client library for CertySign Trust Services — digital document
5
+ * signing, X.509 certificate issuance, and PKI operations for East Africa.
6
+ *
7
+ * @example Basic setup
8
+ * ```js
9
+ * const { CertySignClient } = require('@certysign/sdk');
10
+ *
11
+ * const client = new CertySignClient({
12
+ * publicKey: 'cs_pk_...',
13
+ * secretKey: 'cs_sk_...'
14
+ * });
15
+ * ```
16
+ */
17
+
18
+ 'use strict';
19
+
20
+ const { HttpClient, CertySignError } = require('./lib/HttpClient');
21
+ const { SigningResource } = require('./lib/SigningResource');
22
+ const { HashSigningResource } = require('./lib/HashSigningResource');
23
+ const { CertificateResource } = require('./lib/CertificateResource');
24
+ const { PkiResource } = require('./lib/PkiResource');
25
+ const { EnvelopeResource } = require('./lib/EnvelopeResource');
26
+ const { SigningSessionResource } = require('./lib/SigningSessionResource');
27
+ const { DashboardResource } = require('./lib/DashboardResource');
28
+ const { IdentityResource } = require('./lib/IdentityResource');
29
+ const { BillingResource } = require('./lib/BillingResource');
30
+ const { SignerResource } = require('./lib/SignerResource');
31
+ const { DocumentHasher } = require('./lib/DocumentHasher');
32
+ const { SignatureEmbedder } = require('./lib/SignatureEmbedder');
33
+
34
+ /**
35
+ * CertySign API client.
36
+ *
37
+ * Resources are accessed as properties:
38
+ * - client.sign — hash-based document signing (documents stay local)
39
+ * - client.sessions — multi-recipient signing sessions with OTP verification
40
+ * - client.dashboard — SDK usage analytics (stats, recipients, documents)
41
+ * - client.certificates — X.509 certificate lifecycle (issue, verify, status, getActive)
42
+ * - client.pki — PKI infrastructure (CRL, OCSP, CA chain, info)
43
+ * - client.envelopes — envelope management (create, upload, send, sign, audit)
44
+ * - client.hasher — local document hashing utility
45
+ * - client.embedder — local signature embedding (PDF, XML, JSON)
46
+ * - client.legacySign — legacy file-upload signing (deprecated)
47
+ *
48
+ * @example Hash-based signing (documents never leave your system)
49
+ * const { CertySignClient } = require('@certysign/sdk');
50
+ *
51
+ * const client = new CertySignClient({
52
+ * publicKey: process.env.CERTYSIGN_PUBLIC_KEY,
53
+ * secretKey: process.env.CERTYSIGN_SECRET_KEY,
54
+ * environment: 'production'
55
+ * });
56
+ *
57
+ * // 1. Hash locally → sign remotely → embed locally
58
+ * const result = await client.sign.hashAndSign({
59
+ * document: fs.readFileSync('./contract.pdf'),
60
+ * fileName: 'contract.pdf',
61
+ * reason: 'Contract approval'
62
+ * });
63
+ *
64
+ * // 2. Embed signature into the PDF on your system
65
+ * const signedPdf = await client.embedder.embedInPdf(
66
+ * fs.readFileSync('./contract.pdf'),
67
+ * {
68
+ * signature: result.data.signature,
69
+ * certificate: result.data.certificate,
70
+ * chain: result.data.chain,
71
+ * signerName: 'Dr. Amina Okonkwo',
72
+ * reason: 'Contract approval',
73
+ * certSerialNumber: result.data.certSerialNumber
74
+ * }
75
+ * );
76
+ * fs.writeFileSync('./contract-signed.pdf', signedPdf);
77
+ */
78
+ class CertySignClient {
79
+ /**
80
+ * @param {ClientOptions} options
81
+ */
82
+ constructor(options = {}) {
83
+ const {
84
+ publicKey,
85
+ secretKey,
86
+ baseUrl,
87
+ environment = 'production',
88
+ timeout,
89
+ retries,
90
+ debug = false,
91
+ tsaUrl,
92
+ } = options;
93
+
94
+ if (!publicKey) throw new Error('CertySignClient: publicKey is required');
95
+ if (!secretKey) throw new Error('CertySignClient: secretKey is required');
96
+
97
+ // Resolve base URL from environment if not explicitly provided
98
+ const resolvedBaseUrl = baseUrl ?? CertySignClient.BASE_URLS[environment];
99
+ if (!resolvedBaseUrl) {
100
+ throw new Error(
101
+ `CertySignClient: unknown environment "${environment}". ` +
102
+ `Expected one of: ${Object.keys(CertySignClient.BASE_URLS).join(', ')} ` +
103
+ `or provide baseUrl directly.`
104
+ );
105
+ }
106
+
107
+ this._http = new HttpClient({
108
+ publicKey,
109
+ secretKey,
110
+ baseUrl: resolvedBaseUrl,
111
+ timeout,
112
+ retries,
113
+ debug
114
+ });
115
+
116
+ // ── Resource objects ──
117
+ this.sign = new HashSigningResource(this._http); // Hash-based signing (documents stay local)
118
+ this.legacySign = new SigningResource(this._http); // Legacy file-upload signing
119
+ this.certificates = new CertificateResource(this._http);
120
+ this.pki = new PkiResource(this._http);
121
+ this.envelopes = new EnvelopeResource(this._http);
122
+ this.sessions = new SigningSessionResource(this._http); // Multi-recipient signing sessions
123
+ this.dashboard = new DashboardResource(this._http); // SDK usage analytics
124
+ this.identity = new IdentityResource(this._http); // National-ID verification (IPRS)
125
+ this.billing = new BillingResource(this._http); // Balance, quotes, plan (read-only)
126
+ this.signers = new SignerResource(this._http); // Sponsor + check the people you sign for
127
+ this.hasher = new DocumentHasher(); // Local document hashing
128
+
129
+ // TSA URL: explicit > environment-derived
130
+ const resolvedTsaUrl = tsaUrl ?? CertySignClient.TSA_URLS[environment] ?? null;
131
+ this.embedder = new SignatureEmbedder({ tsaUrl: resolvedTsaUrl }); // PAdES-T when TSA URL available
132
+
133
+ this.publicKey = publicKey;
134
+ this.environment = environment;
135
+ this.baseUrl = resolvedBaseUrl;
136
+ this.tsaUrl = resolvedTsaUrl;
137
+ }
138
+
139
+ /**
140
+ * Environment → base URL mapping.
141
+ * Override any entry via the `baseUrl` constructor option.
142
+ */
143
+ static get BASE_URLS() {
144
+ return {
145
+ production: 'https://core.certysign.io',
146
+ staging: 'https://service.certysign.io',
147
+ development: 'http://localhost:8000',
148
+ test: 'http://localhost:8000'
149
+ };
150
+ }
151
+
152
+ /**
153
+ * Environment → TSA URL mapping.
154
+ * Override via the `tsaUrl` constructor option.
155
+ */
156
+ static get TSA_URLS() {
157
+ return {
158
+ production: 'https://tsa.certysign.io',
159
+ staging: 'https://tsa-staging.certysign.io',
160
+ development: 'http://localhost:5015',
161
+ test: 'http://localhost:5015'
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Check that the API key works, as a startup health check.
167
+ *
168
+ * There is no dedicated identity endpoint, so this issues the cheapest
169
+ * authenticated call there is — GET /sdk/v1/pki/info — and reports whether it was
170
+ * accepted. A true `ok` means the credentials authenticated and the key holds
171
+ * `pki:info`; it does NOT prove any other scope is granted.
172
+ *
173
+ * It used to claim to return keyName, permissions and tenantId. /pki/info returns
174
+ * CA metadata and has never carried any of them, so every one of those fields came
175
+ * back undefined — a health check that silently reported nothing about the key it
176
+ * was supposed to be checking.
177
+ *
178
+ * @returns {Promise<{ ok: boolean, environment: string, caInitialized?: boolean, error?: string, code?: string }>}
179
+ *
180
+ * @example
181
+ * const res = await client.ping();
182
+ * if (!res.ok) throw new Error(`CertySign unreachable: ${res.error}`);
183
+ */
184
+ async ping() {
185
+ try {
186
+ const result = await this._http.get('/sdk/v1/pki/info');
187
+ const info = result?.data ?? result;
188
+ return {
189
+ ok: true,
190
+ environment: this.environment,
191
+ caInitialized: info?.initialized ?? info?.status?.initialized,
192
+ };
193
+ } catch (err) {
194
+ return { ok: false, environment: this.environment, error: err.message, code: err.code };
195
+ }
196
+ }
197
+ }
198
+
199
+ /**
200
+ * @typedef {Object} ClientOptions
201
+ * @property {string} publicKey - API public key (cs_pk_...)
202
+ * @property {string} secretKey - API secret key (cs_sk_...)
203
+ * @property {'production'|'staging'|'development'|'test'} [environment] - Target environment (default: 'production')
204
+ * @property {string} [baseUrl] - Override the API base URL (e.g. for self-hosted)
205
+ * @property {number} [timeout] - Request timeout in ms (default: 30000)
206
+ * @property {number} [retries] - Max retries on transient errors (default: 3)
207
+ * @property {boolean} [debug] - Log HTTP requests/responses (default: false)
208
+ */
209
+
210
+ module.exports = {
211
+ CertySignClient,
212
+ CertySignError,
213
+ DocumentHasher,
214
+ SignatureEmbedder,
215
+ HashSigningResource,
216
+ SigningSessionResource,
217
+ DashboardResource,
218
+ IdentityResource,
219
+ // Added in 2.5.0. Exported like every other resource so a caller can type-check
220
+ // or extend them; the client wires them up as client.signers / client.billing.
221
+ SignerResource,
222
+ BillingResource,
223
+ // Legacy exports
224
+ SigningResource,
225
+ CertificateResource,
226
+ PkiResource,
227
+ EnvelopeResource
228
+ };