@assinafy/sdk 2.1.1 → 2.1.2
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 +554 -111
- package/dist/index.d.mts +676 -311
- package/dist/index.d.ts +676 -311
- package/dist/index.js +3064 -1932
- package/dist/index.mjs +3063 -1932
- package/docs/API_COVERAGE.md +28 -30
- package/docs/COMPATIBILITY.md +256 -179
- package/docs/RELEASING.md +42 -11
- package/package.json +10 -9
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -1,27 +1,90 @@
|
|
|
1
1
|
# API compatibility
|
|
2
2
|
|
|
3
3
|
The SDK targets the official Assinafy contract at
|
|
4
|
-
[`/v1/docs/openapi.json`](https://api.assinafy.com.br/v1/docs/openapi.json)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
artifacts. The audited OpenAPI response's SHA-256 digest is
|
|
9
|
-
`7e5957082002e8e96c5abc2cadf7b4b463eaa5bd61b76e26f64b90a8b922088c`.
|
|
4
|
+
[`/v1/docs/openapi.json`](https://api.assinafy.com.br/v1/docs/openapi.json).
|
|
5
|
+
New integrations should send the published request shape. Compatibility paths
|
|
6
|
+
are narrow, typed, and used only when a caller selects one or when a validation
|
|
7
|
+
response unambiguously requests an older shape.
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
contract. A compatibility path is used only when the caller selects it
|
|
13
|
-
explicitly or the server returns a validation error that unambiguously requests
|
|
14
|
-
the older shape.
|
|
9
|
+
## Host availability
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
The production contract includes these account and authenticated-user routes:
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
```text
|
|
14
|
+
GET, POST /v1/accounts
|
|
15
|
+
GET, PUT, DELETE /v1/accounts/{accountId}
|
|
16
|
+
GET, POST, DELETE /v1/accounts/{accountId}/logo
|
|
17
|
+
GET /v1/accounts/{accountId}/theme
|
|
18
|
+
GET /v1/accounts/{accountId}/stats
|
|
19
|
+
GET /v1/users/self
|
|
20
|
+
GET, PUT /v1/users/self/notification-preferences
|
|
21
|
+
GET /v1/users/self/stats
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Sandbox deployments can return `404` for user statistics, account statistics,
|
|
25
|
+
or notification preferences while still accepting the production methods on
|
|
26
|
+
the production host. The SDK keeps the official paths and response types. A
|
|
27
|
+
sandbox `404` does not cause the client to route a request elsewhere.
|
|
28
|
+
|
|
29
|
+
Two browser URL helpers used by older deployments remain available:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
GET /v1/auth/authenticate
|
|
33
|
+
GET /v1/login-callback
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
They map to `auth.getSocialLoginUrl()` and
|
|
37
|
+
`auth.getSocialLoginCallbackUrl()` and are not part of the official
|
|
38
|
+
89-operation total.
|
|
39
|
+
|
|
40
|
+
The SDK also includes the production contract additions for:
|
|
41
|
+
|
|
42
|
+
- the `pades` document artifact;
|
|
43
|
+
- `DigitalCertificate` verification on assignment and template-document
|
|
44
|
+
creation and cost estimation;
|
|
45
|
+
- typed `display_settings` for collect fields;
|
|
46
|
+
- signer `government_id` updates;
|
|
47
|
+
- signature-image `reuse`;
|
|
48
|
+
- the documented `400` response from `GET /sign`; and
|
|
49
|
+
- the dedicated `SignerSelf` response fields.
|
|
50
|
+
|
|
51
|
+
Older signer-self responses can omit `has_signature`, `has_initial`, and
|
|
52
|
+
`is_signature_reusable`; assignment signers can omit `notification_history`.
|
|
53
|
+
Those fields are optional in the SDK response types.
|
|
54
|
+
|
|
55
|
+
`DocumentStatsRow` separates notification-channel counters from verification
|
|
56
|
+
method counters. Notification counters are not mutually exclusive.
|
|
57
|
+
`signature_requests_verification_{email,whatsapp,bypass,digital_certificate}`
|
|
58
|
+
are mutually exclusive and sum to `signature_requests`. Older unsuffixed email
|
|
59
|
+
and WhatsApp counters remain optional.
|
|
60
|
+
|
|
61
|
+
## Assignment list account context
|
|
62
|
+
|
|
63
|
+
`GET /v1/assignments` requires the workspace in the camel-case `accountId`
|
|
64
|
+
query parameter even though most account-scoped routes place it in the path.
|
|
65
|
+
The SDK obtains it from the optional method argument or the client default:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const page = await client.assignments.list(
|
|
69
|
+
{ page: 1, 'per-page': 20 },
|
|
70
|
+
'account-id',
|
|
71
|
+
);
|
|
72
|
+
// Request query: ?page=1&per-page=20&accountId=account-id
|
|
73
|
+
// Response: { data: IAssignment[], meta?: PaginationMeta }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If neither source supplies an account ID, the SDK throws `ValidationError`
|
|
77
|
+
before making the request.
|
|
78
|
+
|
|
79
|
+
## Template management extensions
|
|
80
|
+
|
|
81
|
+
The official OpenAPI document contains only:
|
|
19
82
|
|
|
20
83
|
```text
|
|
21
84
|
GET /v1/accounts/{accountId}/templates
|
|
22
85
|
```
|
|
23
86
|
|
|
24
|
-
|
|
87
|
+
Existing integrations can also use these routes:
|
|
25
88
|
|
|
26
89
|
```text
|
|
27
90
|
POST /v1/accounts/{accountId}/templates
|
|
@@ -31,16 +94,9 @@ DELETE /v1/accounts/{accountId}/templates/{templateId}
|
|
|
31
94
|
GET /v1/accounts/{accountId}/templates/{templateId}/pages/{pageId}/download
|
|
32
95
|
```
|
|
33
96
|
|
|
34
|
-
They map to `
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
future schema is not by itself grounds for removal; removal requires a live
|
|
38
|
-
regression test, a deprecation period, and a major-version decision.
|
|
39
|
-
|
|
40
|
-
Template status examples have also differed in casing (`Uploaded`/`Ready` in
|
|
41
|
-
live extension responses versus `uploaded`/`ready` in the published schema).
|
|
42
|
-
The exported type intentionally remains `string`. Applications should normalize
|
|
43
|
-
before comparing:
|
|
97
|
+
They map to `templates.create`, `get`, `update`, `delete`, and `downloadPage`
|
|
98
|
+
and are excluded from the official operation count. Template status casing can
|
|
99
|
+
vary, so normalize before branching:
|
|
44
100
|
|
|
45
101
|
```ts
|
|
46
102
|
if (template.status.toLowerCase() === 'ready') {
|
|
@@ -48,9 +104,13 @@ if (template.status.toLowerCase() === 'ready') {
|
|
|
48
104
|
}
|
|
49
105
|
```
|
|
50
106
|
|
|
107
|
+
A page object's `download_url` is protected by account authentication. Prefer
|
|
108
|
+
`templates.downloadPage(templateId, pageId)` so the SDK attaches credentials
|
|
109
|
+
and returns the JPEG bytes as a `Buffer`.
|
|
110
|
+
|
|
51
111
|
## Public send-token request
|
|
52
112
|
|
|
53
|
-
The official operation
|
|
113
|
+
The official operation sends an email body:
|
|
54
114
|
|
|
55
115
|
```http
|
|
56
116
|
PUT /v1/public/documents/{documentId}/send-token
|
|
@@ -59,13 +119,11 @@ Content-Type: application/json
|
|
|
59
119
|
{ "email": "signer@example.com" }
|
|
60
120
|
```
|
|
61
121
|
|
|
62
|
-
That is the default SDK call:
|
|
63
|
-
|
|
64
122
|
```ts
|
|
65
123
|
await client.documents.sendToken(documentId, 'signer@example.com');
|
|
66
124
|
```
|
|
67
125
|
|
|
68
|
-
|
|
126
|
+
Older environments can require `{ recipient, channel }`. The explicit
|
|
69
127
|
three-argument overload sends that shape:
|
|
70
128
|
|
|
71
129
|
```ts
|
|
@@ -73,121 +131,142 @@ await client.documents.sendToken(documentId, '+5511999990000', 'whatsapp');
|
|
|
73
131
|
```
|
|
74
132
|
|
|
75
133
|
For a two-argument call, the SDK starts with `{ email }` and retries the older
|
|
76
|
-
email shape only when the
|
|
77
|
-
|
|
78
|
-
retried under this compatibility rule.
|
|
134
|
+
email shape only when the validation response names `recipient` or `channel` as
|
|
135
|
+
required. Other errors are returned unchanged.
|
|
79
136
|
|
|
80
|
-
## Document
|
|
137
|
+
## Document tags
|
|
81
138
|
|
|
82
|
-
|
|
83
|
-
define `tags` as an array of existing **tag IDs**. The SDK follows that contract:
|
|
139
|
+
Replace and attach requests require existing tag IDs:
|
|
84
140
|
|
|
85
141
|
```ts
|
|
86
|
-
const tag = await client.tags.create({ name: 'Contracts' });
|
|
142
|
+
const tag = await client.tags.create({ name: 'Contracts', color: '#ff8800' });
|
|
87
143
|
await client.documents.addTags(documentId, [tag.id]);
|
|
88
144
|
await client.documents.replaceTags(documentId, [tag.id]);
|
|
145
|
+
const result = await client.documents.detachTag(documentId, tag.id);
|
|
146
|
+
// result → { detached: true }
|
|
89
147
|
```
|
|
90
148
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
attachment
|
|
94
|
-
|
|
149
|
+
The API accepts a tag color with or without a leading `#` and returns the
|
|
150
|
+
stored six-character value without it. Unknown tag names are not the normal
|
|
151
|
+
attachment input; create or list the tag first and send its ID. An empty array
|
|
152
|
+
passed to `replaceTags` detaches every tag.
|
|
95
153
|
|
|
96
|
-
## Account branding fields
|
|
154
|
+
## Account branding fields
|
|
97
155
|
|
|
98
|
-
The official
|
|
99
|
-
`
|
|
100
|
-
`
|
|
101
|
-
|
|
102
|
-
|
|
156
|
+
The official account create/update request schemas define `name` and
|
|
157
|
+
`notification_sender_type`. The response includes `primary_color` and
|
|
158
|
+
`secondary_color`. Some deployments also accept those two color fields on
|
|
159
|
+
create/update, so the SDK retains them as optional inputs. Account colors must
|
|
160
|
+
be six hexadecimal characters without a leading `#`.
|
|
103
161
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
the
|
|
107
|
-
|
|
108
|
-
workspace with a name only, then tests the field independently via update so
|
|
109
|
-
the create-side deployment lag cannot prevent the rest of the suite.
|
|
162
|
+
Some sandbox plans reject `notification_sender_type` during account creation
|
|
163
|
+
while accepting it on update. If that occurs, create with `{ name }` and apply
|
|
164
|
+
the sender type in a separate update. `getTheme`, `downloadLogo`, `uploadLogo`,
|
|
165
|
+
and `deleteLogo` are official operations.
|
|
110
166
|
|
|
111
|
-
|
|
112
|
-
|
|
167
|
+
`workspaces.delete(accountId, { force: true })` requests cancellation of an
|
|
168
|
+
active paid subscription as part of account deletion. It is not a general
|
|
169
|
+
override for unrelated deletion restrictions.
|
|
113
170
|
|
|
114
|
-
## Field-definition
|
|
171
|
+
## Field-definition extensions
|
|
115
172
|
|
|
116
173
|
The official field-create body defines `type`, `name`, nullable `regex`, and
|
|
117
|
-
`is_required`;
|
|
118
|
-
`is_active
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
the operation-specific official fields.
|
|
174
|
+
`is_required`; update defines `name`, nullable `regex`, and `is_active`. The SDK
|
|
175
|
+
also retains `is_active` on create and `type` or `is_required` on update for
|
|
176
|
+
deployments that accept them. New code should prefer the operation-specific
|
|
177
|
+
official fields.
|
|
122
178
|
|
|
123
|
-
The field-validation schemas
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
full audit exercised account-authenticated validation; it did not have the
|
|
127
|
-
signer-code fixture needed to re-certify this compatibility query.
|
|
179
|
+
The field-validation schemas omit the `signer-access-code` query parameter used
|
|
180
|
+
by some signer portals. `fields.validate()` and `validateMultiple()` retain the
|
|
181
|
+
typed `signerAccessCode` option for those environments.
|
|
128
182
|
|
|
129
|
-
##
|
|
183
|
+
## Signer request extensions
|
|
130
184
|
|
|
131
|
-
The
|
|
132
|
-
`whatsapp_phone_number`.
|
|
185
|
+
The official signer-create schema uses `full_name`, `email`, and
|
|
186
|
+
`whatsapp_phone_number`. Signer update adds `government_id`, which the SDK
|
|
187
|
+
normalizes to digits. Three older integration inputs remain accepted:
|
|
133
188
|
|
|
134
|
-
- `phone` is
|
|
135
|
-
transmission;
|
|
189
|
+
- `phone` is normalized to `whatsapp_phone_number` before transmission;
|
|
136
190
|
- `cpf` is normalized to digits and forwarded; and
|
|
137
191
|
- create-time `metadata` is forwarded unchanged.
|
|
138
192
|
|
|
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
|
-
|
|
193
|
+
New integrations should use the official create fields and `government_id` on
|
|
194
|
+
update. `cpf` is not an alias for the official update field, and signer
|
|
195
|
+
responses do not return it.
|
|
196
|
+
|
|
197
|
+
## Digital certificate and collect placement
|
|
198
|
+
|
|
199
|
+
`DigitalCertificate` requires the account feature, a CPF or CNPJ stored in the
|
|
200
|
+
signer's `government_id`, and exactly one certificate signer in that signing
|
|
201
|
+
step. It costs two credits per signer in addition to the selected notification
|
|
202
|
+
cost. Notification methods remain `Email` and `Whatsapp`.
|
|
203
|
+
|
|
204
|
+
For a `collect` assignment, each field can include `display_settings`.
|
|
205
|
+
`left`, `top`, `width`, `height`, and `fontSize` are required; `fontFamily` and
|
|
206
|
+
`backgroundColor` are optional. Values use Assinafy's 150-DPI page-image pixels
|
|
207
|
+
from the upper-left corner and must stay within the page.
|
|
208
|
+
|
|
209
|
+
## Document responses and artifacts
|
|
210
|
+
|
|
211
|
+
`documents.rename()` can return a document without `pages` or `assignment`.
|
|
212
|
+
`IRenameDocumentResponse` therefore keeps those two properties optional while
|
|
213
|
+
retaining the other document fields.
|
|
214
|
+
|
|
215
|
+
`documents.details()` returns `decline_reason` only when the access token
|
|
216
|
+
belongs to the document creator. Do not infer the absence of a decline merely
|
|
217
|
+
because that field is missing for another authenticated user.
|
|
218
|
+
|
|
219
|
+
Owner and signer downloads accept `original`, `certificated`,
|
|
220
|
+
`certificate-page`, `pades`, and `bundle`:
|
|
221
|
+
|
|
222
|
+
- `pades` exists only when the document had an ICP-Brasil certificate signer;
|
|
223
|
+
- `bundle` is a ZIP containing `original`, `certificated`, and
|
|
224
|
+
`certificate-page`, plus `pades` when it exists; and
|
|
225
|
+
- a generated artifact can return `404` until processing or certification is
|
|
226
|
+
complete.
|
|
227
|
+
|
|
228
|
+
Document and page download URLs in JSON responses are protected. Prefer the
|
|
229
|
+
typed download methods so credentials are applied and binary data is returned
|
|
230
|
+
as a `Buffer`.
|
|
231
|
+
|
|
232
|
+
## Signer-side preconditions
|
|
233
|
+
|
|
234
|
+
The signer `confirm-data` body contains `full_name`, `email`,
|
|
235
|
+
`government_id`, and `has_accepted_terms`. A certificate signer must confirm
|
|
236
|
+
data and accept terms before `getAssignment()`; either send
|
|
237
|
+
`has_accepted_terms: true` with `confirmData()` or call `acceptTerms()` first.
|
|
238
|
+
The `has_accepted_terms` query on `getAssignment()` is too late to open that
|
|
239
|
+
gate for a certificate signer.
|
|
240
|
+
|
|
241
|
+
`getAssignment()` uses `GET /sign`, but the API records the signer as having
|
|
242
|
+
viewed the assignment. The SDK therefore excludes this request from automatic
|
|
243
|
+
HTTP 429 replay.
|
|
244
|
+
|
|
245
|
+
`sign()` sends a non-empty array of `{ itemId, fieldId, pageId, value }` and is
|
|
246
|
+
intended for collect assignments. A virtual signer must confirm their data
|
|
247
|
+
before signing and should use `signMultiple()`, which accepts only virtual
|
|
248
|
+
documents. Certificate signers cannot use `sign()`; they complete the
|
|
249
|
+
certificate-start and certificate-complete browser flow.
|
|
250
|
+
|
|
251
|
+
Signature image upload sends raw PNG bytes with `Content-Type: image/png`.
|
|
252
|
+
`reuse: true` persists the image for later documents. A deprecated
|
|
253
|
+
`contentType` option remains for older integrations, but the official contract
|
|
254
|
+
supports PNG only.
|
|
255
|
+
|
|
256
|
+
## Upload metadata and expiration reset
|
|
257
|
+
|
|
258
|
+
Document upload accepts a PDF of at most 25 MB and 2,000 pages. The multipart
|
|
259
|
+
schema documents the file; the SDK's optional `metadata` JSON part is retained
|
|
260
|
+
for deployments that accept application-owned opaque metadata.
|
|
261
|
+
|
|
262
|
+
The reset-expiration schema requires an ISO-8601 date-time string. The SDK also
|
|
263
|
+
accepts `null` for older integrations that clear an expiration this way. Confirm
|
|
264
|
+
support in the target deployment before sending `null`.
|
|
183
265
|
|
|
184
266
|
## Resend-cost response variants
|
|
185
267
|
|
|
186
|
-
The
|
|
187
|
-
|
|
188
|
-
response references the full `CostEstimate` schema. A smaller resend-specific
|
|
189
|
-
shape has also been observed live. The SDK therefore returns the honest union
|
|
190
|
-
`IResendCostEstimate`:
|
|
268
|
+
The official resend-cost response is `ICostEstimate`. Older deployments can
|
|
269
|
+
return a compact branch, so the SDK exposes `IResendCostEstimate`:
|
|
191
270
|
|
|
192
271
|
```ts
|
|
193
272
|
const estimate = await client.assignments.estimateResendCost(
|
|
@@ -203,83 +282,81 @@ if ('total_credits' in estimate) {
|
|
|
203
282
|
}
|
|
204
283
|
```
|
|
205
284
|
|
|
206
|
-
The SDK does not
|
|
207
|
-
zeroes for server-provided balances.
|
|
285
|
+
The SDK does not add absent balance fields.
|
|
208
286
|
|
|
209
|
-
## Public
|
|
287
|
+
## Public document and signer download
|
|
210
288
|
|
|
211
|
-
The official
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
and retains the compact fields. Check optional fields before using them:
|
|
289
|
+
The official public-document response is the full `Document` schema. Compact
|
|
290
|
+
responses can contain only `id`, `name`, `page_count`, and `created_by`.
|
|
291
|
+
`IPublicDocumentInfo` requires `id` and `name`, keeps expanded fields optional,
|
|
292
|
+
and retains the compact fields:
|
|
216
293
|
|
|
217
294
|
```ts
|
|
218
295
|
const document = await client.documents.getPublic(documentId);
|
|
219
|
-
|
|
220
|
-
console.log(document.pages.length);
|
|
221
|
-
} else {
|
|
222
|
-
console.log(Number(document.page_count ?? 0));
|
|
223
|
-
}
|
|
296
|
+
const pages = document.pages?.length ?? Number(document.page_count ?? 0);
|
|
224
297
|
```
|
|
225
298
|
|
|
299
|
+
Signer artifact download is public in the OpenAPI document and requires no
|
|
300
|
+
access-code query in the official three-argument call. An optional fourth code
|
|
301
|
+
is available only for older deployments that require it.
|
|
302
|
+
|
|
226
303
|
## Empty acknowledgements
|
|
227
304
|
|
|
228
|
-
Several write operations return a
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
305
|
+
Several write operations return a success envelope without `data`; older
|
|
306
|
+
responses can use an empty array or object. Methods with no meaningful result
|
|
307
|
+
resolve to `Promise<void>` after validating the HTTP and envelope status. This
|
|
308
|
+
applies to token dispatch, signer OTP and terms, signature-image upload, bulk
|
|
309
|
+
signer actions, and deletions without a documented result. Tag deletion and
|
|
310
|
+
document-tag detachment preserve `{ deleted: boolean }` and
|
|
311
|
+
`{ detached: boolean }`.
|
|
312
|
+
|
|
313
|
+
## WhatsApp notification buttons
|
|
314
|
+
|
|
315
|
+
The published notification button schema requires `text`. Some deployments
|
|
316
|
+
also return `url`, so the SDK types it as optional. A button URL can contain a
|
|
317
|
+
signer access or verification value; treat it as a credential and never log it.
|
|
318
|
+
|
|
319
|
+
## Webhook delivery
|
|
320
|
+
|
|
321
|
+
Assinafy sends webhook events as HTTP `POST` JSON requests with
|
|
322
|
+
`Connection: close`. Any `2xx` is successful. There are at most two automatic
|
|
323
|
+
attempts per event with a three-second wait. After ten consecutive failed
|
|
324
|
+
events, ordinary delivery pauses and about 5% of later events are attempted
|
|
325
|
+
until one succeeds. `webhooks.retryDispatch()` requests immediate redelivery.
|
|
326
|
+
Only the first 2,000 characters of the receiver response body are retained in
|
|
327
|
+
dispatch history.
|
|
328
|
+
|
|
329
|
+
The common body contains `id`, `event`, nullable `message`, nullable `payload`,
|
|
330
|
+
nullable `origin`, Unix-second `created_at`, polymorphic `subject` and `object`,
|
|
331
|
+
and `account_id`. Use `id` for idempotent handling and accept unknown fields.
|
|
234
332
|
|
|
235
333
|
## Webhook signature verification is not in the OpenAPI contract
|
|
236
334
|
|
|
237
335
|
The official webhook operations define subscription management, event types,
|
|
238
|
-
delivery history, and retry.
|
|
239
|
-
|
|
240
|
-
for incoming deliveries.
|
|
336
|
+
delivery history, and retry. They do not define a shared-secret field,
|
|
337
|
+
signature algorithm, digest encoding, or signature header for incoming events.
|
|
241
338
|
|
|
242
|
-
`client.webhookVerifier` is
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
`X-Assinafy-Signature` header solely from this SDK.
|
|
339
|
+
`client.webhookVerifier` is an opt-in HMAC-SHA256 utility for environments whose
|
|
340
|
+
separate Assinafy agreement provides a shared secret and hex digest. Confirm the
|
|
341
|
+
header name and signing procedure for the target environment before enforcing
|
|
342
|
+
it. Do not assume an `X-Assinafy-Signature` header solely from this SDK.
|
|
247
343
|
|
|
248
344
|
## Authentication isolation
|
|
249
345
|
|
|
250
|
-
Public documents, login
|
|
346
|
+
Public documents, login and social login, password reset, OAuth URLs, and
|
|
251
347
|
signer-access-code flows use a separate HTTP transport without `X-Api-Key` or
|
|
252
|
-
`Authorization` defaults.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
`{ user, accounts }` and
|
|
265
|
-
normalizes both forms to `IAuthenticatedUser
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
The same sandbox returns `404` for the official `GET /users/self/stats` and
|
|
269
|
-
`GET /accounts/{accountId}/stats` routes. The production host recognizes both
|
|
270
|
-
routes (an unauthenticated probe receives `401`), so the SDK retains the exact
|
|
271
|
-
published paths and types. The live audit reports those sandbox-only `404`s as
|
|
272
|
-
explicit `SKIP`s rather than claiming they passed or rewriting calls to an
|
|
273
|
-
undocumented route.
|
|
274
|
-
|
|
275
|
-
## Updating this record
|
|
276
|
-
|
|
277
|
-
When the upstream API changes:
|
|
278
|
-
|
|
279
|
-
1. Diff the new official OpenAPI paths and schemas against the snapshot date
|
|
280
|
-
above.
|
|
281
|
-
2. Add or update typed methods and request/response tests.
|
|
282
|
-
3. Verify live-only behavior in the sandbox without logging secrets or tokens.
|
|
283
|
-
4. Update [API_COVERAGE.md](API_COVERAGE.md) and this file in the same change.
|
|
284
|
-
5. Keep compatibility behavior isolated and feature-detectable; do not silently
|
|
285
|
-
broaden retries or coerce malformed success payloads.
|
|
348
|
+
`Authorization` defaults. A credentialless `new AssinafyClient()` can drive
|
|
349
|
+
those flows, and credentials configured for protected resources are not sent.
|
|
350
|
+
|
|
351
|
+
Protected methods use the authenticated transport and receive the API's normal
|
|
352
|
+
`401` response when credentials are absent or invalid. The authenticated
|
|
353
|
+
transport accepts same-origin absolute URLs, rejects cross-origin requests
|
|
354
|
+
before dispatch, and treats credentials as redirect-sensitive. Use a separate
|
|
355
|
+
HTTP client for unrelated origins.
|
|
356
|
+
|
|
357
|
+
## Authenticated-user response variants
|
|
358
|
+
|
|
359
|
+
`GET /users/self` officially returns `AuthUser` directly. Some sandbox
|
|
360
|
+
deployments return `{ user, accounts }` and add `user.is_password_set`.
|
|
361
|
+
`users.getCurrent()` normalizes both forms to `IAuthenticatedUser`, where
|
|
362
|
+
`is_password_set` is optional.
|
package/docs/RELEASING.md
CHANGED
|
@@ -9,7 +9,7 @@ event, and the workflow intentionally does not depend on one.
|
|
|
9
9
|
|
|
10
10
|
| Runtime | Release responsibility |
|
|
11
11
|
| --- | --- |
|
|
12
|
-
| Bun 1.
|
|
12
|
+
| Bun 1.4.0 | Locked install, tests, build, contract checks, and packaging |
|
|
13
13
|
| Node.js 22 | Minimum supported consumer runtime |
|
|
14
14
|
| Node.js 24 LTS | Packaging and registry publishing runtime |
|
|
15
15
|
| Node.js 26 Current | Forward-compatibility consumer test |
|
|
@@ -29,12 +29,16 @@ publisher using these repository coordinates:
|
|
|
29
29
|
| Organization or user | `assinafy` |
|
|
30
30
|
| Repository | `typescript-sdk` |
|
|
31
31
|
| Workflow filename | `release.yml` |
|
|
32
|
-
| Environment |
|
|
32
|
+
| Environment | `release` |
|
|
33
|
+
| Allowed actions | `npm publish` |
|
|
33
34
|
|
|
34
35
|
The `publish-npm` job grants only `contents: read` and `id-token: write`.
|
|
35
36
|
Modern npm exchanges GitHub's short-lived OIDC identity for publish credentials;
|
|
36
37
|
no long-lived `NPM_TOKEN` is required. Test trusted publishing before deleting a
|
|
37
38
|
legacy token, then remove that token from repository and organization secrets.
|
|
39
|
+
Keep package access **public** and select npm's most restrictive publishing
|
|
40
|
+
access option: **Require two-factor authentication and disallow bypass 2FA
|
|
41
|
+
tokens**. Trusted-publisher OIDC remains compatible with that setting.
|
|
38
42
|
|
|
39
43
|
### GitHub Packages
|
|
40
44
|
|
|
@@ -43,11 +47,33 @@ The `publish-gh` job uses the workflow-scoped `GITHUB_TOKEN` with
|
|
|
43
47
|
the `@assinafy` scope and that the package remains linked to this repository.
|
|
44
48
|
No separate personal access token should be stored.
|
|
45
49
|
|
|
50
|
+
### Sandbox integration environment
|
|
51
|
+
|
|
52
|
+
Create a protected GitHub environment named `sandbox`. Restrict deployments to
|
|
53
|
+
the mirrored `main` branch, require reviewer approval, and store these required
|
|
54
|
+
environment secrets:
|
|
55
|
+
|
|
56
|
+
- `ASSINAFY_API_KEY`
|
|
57
|
+
- `ASSINAFY_ACCOUNT_ID`
|
|
58
|
+
|
|
59
|
+
The `disposable-full` mode also requires `ASSINAFY_TEST_EMAIL_PRIMARY` and
|
|
60
|
+
`ASSINAFY_TEST_EMAIL_SECONDARY`. Optional coverage uses
|
|
61
|
+
`ASSINAFY_TEST_WEBHOOK_URL`, `ASSINAFY_TEST_LOGIN_EMAIL`,
|
|
62
|
+
`ASSINAFY_TEST_LOGIN_PASSWORD`, `ASSINAFY_SIGNER_ACCESS_CODE`,
|
|
63
|
+
`ASSINAFY_SIGNER_OTP`, and `ASSINAFY_PUBLIC_DOCUMENT_ID`.
|
|
64
|
+
|
|
65
|
+
Keep secret values out of repository variables, files, and logs. Run the manual
|
|
66
|
+
**Sandbox integration** workflow from mirrored `main`; use `read-only` first
|
|
67
|
+
and select `disposable-full` only for a deliberate reversible test run.
|
|
68
|
+
|
|
46
69
|
### Mirror and tag protection
|
|
47
70
|
|
|
48
71
|
The GitLab push mirror must include tags and be able to update the GitHub
|
|
49
|
-
repository. Protect
|
|
50
|
-
|
|
72
|
+
repository. Protect `v*` tags in GitLab so only release maintainers can create
|
|
73
|
+
them, and add a GitHub tag ruleset that restricts creating, updating, and
|
|
74
|
+
deleting the same pattern to the mirror/release maintainers. Protect the GitHub
|
|
75
|
+
`release` environment with required reviewers and a deployment tag rule for
|
|
76
|
+
`v*`. GitHub Actions must be enabled on the mirror.
|
|
51
77
|
|
|
52
78
|
## Preparing a release
|
|
53
79
|
|
|
@@ -66,8 +92,8 @@ create patterns matching `v*`. GitHub Actions must be enabled on the mirror.
|
|
|
66
92
|
bun run audit:api
|
|
67
93
|
```
|
|
68
94
|
|
|
69
|
-
5. For API changes, run the
|
|
70
|
-
read-only:
|
|
95
|
+
5. For API changes, run the sandbox smoke script against a dedicated account.
|
|
96
|
+
Start read-only:
|
|
71
97
|
|
|
72
98
|
```sh
|
|
73
99
|
ASSINAFY_API_KEY='...' \
|
|
@@ -105,9 +131,10 @@ create patterns matching `v*`. GitHub Actions must be enabled on the mirror.
|
|
|
105
131
|
The workflow serializes releases repository-wide and performs these steps:
|
|
106
132
|
|
|
107
133
|
1. verify that the tag and `package.json` versions match;
|
|
108
|
-
2. install from `bun.lock`, run `verify
|
|
134
|
+
2. install from `bun.lock`, run `verify`, dependency and API-contract checks,
|
|
135
|
+
and build once;
|
|
109
136
|
3. create one `.tgz` with lifecycle scripts disabled and record its SHA-256;
|
|
110
|
-
4. upload that archive and checksum as a
|
|
137
|
+
4. upload that archive and checksum as a seven-day workflow artifact;
|
|
111
138
|
5. verify and publish the archive to npm through trusted-publisher OIDC; and
|
|
112
139
|
6. verify and publish the **same bytes** to GitHub Packages using
|
|
113
140
|
`GITHUB_TOKEN`.
|
|
@@ -120,15 +147,19 @@ contract and must be preserved when editing the workflow.
|
|
|
120
147
|
## Verification and recovery
|
|
121
148
|
|
|
122
149
|
After publishing, confirm that the expected version appears on npm and GitHub
|
|
123
|
-
Packages
|
|
124
|
-
entrypoints
|
|
150
|
+
Packages, that a clean Node.js consumer can import both the ESM and CommonJS
|
|
151
|
+
entrypoints, and that registry downloads have the expected checksum.
|
|
125
152
|
|
|
126
153
|
If packaging or npm publishing fails, fix the source, increment or retain the
|
|
127
154
|
version as registry state allows, and create a new tag only after review. Never
|
|
128
155
|
move a tag that has published a package.
|
|
129
156
|
|
|
157
|
+
Do not rerun an old release after changing its workflow or trusted-publisher
|
|
158
|
+
coordinates: GitHub reruns use the original commit and ref. Merge the fix and
|
|
159
|
+
create a reviewed new version and tag instead.
|
|
160
|
+
|
|
130
161
|
If npm succeeds and GitHub Packages fails, rerun only the failed job while the
|
|
131
|
-
original
|
|
162
|
+
original seven-day workflow artifact is retained. This preserves the exact
|
|
132
163
|
archive already published to npm. Do not repack an approximation or unpublish a
|
|
133
164
|
released npm version. If the artifact has expired, stop and review recovery with
|
|
134
165
|
the maintainers before changing workflow dependencies or registry state.
|