@v3finance/core-sdk 0.2.2 → 0.2.3

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 CHANGED
@@ -3,6 +3,25 @@
3
3
  All notable changes to this package are documented in this file. The format is based on
4
4
  [Keep a Changelog](https://keepachangelog.com), and this project adheres to [Semantic Versioning](https://semver.org).
5
5
 
6
+ ## 0.2.3 — 2026-11-12
7
+
8
+ Spec snapshot refreshed from the live API (commit `031d7bf`,
9
+ [v3-finance/policy-engine#23](https://github.com/v3-finance/policy-engine/pull/23)). No operation
10
+ was added or removed, no type changed, and no code in this package changed: two failures that used
11
+ to answer 500 `INTERNAL_ERROR` now answer 409 with a code of their own.
12
+
13
+ ### Fixed
14
+
15
+ - `folders.update()` — renaming a folder to a name its owner already uses for another folder is a
16
+ 409 `GROUP_NAME_CONFLICT`, the same answer `folders.create()` gives. It used to be a 500
17
+ `INTERNAL_ERROR`.
18
+ - `addresses.create()` — when `create_address` requires signatures but fewer people can give them
19
+ than the threshold asks for, the call throws 409 `APPROVAL_UNSATISFIABLE` (no `details`); nothing
20
+ was created, and there is no 202. Do not retry: an administrator has to change the policy or the
21
+ approver group. Any other failure to create the approval request is 409 `APPROVAL_FAILED`. Both
22
+ used to be a 500 `INTERNAL_ERROR`.
23
+ - `docs/errors.md`: these codes in the address and folder tables.
24
+
6
25
  ## 0.2.2 — 2026-11-12
7
26
 
8
27
  Spec snapshot refreshed from the live API (commit `3ca1538`,
@@ -10,7 +10,7 @@
10
10
  // the API does not slip in unclassified.
11
11
  //
12
12
  // Operations: 171 · admin: 40 · both: 1 · member: 127 · service: 3
13
- // Spec sha256: 30be5f9b9733d1d1d67eebf21e0bfaa457651e951676211ec9fa464cca5d3795
13
+ // Spec sha256: 1f0f2a38668572c443a84cb0207d4070b419a16c293b8e975f5e21c68e85b15a
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.OPERATIONS = void 0;
16
16
  exports.isAdminOperation = isAdminOperation;
@@ -1,5 +1,5 @@
1
1
  /** SDK version, sent in the `user-agent` header. */
2
- export declare const SDK_VERSION = "0.2.2";
2
+ export declare const SDK_VERSION = "0.2.3";
3
3
  /** Default API base URL. */
4
4
  export declare const DEFAULT_BASE_URL = "https://policy-engine-rest.ezig.workers.dev";
5
5
  //# sourceMappingURL=version.d.ts.map
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_BASE_URL = exports.SDK_VERSION = void 0;
4
4
  /** SDK version, sent in the `user-agent` header. */
5
- exports.SDK_VERSION = '0.2.2';
5
+ exports.SDK_VERSION = '0.2.3';
6
6
  /** Default API base URL. */
7
7
  exports.DEFAULT_BASE_URL = 'https://policy-engine-rest.ezig.workers.dev';
8
8
  //# sourceMappingURL=version.js.map
@@ -9,7 +9,7 @@
9
9
  // the API does not slip in unclassified.
10
10
  //
11
11
  // Operations: 171 · admin: 40 · both: 1 · member: 127 · service: 3
12
- // Spec sha256: 30be5f9b9733d1d1d67eebf21e0bfaa457651e951676211ec9fa464cca5d3795
12
+ // Spec sha256: 1f0f2a38668572c443a84cb0207d4070b419a16c293b8e975f5e21c68e85b15a
13
13
  export const OPERATIONS = {
14
14
  "DELETE /api/v1/me/push-tokens/{token}": {
15
15
  "method": "delete",
@@ -1,5 +1,5 @@
1
1
  /** SDK version, sent in the `user-agent` header. */
2
- export declare const SDK_VERSION = "0.2.2";
2
+ export declare const SDK_VERSION = "0.2.3";
3
3
  /** Default API base URL. */
4
4
  export declare const DEFAULT_BASE_URL = "https://policy-engine-rest.ezig.workers.dev";
5
5
  //# sourceMappingURL=version.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /** SDK version, sent in the `user-agent` header. */
2
- export const SDK_VERSION = '0.2.2';
2
+ export const SDK_VERSION = '0.2.3';
3
3
  /** Default API base URL. */
4
4
  export const DEFAULT_BASE_URL = 'https://policy-engine-rest.ezig.workers.dev';
5
5
  //# sourceMappingURL=version.js.map
package/docs/errors.md CHANGED
@@ -194,8 +194,10 @@ Two sets of uppercase strings travel inside **successful** bodies and will misle
194
194
  | `NO_DYNAMIC_ROUTE` | 500 | The vault's derivation scheme has no incrementing segment. | Configuration fault — address creation is impossible in this vault until an admin fixes it. |
195
195
  | `TOKEN_NOT_REGISTERED` | 500 | An asset segment points at a token missing from the registry. | Configuration fault. Contact an administrator. |
196
196
  | `POLICY_DENIED` | 403 | `block`, or no policy permits `create_address`. `details` holds the decision. | Terminal. Show `message`. |
197
+ | `APPROVAL_UNSATISFIABLE` | 409 | `create_address` requires signatures, but fewer people can give them than the threshold asks for (the initiator does not count unless the policy allows approving one's own request). Neither the address nor an approval request was created. Unlike the transfer's, it carries no `details`. | **Do not retry.** An administrator has to change the policy or the approver group. See [Easily confused](#easily-confused). |
198
+ | `APPROVAL_FAILED` | 409 | The approval request could not be created for a reason other than `APPROVAL_UNSATISFIABLE`. See the note under [Declared but never returned](#declared-but-never-returned). | Retry once. If it repeats, it is a server-side fault — escalate. |
197
199
 
198
- Address creation that requires signatures is **not** an error: the server answers **202** with `{status:"awaiting_approval", approvalRequestId, approvalThreshold}`. Nothing is thrown. (`POLICY_REQUIRES_APPROVAL` exists in the server's type but is never sent — see [Declared but never returned](#declared-but-never-returned).)
200
+ Address creation that requires signatures is **not** an error: the server answers **202** with `{status:"awaiting_approval", approvalRequestId, approvalThreshold}`. Nothing is thrown. (`POLICY_REQUIRES_APPROVAL` exists in the server's type but is never sent — see [Declared but never returned](#declared-but-never-returned).) The exception is signatures that cannot be gathered at all: then there is no request and no 202, but `APPROVAL_UNSATISFIABLE` above.
199
201
 
200
202
  Creating an address **into a folder** (`groupId`) can succeed without the folder, and that is not an error either. The right to the folder is checked before anything is created — a refusal there is `GROUP_CREATE_FORBIDDEN` above — but the address is put into the folder only after the signing service and monitoring, and the right is checked again at that moment. If that fails, the address still exists and the answer is still **201**, with `warnings: [{code, message}]` in the body:
201
203
 
@@ -225,7 +227,7 @@ Address shares, folder shares, member-visibility grants. All grant `POST`s are i
225
227
  | `NOT_FOLDER_MANAGER` | 403 | Only the folder's creator changes its contents. | Terminal. Ask the creator. |
226
228
  | `NOT_ADDRESS_OWNER` | 403 | You manage the folder, but the address you are adding is not yours — putting it in a shared folder would widen access to it behind its owner's back. | Terminal, and deliberately so. Only the address's own owner can add it. |
227
229
  | `ALREADY_MEMBER` | 409 | The address is already in the folder. | Benign. Treat as success and refresh. |
228
- | `GROUP_NAME_CONFLICT` | 409 | You already have a folder with that name (names are unique per owner, not per vault). | Ask for a different name. |
230
+ | `GROUP_NAME_CONFLICT` | 409 | Creating a folder, or renaming one (`PATCH`), with a name its owner already uses for another folder (names are unique per owner, not per vault). | Ask for a different name. |
229
231
  | `ACCESS_VIA_GROUP` | 409 | You tried to remove your own access, but it comes from a user group, not a personal grant. `details` has `{groupId, groupName}`. | Explain it with the group name from `details`: the user must leave the group, or an admin must revoke the group's grant. |
230
232
  | `NOT_YOURS` | 403 | You tried to remove someone else's grant via the "remove me" endpoint. | A client bug. Revoking another person's access is the object owner's prerogative. |
231
233
  | `FORBIDDEN` | 403 | Generic refusal when removing an address from a folder. | Terminal. |
@@ -426,7 +428,7 @@ Rate limiting outside `/api/auth/*` is not implemented in the API itself. A 429
426
428
 
427
429
  ## Easily confused
428
430
 
429
- **`APPROVAL_UNSATISFIABLE` / `UNSATISFIABLE` is not a transient conflict.** It is a 409, and 409s are usually worth a retry. This one never is: it means the policy demands more signatures than there are people able to give them, so every retry fails identically. The only resolution is an administrator changing the policy or the approver group. Say that, and do not offer a retry button. On a transfer, the reserve has already been returned when you see this, so no funds are stuck.
431
+ **`APPROVAL_UNSATISFIABLE` / `UNSATISFIABLE` is not a transient conflict.** It is a 409, and 409s are usually worth a retry. This one never is: it means the policy demands more signatures than there are people able to give them, so every retry fails identically. The only resolution is an administrator changing the policy or the approver group. Say that, and do not offer a retry button. On a transfer, the reserve has already been returned when you see this, so no funds are stuck; on address creation, neither the address nor a request exists.
430
432
 
431
433
  **`TRANSFER_STILL_EXECUTING` means "wait", not "no".** The transfer went into `pending` less than 10 minutes ago and execution may still be in flight. The server refuses on purpose: intervening could cause a **second broadcast**, which is far more expensive than waiting. Do not surface it as a failure, do not loop on it — back off past the window and offer the action again.
432
434
 
@@ -506,4 +508,4 @@ These codes exist on the server and never reach a client. Most are simply never
506
508
 
507
509
  Two further codes are reachable only through server misconfiguration and are worth knowing so you classify them correctly rather than showing them to a user: `DB_REQUIRED` (500, a money path reached without its database binding — fail-closed, nothing is left locked) and `VAULT_HAS_NO_WALLET_SERVICE` / `NO_DYNAMIC_ROUTE` / `TOKEN_NOT_REGISTERED` (500, vault configuration gaps that make transfers or address creation impossible until an administrator fixes them).
508
510
 
509
- **Conditions I could not pin down:** `TRANSFER_NOT_EXECUTABLE` is thrown from several places with three different statuses (404 when the transfer is missing, 409 when it is not `pending`, 500 when its execution context fails to load), so apart from "re-read the transfer and trust its status" there is no single client action that fits all of them. `APPROVAL_FAILED` is the fallback for any approval-request creation failure that is not `UNSATISFIABLE`; which failures reach it is not evident from the code, so "retry once with a new key, then escalate" is the honest guidance rather than a specific cause.
511
+ **Conditions I could not pin down:** `TRANSFER_NOT_EXECUTABLE` is thrown from several places with three different statuses (404 when the transfer is missing, 409 when it is not `pending`, 500 when its execution context fails to load), so apart from "re-read the transfer and trust its status" there is no single client action that fits all of them. `APPROVAL_FAILED` is the fallback for any approval-request creation failure that is not `UNSATISFIABLE`, on a transfer and on address creation; which failures reach it is not evident from the code, so "retry once (on a transfer, with a new key), then escalate" is the honest guidance rather than a specific cause.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v3finance/core-sdk",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "The official TypeScript SDK for the V3 Finance Core API — custodial addresses, transfers under policy control, approvals, shared access, labelling and reports",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -9,7 +9,7 @@
9
9
  // the API does not slip in unclassified.
10
10
  //
11
11
  // Operations: 171 · admin: 40 · both: 1 · member: 127 · service: 3
12
- // Spec sha256: 30be5f9b9733d1d1d67eebf21e0bfaa457651e951676211ec9fa464cca5d3795
12
+ // Spec sha256: 1f0f2a38668572c443a84cb0207d4070b419a16c293b8e975f5e21c68e85b15a
13
13
 
14
14
  export type Audience = 'member' | 'admin' | 'service' | 'both' | 'unknown'
15
15
 
package/src/version.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** SDK version, sent in the `user-agent` header. */
2
- export const SDK_VERSION = '0.2.2'
2
+ export const SDK_VERSION = '0.2.3'
3
3
 
4
4
  /** Default API base URL. */
5
5
  export const DEFAULT_BASE_URL = 'https://policy-engine-rest.ezig.workers.dev'