@certysign/sdk 2.4.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 +76 -0
- package/package.json +54 -54
- package/src/index.js +228 -214
- package/src/lib/BillingResource.js +90 -0
- package/src/lib/EnvelopeResource.js +306 -249
- package/src/lib/HashSigningResource.js +9 -2
- package/src/lib/HttpClient.js +211 -198
- package/src/lib/IdentityResource.js +143 -0
- package/src/lib/SignerResource.js +120 -0
- package/src/lib/SigningResource.js +11 -7
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.
|
|
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 {
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* - client.
|
|
39
|
-
* - client.
|
|
40
|
-
* - client.
|
|
41
|
-
* - client.
|
|
42
|
-
* - client.
|
|
43
|
-
* - client.
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.
|
|
118
|
-
this.
|
|
119
|
-
this.
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.
|
|
126
|
-
|
|
127
|
-
this.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
+
};
|