@assinafy/sdk 2.1.2 → 2.3.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/CHANGELOG.md +168 -1
- package/README.en.md +1373 -0
- package/README.md +763 -522
- package/SECURITY.md +17 -2
- package/dist/index.d.mts +794 -12
- package/dist/index.d.ts +794 -12
- package/dist/index.js +900 -59
- package/dist/index.mjs +894 -57
- package/docs/API_COVERAGE.md +28 -4
- package/docs/COMPATIBILITY.md +86 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,170 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.3.0] - 2026-09-20
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **OAuth 2.1 support — `client.oauth`.** Applications that act inside *other
|
|
15
|
+
people's* workspaces can now run the whole authorization-code flow through
|
|
16
|
+
the SDK instead of assembling it by hand:
|
|
17
|
+
- `createAuthorizationUrl(options)` mints a fresh PKCE verifier (S256), a
|
|
18
|
+
`state` and, for `openid`, a `nonce`, then builds the consent URL. It
|
|
19
|
+
returns everything the callback and token exchange need, so nothing has to
|
|
20
|
+
be re-derived later.
|
|
21
|
+
- `readAuthorizationCallback(params, expected)` validates the redirect before
|
|
22
|
+
anything on it is trusted: `state` in constant time, then `iss` (RFC 9207).
|
|
23
|
+
A declined consent surfaces as an `OAuthError`, not a silent success. It
|
|
24
|
+
accepts an Express `req.query`, a `URLSearchParams`, a `URL`, a full
|
|
25
|
+
callback URL or a bare query string.
|
|
26
|
+
- `exchangeCode(options)`, `refreshToken(options)` and `revokeToken(options)`
|
|
27
|
+
call `POST /oauth/token` and `POST /oauth/revoke` on a credential-free
|
|
28
|
+
transport, so an integrator's own `X-Api-Key` is never sent to a route that
|
|
29
|
+
authenticates the application.
|
|
30
|
+
- `getUserInfo(accessToken?)` reads the OpenID Connect claims.
|
|
31
|
+
- `getProtectedResourceMetadata()` (RFC 9728, served at the API host root)
|
|
32
|
+
and `getAuthorizationServerMetadata(issuer?)` (RFC 8414) discover the
|
|
33
|
+
endpoints instead of hardcoding them, and the second one rejects a document
|
|
34
|
+
whose `issuer` disagrees with where it was fetched from.
|
|
35
|
+
- **`OAuthError`** — the OAuth endpoints answer with a flat
|
|
36
|
+
`{ error, error_description }` body rather than the `{ status, message, data }`
|
|
37
|
+
envelope, so the RFC 6749 code is exposed as `error` and the explanation as
|
|
38
|
+
`errorDescription`. It extends `ApiError`, so existing `catch` blocks keep
|
|
39
|
+
matching.
|
|
40
|
+
- **`ApiError.challenge`** — the parsed `WWW-Authenticate` header, when the API
|
|
41
|
+
sends one. On a `403` it names the scope the token is missing
|
|
42
|
+
(`insufficient_scope`), which is the only way to tell "reconnect asking for
|
|
43
|
+
more" apart from a permission an OAuth token can never hold. The parser is
|
|
44
|
+
also exported as `parseWwwAuthenticate`.
|
|
45
|
+
- Both READMEs document the complete OAuth flow: registering the application,
|
|
46
|
+
the scope catalogue, workspace binding, refresh-token rotation, revocation,
|
|
47
|
+
and what each failure means.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- **Signer verification and notification channels are now validated as a
|
|
52
|
+
pair.** The API couples them — the verification code travels on the
|
|
53
|
+
notification channel — so `Email` verification only allows `Email`
|
|
54
|
+
notification, `Whatsapp` only `Whatsapp`, and `DigitalCertificate` either
|
|
55
|
+
one. Exactly one notification method is allowed per signer. The SDK rejected
|
|
56
|
+
unknown channel names but let an impossible pairing (and an empty or
|
|
57
|
+
two-element `notification_methods`) through to a `400`. The rule now lives in
|
|
58
|
+
`validateAssignmentSignerOptions()` and therefore applies to assignment
|
|
59
|
+
creation, cost estimation and template-driven document creation alike; the
|
|
60
|
+
duplicate one-method check in the template path was removed.
|
|
61
|
+
- A payload the API would have rejected now fails locally with a
|
|
62
|
+
`ValidationError` naming the pairing.
|
|
63
|
+
- `AssignmentVerificationMethod` and `AssignmentNotificationMethod` document
|
|
64
|
+
the channel matrix, its costs and its prerequisites. ICP-Brasil **A1** and
|
|
65
|
+
**A3** are recorded explicitly as certificate media — a file in software or a
|
|
66
|
+
token/smartcard, chosen by the signer in the browser — both modelled by the
|
|
67
|
+
single `DigitalCertificate` value, with no separate field to send.
|
|
68
|
+
- `bun run audit:api` additionally fetches the two OAuth discovery documents
|
|
69
|
+
and checks the issuer, the authorization and token endpoints, PKCE `S256` and
|
|
70
|
+
the RFC 9207 `iss` parameter against the published contract. They are the
|
|
71
|
+
only part of the OAuth surface that does not live in the OpenAPI document.
|
|
72
|
+
- `docs/API_COVERAGE.md` maps the four new OAuth operations, bringing the
|
|
73
|
+
ledger to 93 of 93.
|
|
74
|
+
- The Portuguese README is now the complete reference rather than a summary
|
|
75
|
+
pointing at the English one: installation through the end-to-end signature
|
|
76
|
+
flow, every resource, errors, environments and development.
|
|
77
|
+
|
|
78
|
+
## [2.2.0] - 2026-08-27
|
|
79
|
+
|
|
80
|
+
### Security
|
|
81
|
+
|
|
82
|
+
- **`baseUrl` now requires `https` for any remote host.** Every request on the
|
|
83
|
+
authenticated transport carries the caller's `X-Api-Key` or bearer token, so
|
|
84
|
+
a plaintext `http://` base URL put a long-lived credential on the wire in
|
|
85
|
+
cleartext. `http` remains accepted when the host is loopback (`localhost`,
|
|
86
|
+
the `127.0.0.0/8` block, or `::1`) so local mock servers and the packed
|
|
87
|
+
consumer smoke test keep working; anything else is rejected with a
|
|
88
|
+
`ValidationError` at construction time. `SECURITY.md` already required HTTPS
|
|
89
|
+
endpoints — the client now enforces it rather than trusting configuration.
|
|
90
|
+
- Callers pointing at a remote `http://` host must switch to `https://`.
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
|
|
94
|
+
- **`signers.findByEmail()` requested 100 rows per page and received 50.** The
|
|
95
|
+
API clamps `per-page` to 50 and answers `200`, so the lookup scanned half the
|
|
96
|
+
window its documentation claimed. It now pins the real maximum, and the
|
|
97
|
+
method and `signers.list()` documentation state the clamp instead of naming
|
|
98
|
+
100 as the API maximum. `documents.list()` carried the same incorrect claim.
|
|
99
|
+
- **Unstructured error bodies were reported as the generic "API request
|
|
100
|
+
failed".** A gateway or proxy in front of the API answers with `text/plain`
|
|
101
|
+
or HTML rather than the Assinafy JSON envelope. `ApiError.fromResponse()`
|
|
102
|
+
only read `message`/`error` off an object, so exactly the failures with no
|
|
103
|
+
structured body to explain them lost their only explanation. A non-JSON body
|
|
104
|
+
is now used as the message, with whitespace collapsed and the text capped at
|
|
105
|
+
500 characters; the untouched body remains on `ApiError.responseData`.
|
|
106
|
+
|
|
107
|
+
### Added
|
|
108
|
+
|
|
109
|
+
- **`MAX_LIST_PAGE_SIZE`** — the largest page any list endpoint returns (50).
|
|
110
|
+
Exported so callers can size pagination loops against the value the server
|
|
111
|
+
actually honours rather than the one they request.
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
|
|
115
|
+
- The email and E.164 phone-number patterns had five and two copies across the
|
|
116
|
+
resource files. They are now `isEmail()`, `assertEmail()`, and
|
|
117
|
+
`isE164PhoneNumber()` in `src/utils.ts`, so the accepted shape of a contact
|
|
118
|
+
value is defined in one place. Validation behaviour and error messages are
|
|
119
|
+
unchanged.
|
|
120
|
+
- `decodeBinaryErrorBody()` returns a non-JSON binary body as a string instead
|
|
121
|
+
of wrapping it in `{ message }`, so both unstructured-body paths converge on
|
|
122
|
+
the single rule in `ApiError.fromResponse()`.
|
|
123
|
+
- GitLab CI reads the Bun version from `package.json`'s `packageManager` field
|
|
124
|
+
instead of repeating the literal, matching how GitHub Actions' `setup-bun`
|
|
125
|
+
resolves it. Both CIs now move together when that field is bumped.
|
|
126
|
+
- README gained a contents map linking the setup, end-to-end workflow, and
|
|
127
|
+
per-resource sections; list examples use the `per-page` spelling the API
|
|
128
|
+
reads and document the page-size clamp.
|
|
129
|
+
|
|
130
|
+
## [2.1.2] - 2026-08-26
|
|
131
|
+
|
|
132
|
+
### Added
|
|
133
|
+
|
|
134
|
+
- `SDK_USER_AGENT` — every transport, including public and signer-access-code
|
|
135
|
+
requests, now identifies itself as `Assinafy-Typescript-SDK/v<VERSION>`.
|
|
136
|
+
- `scripts/node-consumer-smoke.mjs`, exercised by CI and the release workflow:
|
|
137
|
+
it installs the packed tarball into an isolated consumer and drives the real
|
|
138
|
+
Node HTTP, auth, and multipart paths through both CJS and ESM entrypoints.
|
|
139
|
+
- A manual **Sandbox integration** workflow with `read-only` and
|
|
140
|
+
`disposable-full` modes, gated on a protected environment.
|
|
141
|
+
|
|
142
|
+
### Security
|
|
143
|
+
|
|
144
|
+
- Requests on the authenticated transport are pinned to the configured API
|
|
145
|
+
origin. A cross-origin URL is rejected before dispatch, and `Authorization`
|
|
146
|
+
and `X-Api-Key` are marked redirect-sensitive so the redirect stack strips
|
|
147
|
+
them.
|
|
148
|
+
- Cross-origin redirects are blocked unless they are a `GET`/`HEAD` to an
|
|
149
|
+
`https` target whose source URL carries no sensitive query parameter.
|
|
150
|
+
- Public, login, and signer-access-code flows run on a transport whose
|
|
151
|
+
credential headers are removed at construction, so a configured API key
|
|
152
|
+
cannot reach a public endpoint.
|
|
153
|
+
- `AxiosError` is no longer attached as an SDK error `cause`. It retains the
|
|
154
|
+
full request config, including credentials and body, which error reporters
|
|
155
|
+
commonly serialize. Transport failures now carry a sanitized cause with
|
|
156
|
+
credential-shaped values redacted from the message.
|
|
157
|
+
- Caller-supplied loggers receive an allowlist of numeric operational counters
|
|
158
|
+
only. Logger exceptions and rejected promises are swallowed so telemetry
|
|
159
|
+
cannot change request semantics.
|
|
160
|
+
|
|
161
|
+
### Fixed
|
|
162
|
+
|
|
163
|
+
- `AssinafyClient.create()` no longer let its options bag override the
|
|
164
|
+
`apiKey`/`accountId` passed positionally, and it rejects missing or malformed
|
|
165
|
+
credentials instead of constructing an unusable client.
|
|
166
|
+
- Constructor options are validated up front: a non-object bag, a blank
|
|
167
|
+
credential, or an invalid `timeout`/`maxRetries` throws `ValidationError`.
|
|
168
|
+
- `uploadAndRequestSignatures()` validates every signer before uploading, so an
|
|
169
|
+
invalid later signer no longer leaves an orphaned document behind, and it no
|
|
170
|
+
longer waits for `metadata_ready` before creating a virtual assignment.
|
|
171
|
+
- HTTP 429 replay is limited to `GET`, `HEAD`, `OPTIONS`, and `DELETE`, with
|
|
172
|
+
`GET /sign` excluded because that read records a signer view.
|
|
173
|
+
|
|
10
174
|
## [2.1.1] - 2026-08-06
|
|
11
175
|
|
|
12
176
|
Maintenance only. The published `dist/` is byte-identical to 2.1.0; no runtime,
|
|
@@ -457,7 +621,10 @@ fields (`cpf`, `whatsapp_phone_number`) with the PHP SDK and n8n node.
|
|
|
457
621
|
- High-level `uploadAndRequestSignatures` helper on `AssinafyClient`.
|
|
458
622
|
- `PaginatedResult<T>` with parsed `X-Pagination-*` header meta.
|
|
459
623
|
|
|
460
|
-
[Unreleased]: https://github.com/assinafy/typescript-sdk/compare/v2.
|
|
624
|
+
[Unreleased]: https://github.com/assinafy/typescript-sdk/compare/v2.3.0...HEAD
|
|
625
|
+
[2.3.0]: https://github.com/assinafy/typescript-sdk/compare/v2.2.0...v2.3.0
|
|
626
|
+
[2.2.0]: https://github.com/assinafy/typescript-sdk/compare/v2.1.2...v2.2.0
|
|
627
|
+
[2.1.2]: https://github.com/assinafy/typescript-sdk/compare/v2.1.1...v2.1.2
|
|
461
628
|
[2.1.1]: https://github.com/assinafy/typescript-sdk/compare/v2.1.0...v2.1.1
|
|
462
629
|
[2.1.0]: https://github.com/assinafy/typescript-sdk/compare/v2.0.0...v2.1.0
|
|
463
630
|
[2.0.0]: https://github.com/assinafy/typescript-sdk/releases/tag/v2.0.0
|