platform-types 1.10.713 → 1.10.715
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/dist/cjs/delivery.js +48 -0
- package/dist/cjs/invoice.js +42 -1
- package/dist/delivery.d.ts +135 -2
- package/dist/delivery.js +47 -1
- package/dist/invoice.d.ts +126 -0
- package/dist/invoice.js +41 -0
- package/dist/platform.d.ts +10 -7
- package/dist/subscription.d.ts +7 -10
- package/package.json +1 -1
package/dist/cjs/delivery.js
CHANGED
|
@@ -1,2 +1,50 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DELIVERY_ERROR_CODES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Every refusal code the delivery handlers (`POST /deliveries`,
|
|
6
|
+
* `POST /deliveries/{id}/events`, `GET /deliveries`, `GET /deliveries/{id}`)
|
|
7
|
+
* put on the wire, beyond the platform-wide set (`VALIDATION_FAILED`,
|
|
8
|
+
* `ROLE_FORBIDDEN`, `tryCatch`'s generic `UNHANDLED_ERROR`). Pinned against
|
|
9
|
+
* the handler sources by `tests/unit/deliveryErrorCodesPublished.test.ts`.
|
|
10
|
+
*
|
|
11
|
+
* - `INVALID_DELIVERY_ID` · 400 — no delivery id in the path.
|
|
12
|
+
* - `DELIVERY_NOT_FOUND` · 404 — unknown id, or another tenant's.
|
|
13
|
+
* - `DELIVERY_NOT_ASSIGNED` · 403 — the delivery names a platform courier
|
|
14
|
+
* (`courier.userId`) and the caller is neither that user nor ADMIN-tier.
|
|
15
|
+
* - `DELIVERY_TERMINAL` · 409 — the delivery is already `'delivered'` or
|
|
16
|
+
* `'failed'`; a failed delivery is re-dispatched through `POST /deliveries`.
|
|
17
|
+
* - `INVALID_IDEMPOTENCY_KEY` · 400 — the key is not ≤200 chars of
|
|
18
|
+
* `[A-Za-z0-9._:-]`.
|
|
19
|
+
* - `IDEMPOTENCY_KEY_REUSE` · 422 — the key was used with a different body.
|
|
20
|
+
* - `IDEMPOTENCY_KEY_FAILED` · 409 — the attempt under the key failed after it
|
|
21
|
+
* may have written proof, or the attempt lookup fenced the key; ask the
|
|
22
|
+
* lookup, then use a new key.
|
|
23
|
+
* - `IDEMPOTENCY_IN_PROGRESS` · 409 — the same key is still running.
|
|
24
|
+
* - `IDEMPOTENCY_LOCK_CONTENTION` · 409 — the key's marker could not be
|
|
25
|
+
* claimed; retry under the SAME key.
|
|
26
|
+
* - `INVALID_CURSOR` · 400 — a `?mine=true` `startKey` that is malformed or
|
|
27
|
+
* names another store's partition.
|
|
28
|
+
* - `IMPERSONATION_READONLY` · 403 — the attempt lookup, under a support
|
|
29
|
+
* session, could answer only by fencing the key (`op: 'delivery.attemptFence'`).
|
|
30
|
+
* - `INVALID_BASE64` · 400, `CONTENT_TOO_LARGE` · 413,
|
|
31
|
+
* `UNSUPPORTED_MEDIA_TYPE` · 415 — the inline proof payload was refused
|
|
32
|
+
* before anything was stored.
|
|
33
|
+
*/
|
|
34
|
+
exports.DELIVERY_ERROR_CODES = [
|
|
35
|
+
'DELIVERY_NOT_FOUND',
|
|
36
|
+
'DELIVERY_NOT_ASSIGNED',
|
|
37
|
+
'DELIVERY_TERMINAL',
|
|
38
|
+
'INVALID_DELIVERY_ID',
|
|
39
|
+
'INVALID_IDEMPOTENCY_KEY',
|
|
40
|
+
'IDEMPOTENCY_KEY_REUSE',
|
|
41
|
+
'IDEMPOTENCY_KEY_FAILED',
|
|
42
|
+
'IDEMPOTENCY_IN_PROGRESS',
|
|
43
|
+
'IDEMPOTENCY_LOCK_CONTENTION',
|
|
44
|
+
'INVALID_CURSOR',
|
|
45
|
+
'IMPERSONATION_READONLY',
|
|
46
|
+
// The proof payload gate (`deliveryAttachmentValidation.ts`).
|
|
47
|
+
'INVALID_BASE64',
|
|
48
|
+
'CONTENT_TOO_LARGE',
|
|
49
|
+
'UNSUPPORTED_MEDIA_TYPE',
|
|
50
|
+
];
|
package/dist/cjs/invoice.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.INVOICE_POST_VOUCHER_ERROR_CODES = void 0;
|
|
3
|
+
exports.INVOICE_ISSUANCE_REFUSAL_RECOVERY = exports.INVOICE_ISSUANCE_REFUSAL_CODES = exports.INVOICE_POST_VOUCHER_ERROR_CODES = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* The codes `POST /invoices` answers AFTER a voucher number was spent — ARCA
|
|
6
6
|
* was asked, or a CAEA number was claimed — as a runtime value the app maps.
|
|
@@ -32,3 +32,44 @@ exports.INVOICE_POST_VOUCHER_ERROR_CODES = [
|
|
|
32
32
|
'INVOICE_EXPORT_OUTCOME_UNKNOWN',
|
|
33
33
|
'CAEA_COMMIT_FAILED_AFTER_CLAIM',
|
|
34
34
|
];
|
|
35
|
+
/**
|
|
36
|
+
* The codes `POST /invoices` answers when it REFUSED to start an issuance — or
|
|
37
|
+
* could not confirm it — before any voucher of this request was recorded, as a
|
|
38
|
+
* runtime value a client maps. Distinct from
|
|
39
|
+
* {@link INVOICE_POST_VOUCHER_ERROR_CODES}: each has its own recovery, given by
|
|
40
|
+
* {@link INVOICE_ISSUANCE_REFUSAL_RECOVERY}.
|
|
41
|
+
*
|
|
42
|
+
* - `INVOICE_ISSUANCE_IN_PROGRESS` · 409 — another issuance of this order is
|
|
43
|
+
* live: the same request's idempotency lock, or another request holding the
|
|
44
|
+
* order's factura issuance guard inside its horizon. Also answered after the
|
|
45
|
+
* order read, when the guard's owner-conditioned pre-ARCA mark or attempt
|
|
46
|
+
* record finds the guard taken over by a successor — before that request's
|
|
47
|
+
* submit went on the wire, so it spent nothing. Retry the same body shortly.
|
|
48
|
+
* - `CAEA_CLAIM_AMBIGUOUS` · 503 — ARCA was down and the CAEA number claim could
|
|
49
|
+
* not be confirmed: the claim may have landed (an operator row records it), no
|
|
50
|
+
* invoice was recorded and nothing was sent to ARCA, and the request released
|
|
51
|
+
* its idempotency record. Retry the same body shortly — a retry claims again,
|
|
52
|
+
* so the worst case is one unused CAEA number, never a second voucher.
|
|
53
|
+
* - `INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH` · 409 — the request's key is bound to
|
|
54
|
+
* an issuance with a different voucher-shaping body (or to a record from
|
|
55
|
+
* before payload hashing, which matches nothing). It does NOT say a voucher
|
|
56
|
+
* exists on the order. Resend only the body that was issued, or credit the
|
|
57
|
+
* voucher first.
|
|
58
|
+
* - `INVOICE_ISSUANCE_OUTCOME_UNCERTAIN` · 409 — an earlier factura of this
|
|
59
|
+
* order was interrupted once it may have spent a voucher number, with no
|
|
60
|
+
* recorded outcome. `data`
|
|
61
|
+
* is {@link InvoiceIssuanceOutcomeUncertainErrorData}. Never retry; support
|
|
62
|
+
* reconciles.
|
|
63
|
+
*/
|
|
64
|
+
exports.INVOICE_ISSUANCE_REFUSAL_CODES = [
|
|
65
|
+
'INVOICE_ISSUANCE_IN_PROGRESS',
|
|
66
|
+
'CAEA_CLAIM_AMBIGUOUS',
|
|
67
|
+
'INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH',
|
|
68
|
+
'INVOICE_ISSUANCE_OUTCOME_UNCERTAIN',
|
|
69
|
+
];
|
|
70
|
+
exports.INVOICE_ISSUANCE_REFUSAL_RECOVERY = {
|
|
71
|
+
INVOICE_ISSUANCE_IN_PROGRESS: 'retry',
|
|
72
|
+
CAEA_CLAIM_AMBIGUOUS: 'retry',
|
|
73
|
+
INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH: 'resend-issued-body',
|
|
74
|
+
INVOICE_ISSUANCE_OUTCOME_UNCERTAIN: 'reconcile',
|
|
75
|
+
};
|
package/dist/delivery.d.ts
CHANGED
|
@@ -84,8 +84,9 @@ declare global {
|
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
86
|
* One append-only entry in a delivery's timeline. Never overwritten and never
|
|
87
|
-
* deleted
|
|
88
|
-
*
|
|
87
|
+
* deleted. `'delivered'` and `'failed'` are TERMINAL: nothing is appended
|
|
88
|
+
* after either (`409 DELIVERY_TERMINAL`), and a failed delivery is
|
|
89
|
+
* re-dispatched as a new delivery through `POST /deliveries`.
|
|
89
90
|
*
|
|
90
91
|
* PK `DELIVERY#{storeId}#{deliveryId}`, SK `EVENT#{createdAt}#{eventId}` —
|
|
91
92
|
* the storeId segment is load-bearing, exactly as it is for `CashEvent`:
|
|
@@ -108,6 +109,18 @@ declare global {
|
|
|
108
109
|
proof?: DeliveryProofAsset[];
|
|
109
110
|
/** Set only on a `'failed'` event. */
|
|
110
111
|
failureReason?: DeliveryFailureReason;
|
|
112
|
+
/**
|
|
113
|
+
* The `Idempotency-Key` the actor appended this event under — what lets a
|
|
114
|
+
* client match its own attempt exactly instead of guessing from type, time
|
|
115
|
+
* or photo count.
|
|
116
|
+
*
|
|
117
|
+
* ⚠️ Actor-scoped on the wire: `GET /deliveries/{id}` returns it only when
|
|
118
|
+
* the reader is this event's `actorUserId` or an ADMIN-tier role, and omits
|
|
119
|
+
* it otherwise. Absent on an event appended WITHOUT a key (still accepted —
|
|
120
|
+
* see `DeliveryEventAppendRequest`), on one written before keys existed, and
|
|
121
|
+
* on the opening `'assigned'` event `POST /deliveries` writes.
|
|
122
|
+
*/
|
|
123
|
+
idempotencyKey?: string;
|
|
111
124
|
}
|
|
112
125
|
/**
|
|
113
126
|
* A `DeliveryProofAsset` carrying the read-time-only `downloadUrl` minted by
|
|
@@ -126,5 +139,125 @@ declare global {
|
|
|
126
139
|
type DeliveryEventWithProofUrls = Omit<DeliveryEvent, 'proof'> & {
|
|
127
140
|
proof?: DeliveryProofAssetWithUrl[];
|
|
128
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* Body of `POST /deliveries/{id}/events`. The `Idempotency-Key` header is
|
|
144
|
+
* OPTIONAL for now and strongly recommended — the key, not the body, is what
|
|
145
|
+
* makes a retry safe. It becomes REQUIRED in a later change, once the courier
|
|
146
|
+
* app sends it.
|
|
147
|
+
*
|
|
148
|
+
* ⚠️ WITHOUT a key the append is NOT idempotent: every call writes a new
|
|
149
|
+
* event, so a resend after a lost response records the event twice. Same
|
|
150
|
+
* validation, assignee scoping and terminal refusal; no replay protection and
|
|
151
|
+
* no attempt lookup.
|
|
152
|
+
*
|
|
153
|
+
* WITH a key, resend the SAME key with the byte-identical body after a lost
|
|
154
|
+
* response: a committed attempt answers its original event
|
|
155
|
+
* (`Idempotent-Replayed: true`), a changed body under that key is
|
|
156
|
+
* `422 IDEMPOTENCY_KEY_REUSE`.
|
|
157
|
+
*
|
|
158
|
+
* A transient fault answers `tryCatch`'s generic `400 UNHANDLED_ERROR`. A
|
|
159
|
+
* same-key resend then replays the attempt if it committed, RE-RUNS only if
|
|
160
|
+
* DynamoDB cancelled its transaction (nothing applied), and otherwise answers
|
|
161
|
+
* `409 IDEMPOTENCY_KEY_FAILED` — the attempt may have stored proof or
|
|
162
|
+
* committed, so the key is sealed. On that 409, ask
|
|
163
|
+
* `GET /deliveries/{id}?idempotencyKey=` (`DeliveryEventAttemptLookup`) and
|
|
164
|
+
* mint a new key only when it answers `'not-committed'`.
|
|
165
|
+
*
|
|
166
|
+
* The server sets `actorUserId`, `createdAt`, `gps.receivedAt` and the proof
|
|
167
|
+
* object keys; none of them is accepted here.
|
|
168
|
+
*
|
|
169
|
+
* Held to its schema by `AssertDeliveryEventAppendRequestMatchesSchema`.
|
|
170
|
+
*/
|
|
171
|
+
interface DeliveryEventAppendRequest {
|
|
172
|
+
type: DeliveryEventType;
|
|
173
|
+
/** ≤ 1000 characters. */
|
|
174
|
+
note?: string;
|
|
175
|
+
gps?: Omit<DeliveryGpsFix, 'receivedAt'>;
|
|
176
|
+
/**
|
|
177
|
+
* Inline base64 proof, at most 5 assets (`MAX_PROOF_ASSETS_PER_EVENT`). Stored
|
|
178
|
+
* under a name derived from the delivery, the key, the asset's position and
|
|
179
|
+
* its bytes, written create-only — a retry can never replace an object.
|
|
180
|
+
*/
|
|
181
|
+
proof?: Array<{
|
|
182
|
+
kind: DeliveryProofAsset['kind'];
|
|
183
|
+
contentType: string;
|
|
184
|
+
data: string;
|
|
185
|
+
}>;
|
|
186
|
+
/** Only on a `'failed'` event — anything else is `400 VALIDATION_FAILED`. */
|
|
187
|
+
failureReason?: DeliveryFailureReason;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* What `GET /deliveries/{id}?idempotencyKey=<key>` answers about the
|
|
191
|
+
* CALLER'S OWN attempt under that key on THAT delivery — the authoritative
|
|
192
|
+
* recovery read, unlike the bounded (`truncated`) timeline, which can never
|
|
193
|
+
* prove absence.
|
|
194
|
+
*
|
|
195
|
+
* - `'committed'` — the attempt's event exists; `event` is that exact
|
|
196
|
+
* original. Never append again for it.
|
|
197
|
+
* - `'pending'` — a request under the key is still in flight. Re-ask after
|
|
198
|
+
* `retryAfterMs`; nothing was fenced.
|
|
199
|
+
* - `'not-committed'` — nothing was appended under the key, and the key is
|
|
200
|
+
* FENCED: a durable tombstone (written by this read, or an earlier one, at
|
|
201
|
+
* `fencedAt`) makes every later commit under it refuse. Only now may the
|
|
202
|
+
* client mint a NEW key for the same intent; the old key answers
|
|
203
|
+
* `409 IDEMPOTENCY_KEY_FAILED` forever.
|
|
204
|
+
*
|
|
205
|
+
* ⚠️ This read can WRITE: when the key is neither committed nor in flight it
|
|
206
|
+
* writes the tombstone before answering `'not-committed'`, so asking is itself
|
|
207
|
+
* a decision to give the key up. A client that would rather keep it resends
|
|
208
|
+
* under the same key instead.
|
|
209
|
+
*
|
|
210
|
+
* Attempt evidence is durable (no TTL), so both `'committed'` and
|
|
211
|
+
* `'not-committed'` stay answerable for the life of the delivery.
|
|
212
|
+
*
|
|
213
|
+
* The lookup takes the append's own authority bar: on a delivery that names
|
|
214
|
+
* a platform courier, a caller who is neither that courier nor ADMIN-tier is
|
|
215
|
+
* `403 DELIVERY_NOT_ASSIGNED`, before anything is read or written. Under an
|
|
216
|
+
* impersonated support session it answers only from stored state, and is
|
|
217
|
+
* `403 IMPERSONATION_READONLY` (`op: 'delivery.attemptFence'`) exactly where
|
|
218
|
+
* answering would need the tombstone.
|
|
219
|
+
*/
|
|
220
|
+
interface DeliveryEventAttemptLookup {
|
|
221
|
+
idempotencyKey: string;
|
|
222
|
+
verdict: 'committed' | 'pending' | 'not-committed';
|
|
223
|
+
/** Present only on `'committed'`. */
|
|
224
|
+
event?: DeliveryEventWithProofUrls;
|
|
225
|
+
/** Present only on `'pending'`. */
|
|
226
|
+
retryAfterMs?: number;
|
|
227
|
+
/** Present only on `'not-committed'` — ms epoch the tombstone was written. */
|
|
228
|
+
fencedAt?: number;
|
|
229
|
+
}
|
|
129
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Every refusal code the delivery handlers (`POST /deliveries`,
|
|
233
|
+
* `POST /deliveries/{id}/events`, `GET /deliveries`, `GET /deliveries/{id}`)
|
|
234
|
+
* put on the wire, beyond the platform-wide set (`VALIDATION_FAILED`,
|
|
235
|
+
* `ROLE_FORBIDDEN`, `tryCatch`'s generic `UNHANDLED_ERROR`). Pinned against
|
|
236
|
+
* the handler sources by `tests/unit/deliveryErrorCodesPublished.test.ts`.
|
|
237
|
+
*
|
|
238
|
+
* - `INVALID_DELIVERY_ID` · 400 — no delivery id in the path.
|
|
239
|
+
* - `DELIVERY_NOT_FOUND` · 404 — unknown id, or another tenant's.
|
|
240
|
+
* - `DELIVERY_NOT_ASSIGNED` · 403 — the delivery names a platform courier
|
|
241
|
+
* (`courier.userId`) and the caller is neither that user nor ADMIN-tier.
|
|
242
|
+
* - `DELIVERY_TERMINAL` · 409 — the delivery is already `'delivered'` or
|
|
243
|
+
* `'failed'`; a failed delivery is re-dispatched through `POST /deliveries`.
|
|
244
|
+
* - `INVALID_IDEMPOTENCY_KEY` · 400 — the key is not ≤200 chars of
|
|
245
|
+
* `[A-Za-z0-9._:-]`.
|
|
246
|
+
* - `IDEMPOTENCY_KEY_REUSE` · 422 — the key was used with a different body.
|
|
247
|
+
* - `IDEMPOTENCY_KEY_FAILED` · 409 — the attempt under the key failed after it
|
|
248
|
+
* may have written proof, or the attempt lookup fenced the key; ask the
|
|
249
|
+
* lookup, then use a new key.
|
|
250
|
+
* - `IDEMPOTENCY_IN_PROGRESS` · 409 — the same key is still running.
|
|
251
|
+
* - `IDEMPOTENCY_LOCK_CONTENTION` · 409 — the key's marker could not be
|
|
252
|
+
* claimed; retry under the SAME key.
|
|
253
|
+
* - `INVALID_CURSOR` · 400 — a `?mine=true` `startKey` that is malformed or
|
|
254
|
+
* names another store's partition.
|
|
255
|
+
* - `IMPERSONATION_READONLY` · 403 — the attempt lookup, under a support
|
|
256
|
+
* session, could answer only by fencing the key (`op: 'delivery.attemptFence'`).
|
|
257
|
+
* - `INVALID_BASE64` · 400, `CONTENT_TOO_LARGE` · 413,
|
|
258
|
+
* `UNSUPPORTED_MEDIA_TYPE` · 415 — the inline proof payload was refused
|
|
259
|
+
* before anything was stored.
|
|
260
|
+
*/
|
|
261
|
+
export declare const DELIVERY_ERROR_CODES: readonly ["DELIVERY_NOT_FOUND", "DELIVERY_NOT_ASSIGNED", "DELIVERY_TERMINAL", "INVALID_DELIVERY_ID", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "INVALID_CURSOR", "IMPERSONATION_READONLY", "INVALID_BASE64", "CONTENT_TOO_LARGE", "UNSUPPORTED_MEDIA_TYPE"];
|
|
262
|
+
export type DeliveryErrorCode = (typeof DELIVERY_ERROR_CODES)[number];
|
|
130
263
|
export {};
|
package/dist/delivery.js
CHANGED
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Every refusal code the delivery handlers (`POST /deliveries`,
|
|
3
|
+
* `POST /deliveries/{id}/events`, `GET /deliveries`, `GET /deliveries/{id}`)
|
|
4
|
+
* put on the wire, beyond the platform-wide set (`VALIDATION_FAILED`,
|
|
5
|
+
* `ROLE_FORBIDDEN`, `tryCatch`'s generic `UNHANDLED_ERROR`). Pinned against
|
|
6
|
+
* the handler sources by `tests/unit/deliveryErrorCodesPublished.test.ts`.
|
|
7
|
+
*
|
|
8
|
+
* - `INVALID_DELIVERY_ID` · 400 — no delivery id in the path.
|
|
9
|
+
* - `DELIVERY_NOT_FOUND` · 404 — unknown id, or another tenant's.
|
|
10
|
+
* - `DELIVERY_NOT_ASSIGNED` · 403 — the delivery names a platform courier
|
|
11
|
+
* (`courier.userId`) and the caller is neither that user nor ADMIN-tier.
|
|
12
|
+
* - `DELIVERY_TERMINAL` · 409 — the delivery is already `'delivered'` or
|
|
13
|
+
* `'failed'`; a failed delivery is re-dispatched through `POST /deliveries`.
|
|
14
|
+
* - `INVALID_IDEMPOTENCY_KEY` · 400 — the key is not ≤200 chars of
|
|
15
|
+
* `[A-Za-z0-9._:-]`.
|
|
16
|
+
* - `IDEMPOTENCY_KEY_REUSE` · 422 — the key was used with a different body.
|
|
17
|
+
* - `IDEMPOTENCY_KEY_FAILED` · 409 — the attempt under the key failed after it
|
|
18
|
+
* may have written proof, or the attempt lookup fenced the key; ask the
|
|
19
|
+
* lookup, then use a new key.
|
|
20
|
+
* - `IDEMPOTENCY_IN_PROGRESS` · 409 — the same key is still running.
|
|
21
|
+
* - `IDEMPOTENCY_LOCK_CONTENTION` · 409 — the key's marker could not be
|
|
22
|
+
* claimed; retry under the SAME key.
|
|
23
|
+
* - `INVALID_CURSOR` · 400 — a `?mine=true` `startKey` that is malformed or
|
|
24
|
+
* names another store's partition.
|
|
25
|
+
* - `IMPERSONATION_READONLY` · 403 — the attempt lookup, under a support
|
|
26
|
+
* session, could answer only by fencing the key (`op: 'delivery.attemptFence'`).
|
|
27
|
+
* - `INVALID_BASE64` · 400, `CONTENT_TOO_LARGE` · 413,
|
|
28
|
+
* `UNSUPPORTED_MEDIA_TYPE` · 415 — the inline proof payload was refused
|
|
29
|
+
* before anything was stored.
|
|
30
|
+
*/
|
|
31
|
+
export const DELIVERY_ERROR_CODES = [
|
|
32
|
+
'DELIVERY_NOT_FOUND',
|
|
33
|
+
'DELIVERY_NOT_ASSIGNED',
|
|
34
|
+
'DELIVERY_TERMINAL',
|
|
35
|
+
'INVALID_DELIVERY_ID',
|
|
36
|
+
'INVALID_IDEMPOTENCY_KEY',
|
|
37
|
+
'IDEMPOTENCY_KEY_REUSE',
|
|
38
|
+
'IDEMPOTENCY_KEY_FAILED',
|
|
39
|
+
'IDEMPOTENCY_IN_PROGRESS',
|
|
40
|
+
'IDEMPOTENCY_LOCK_CONTENTION',
|
|
41
|
+
'INVALID_CURSOR',
|
|
42
|
+
'IMPERSONATION_READONLY',
|
|
43
|
+
// The proof payload gate (`deliveryAttachmentValidation.ts`).
|
|
44
|
+
'INVALID_BASE64',
|
|
45
|
+
'CONTENT_TOO_LARGE',
|
|
46
|
+
'UNSUPPORTED_MEDIA_TYPE',
|
|
47
|
+
];
|
package/dist/invoice.d.ts
CHANGED
|
@@ -837,6 +837,86 @@ declare global {
|
|
|
837
837
|
/** The fortnight's CAEA code the number was claimed under. */
|
|
838
838
|
CAEA: string;
|
|
839
839
|
}
|
|
840
|
+
/**
|
|
841
|
+
* `data` of a `409 INVOICE_ISSUANCE_OUTCOME_UNCERTAIN` answer from
|
|
842
|
+
* `POST /invoices` (a factura): an earlier issuance of this order was
|
|
843
|
+
* interrupted once it may have spent a voucher number — a live or WSFEX
|
|
844
|
+
* submit was recorded, or the outage path (a CAEA stamp or a `pending_cae`
|
|
845
|
+
* degrade) began — and the server holds no evidence of its outcome: the
|
|
846
|
+
* order's `invoices[]` does not name the recorded invoice and no
|
|
847
|
+
* stranded-voucher row names it. ARCA may hold a voucher for it, or may hold
|
|
848
|
+
* nothing.
|
|
849
|
+
*
|
|
850
|
+
* ⚠️ **Never retry, and never resend the original body as proof.** An
|
|
851
|
+
* unchanged body, a refetched order with no voucher and an elapsed lock are
|
|
852
|
+
* not evidence the earlier attempt spent nothing. The order stays fenced
|
|
853
|
+
* until support reconciles the attempt at ARCA and releases it.
|
|
854
|
+
*/
|
|
855
|
+
interface InvoiceIssuanceOutcomeUncertainErrorData {
|
|
856
|
+
orderId: string;
|
|
857
|
+
/** The server's id for the interrupted invoice. No order entry names it. */
|
|
858
|
+
invoiceId?: string;
|
|
859
|
+
/**
|
|
860
|
+
* How the interrupted attempt reached ARCA: `cae` (live FECAESolicitar),
|
|
861
|
+
* `export` (WSFEX FEXAuthorize) or `outage` (a CAEA stamp or a
|
|
862
|
+
* `pending_cae` degrade). Written with `invoiceId` and `submittedAt` by
|
|
863
|
+
* the same mark, so absent only on a row edited by hand.
|
|
864
|
+
*/
|
|
865
|
+
path?: 'cae' | 'export' | 'outage';
|
|
866
|
+
/** Epoch ms the interrupted attempt was cleared to contact ARCA. */
|
|
867
|
+
submittedAt?: number;
|
|
868
|
+
/**
|
|
869
|
+
* The voucher the interrupted attempt spent or was about to spend. A
|
|
870
|
+
* `cae`/`export` answer always carries it — such a row with no recorded
|
|
871
|
+
* voucher proves no submit went out and is never refused. On `outage` it
|
|
872
|
+
* is the claimed CAEA number (`kind: 'caea'`) when that best-effort
|
|
873
|
+
* record landed, or a live submit's voucher (`kind: 'arca'`) when the
|
|
874
|
+
* outage branch fell through to it; absent, it proves nothing.
|
|
875
|
+
*/
|
|
876
|
+
voucher?: {
|
|
877
|
+
/** `arca` — submitted to ARCA (CAE or WSFEX); `caea` — a claimed CAEA number. */
|
|
878
|
+
kind: 'arca' | 'caea';
|
|
879
|
+
/** ARCA `CbteTipo` — the voucher class. */
|
|
880
|
+
CbteTipo: number;
|
|
881
|
+
/** ARCA `PtoVta` — the punto de venta it went out under. */
|
|
882
|
+
PtoVta: number;
|
|
883
|
+
/** ARCA `CbteNro` — the number ARCA may or may not hold. */
|
|
884
|
+
CbteNro: number;
|
|
885
|
+
/**
|
|
886
|
+
* The submitted voucher's `CbteFch` (`yyyymmdd`), when the attempt
|
|
887
|
+
* recorded one. `fingerprintMatches` compares it too: a voucher found
|
|
888
|
+
* at the number under another date is not this one.
|
|
889
|
+
*/
|
|
890
|
+
CbteFch?: string;
|
|
891
|
+
/**
|
|
892
|
+
* A live `FECAESolicitar` attempt's identifying fields, as submitted —
|
|
893
|
+
* compare a `FECompConsultar` answer at the number against these, never
|
|
894
|
+
* against a rebuild from the order. The receptor's `DocNro` is withheld:
|
|
895
|
+
* compare it against the order's `invoiceMethod`. Absent on a CAEA claim,
|
|
896
|
+
* a WSFEX attempt, and an attempt recorded before it was stored.
|
|
897
|
+
*/
|
|
898
|
+
fingerprint?: InvoiceIssuanceAttemptFingerprint;
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* The fields `FECompConsultar` echoes that identify a submitted voucher, as
|
|
903
|
+
* the interrupted attempt sent them, minus the receptor's `DocNro` and the
|
|
904
|
+
* date (`CbteFch`, beside it). Amounts are in the voucher currency (`MonId`).
|
|
905
|
+
*/
|
|
906
|
+
interface InvoiceIssuanceAttemptFingerprint {
|
|
907
|
+
/** ARCA `DocTipo` — the receptor's document type. */
|
|
908
|
+
DocTipo: number;
|
|
909
|
+
/** ARCA `MonId` — the voucher currency code. */
|
|
910
|
+
MonId: string;
|
|
911
|
+
/** ARCA `MonCotiz` — the rate the voucher was submitted at. */
|
|
912
|
+
MonCotiz: number;
|
|
913
|
+
ImpTotal: number;
|
|
914
|
+
ImpNeto: number;
|
|
915
|
+
ImpIVA: number;
|
|
916
|
+
ImpTotConc: number;
|
|
917
|
+
ImpOpEx: number;
|
|
918
|
+
ImpTrib: number;
|
|
919
|
+
}
|
|
840
920
|
}
|
|
841
921
|
/**
|
|
842
922
|
* The codes `POST /invoices` answers AFTER a voucher number was spent — ARCA
|
|
@@ -866,4 +946,50 @@ declare global {
|
|
|
866
946
|
*/
|
|
867
947
|
export declare const INVOICE_POST_VOUCHER_ERROR_CODES: readonly ["INVOICE_PERSIST_AFTER_CAE_FAILED", "INVOICE_EXPORT_OUTCOME_UNKNOWN", "CAEA_COMMIT_FAILED_AFTER_CLAIM"];
|
|
868
948
|
export type InvoicePostVoucherErrorCode = (typeof INVOICE_POST_VOUCHER_ERROR_CODES)[number];
|
|
949
|
+
/**
|
|
950
|
+
* The codes `POST /invoices` answers when it REFUSED to start an issuance — or
|
|
951
|
+
* could not confirm it — before any voucher of this request was recorded, as a
|
|
952
|
+
* runtime value a client maps. Distinct from
|
|
953
|
+
* {@link INVOICE_POST_VOUCHER_ERROR_CODES}: each has its own recovery, given by
|
|
954
|
+
* {@link INVOICE_ISSUANCE_REFUSAL_RECOVERY}.
|
|
955
|
+
*
|
|
956
|
+
* - `INVOICE_ISSUANCE_IN_PROGRESS` · 409 — another issuance of this order is
|
|
957
|
+
* live: the same request's idempotency lock, or another request holding the
|
|
958
|
+
* order's factura issuance guard inside its horizon. Also answered after the
|
|
959
|
+
* order read, when the guard's owner-conditioned pre-ARCA mark or attempt
|
|
960
|
+
* record finds the guard taken over by a successor — before that request's
|
|
961
|
+
* submit went on the wire, so it spent nothing. Retry the same body shortly.
|
|
962
|
+
* - `CAEA_CLAIM_AMBIGUOUS` · 503 — ARCA was down and the CAEA number claim could
|
|
963
|
+
* not be confirmed: the claim may have landed (an operator row records it), no
|
|
964
|
+
* invoice was recorded and nothing was sent to ARCA, and the request released
|
|
965
|
+
* its idempotency record. Retry the same body shortly — a retry claims again,
|
|
966
|
+
* so the worst case is one unused CAEA number, never a second voucher.
|
|
967
|
+
* - `INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH` · 409 — the request's key is bound to
|
|
968
|
+
* an issuance with a different voucher-shaping body (or to a record from
|
|
969
|
+
* before payload hashing, which matches nothing). It does NOT say a voucher
|
|
970
|
+
* exists on the order. Resend only the body that was issued, or credit the
|
|
971
|
+
* voucher first.
|
|
972
|
+
* - `INVOICE_ISSUANCE_OUTCOME_UNCERTAIN` · 409 — an earlier factura of this
|
|
973
|
+
* order was interrupted once it may have spent a voucher number, with no
|
|
974
|
+
* recorded outcome. `data`
|
|
975
|
+
* is {@link InvoiceIssuanceOutcomeUncertainErrorData}. Never retry; support
|
|
976
|
+
* reconciles.
|
|
977
|
+
*/
|
|
978
|
+
export declare const INVOICE_ISSUANCE_REFUSAL_CODES: readonly ["INVOICE_ISSUANCE_IN_PROGRESS", "CAEA_CLAIM_AMBIGUOUS", "INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH", "INVOICE_ISSUANCE_OUTCOME_UNCERTAIN"];
|
|
979
|
+
export type InvoiceIssuanceRefusalCode = (typeof INVOICE_ISSUANCE_REFUSAL_CODES)[number];
|
|
980
|
+
/**
|
|
981
|
+
* What a client may do with each {@link InvoiceIssuanceRefusalCode}:
|
|
982
|
+
*
|
|
983
|
+
* - `retry` — resend the same body after a short wait;
|
|
984
|
+
* - `resend-issued-body` — only the body of the issuance the key is bound to
|
|
985
|
+
* (or credit that voucher first); a corrected body is refused again;
|
|
986
|
+
* - `reconcile` — do not resend at all; the order is fenced until support acts.
|
|
987
|
+
*/
|
|
988
|
+
export type InvoiceIssuanceRecovery = 'retry' | 'resend-issued-body' | 'reconcile';
|
|
989
|
+
export declare const INVOICE_ISSUANCE_REFUSAL_RECOVERY: {
|
|
990
|
+
readonly INVOICE_ISSUANCE_IN_PROGRESS: "retry";
|
|
991
|
+
readonly CAEA_CLAIM_AMBIGUOUS: "retry";
|
|
992
|
+
readonly INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH: "resend-issued-body";
|
|
993
|
+
readonly INVOICE_ISSUANCE_OUTCOME_UNCERTAIN: "reconcile";
|
|
994
|
+
};
|
|
869
995
|
export {};
|
package/dist/invoice.js
CHANGED
|
@@ -29,3 +29,44 @@ export const INVOICE_POST_VOUCHER_ERROR_CODES = [
|
|
|
29
29
|
'INVOICE_EXPORT_OUTCOME_UNKNOWN',
|
|
30
30
|
'CAEA_COMMIT_FAILED_AFTER_CLAIM',
|
|
31
31
|
];
|
|
32
|
+
/**
|
|
33
|
+
* The codes `POST /invoices` answers when it REFUSED to start an issuance — or
|
|
34
|
+
* could not confirm it — before any voucher of this request was recorded, as a
|
|
35
|
+
* runtime value a client maps. Distinct from
|
|
36
|
+
* {@link INVOICE_POST_VOUCHER_ERROR_CODES}: each has its own recovery, given by
|
|
37
|
+
* {@link INVOICE_ISSUANCE_REFUSAL_RECOVERY}.
|
|
38
|
+
*
|
|
39
|
+
* - `INVOICE_ISSUANCE_IN_PROGRESS` · 409 — another issuance of this order is
|
|
40
|
+
* live: the same request's idempotency lock, or another request holding the
|
|
41
|
+
* order's factura issuance guard inside its horizon. Also answered after the
|
|
42
|
+
* order read, when the guard's owner-conditioned pre-ARCA mark or attempt
|
|
43
|
+
* record finds the guard taken over by a successor — before that request's
|
|
44
|
+
* submit went on the wire, so it spent nothing. Retry the same body shortly.
|
|
45
|
+
* - `CAEA_CLAIM_AMBIGUOUS` · 503 — ARCA was down and the CAEA number claim could
|
|
46
|
+
* not be confirmed: the claim may have landed (an operator row records it), no
|
|
47
|
+
* invoice was recorded and nothing was sent to ARCA, and the request released
|
|
48
|
+
* its idempotency record. Retry the same body shortly — a retry claims again,
|
|
49
|
+
* so the worst case is one unused CAEA number, never a second voucher.
|
|
50
|
+
* - `INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH` · 409 — the request's key is bound to
|
|
51
|
+
* an issuance with a different voucher-shaping body (or to a record from
|
|
52
|
+
* before payload hashing, which matches nothing). It does NOT say a voucher
|
|
53
|
+
* exists on the order. Resend only the body that was issued, or credit the
|
|
54
|
+
* voucher first.
|
|
55
|
+
* - `INVOICE_ISSUANCE_OUTCOME_UNCERTAIN` · 409 — an earlier factura of this
|
|
56
|
+
* order was interrupted once it may have spent a voucher number, with no
|
|
57
|
+
* recorded outcome. `data`
|
|
58
|
+
* is {@link InvoiceIssuanceOutcomeUncertainErrorData}. Never retry; support
|
|
59
|
+
* reconciles.
|
|
60
|
+
*/
|
|
61
|
+
export const INVOICE_ISSUANCE_REFUSAL_CODES = [
|
|
62
|
+
'INVOICE_ISSUANCE_IN_PROGRESS',
|
|
63
|
+
'CAEA_CLAIM_AMBIGUOUS',
|
|
64
|
+
'INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH',
|
|
65
|
+
'INVOICE_ISSUANCE_OUTCOME_UNCERTAIN',
|
|
66
|
+
];
|
|
67
|
+
export const INVOICE_ISSUANCE_REFUSAL_RECOVERY = {
|
|
68
|
+
INVOICE_ISSUANCE_IN_PROGRESS: 'retry',
|
|
69
|
+
CAEA_CLAIM_AMBIGUOUS: 'retry',
|
|
70
|
+
INVOICE_IDEMPOTENCY_PAYLOAD_MISMATCH: 'resend-issued-body',
|
|
71
|
+
INVOICE_ISSUANCE_OUTCOME_UNCERTAIN: 'reconcile',
|
|
72
|
+
};
|
package/dist/platform.d.ts
CHANGED
|
@@ -846,15 +846,15 @@ export interface TenantBillingRollupRow {
|
|
|
846
846
|
}
|
|
847
847
|
/**
|
|
848
848
|
* @deprecated Nothing produces one any more. The copy↔entitlement consistency
|
|
849
|
-
* check went with the free-text plan copy it checked,
|
|
850
|
-
*
|
|
851
|
-
* type stays only
|
|
852
|
-
*
|
|
849
|
+
* check went with the free-text plan copy it checked, and the `warnings` array
|
|
850
|
+
* that carried its findings is gone from the `POST` / `PATCH
|
|
851
|
+
* /platform/billing/plans` replies. The type stays only for the archived check
|
|
852
|
+
* under `stacks/services/_retired/` and for a consumer still naming it.
|
|
853
853
|
*/
|
|
854
854
|
export type CatalogWarningCode = 'NUMERIC_MISMATCH' | 'UNLIMITED_ADVERTISED_AS_CAPPED' | 'UNBACKED_CAPABILITY' | 'MISSING_FEATURE_ROW';
|
|
855
855
|
/**
|
|
856
|
-
* @deprecated See {@link CatalogWarningCode} — no writer emits one
|
|
857
|
-
* `warnings` array
|
|
856
|
+
* @deprecated See {@link CatalogWarningCode} — no writer emits one, and no
|
|
857
|
+
* reply carries a `warnings` array of them any more.
|
|
858
858
|
*/
|
|
859
859
|
export interface CatalogWarning {
|
|
860
860
|
code: CatalogWarningCode;
|
|
@@ -1053,7 +1053,10 @@ export interface PlatformMrrMetrics {
|
|
|
1053
1053
|
* the safer direction for a number an operator acts on.
|
|
1054
1054
|
*/
|
|
1055
1055
|
countedStatuses: SubscriptionStatus[];
|
|
1056
|
-
/**
|
|
1056
|
+
/**
|
|
1057
|
+
* `priceAnnualCents` is the yearly total charged once per year, so
|
|
1058
|
+
* `priceAnnualCents / annualDivisor` is one annual subscription's monthly contribution.
|
|
1059
|
+
*/
|
|
1057
1060
|
annualDivisor: number;
|
|
1058
1061
|
/** Subscriptions in a counted status. The denominator for `excluded`. */
|
|
1059
1062
|
countedSubscriptions: number;
|
package/dist/subscription.d.ts
CHANGED
|
@@ -249,7 +249,7 @@ declare global {
|
|
|
249
249
|
*
|
|
250
250
|
* Prices are integers in the `currency` smallest unit (centavos for ARS,
|
|
251
251
|
* cents for USD). `null` = "Contactar ventas" (AVANZADO annual at launch
|
|
252
|
-
* is sales-led; basico
|
|
252
|
+
* is sales-led; basico is free) per spec §6.4.
|
|
253
253
|
*
|
|
254
254
|
* **Breaking change vs 1.1.x:** the catalog Plan interface was reshaped
|
|
255
255
|
* to match the BE wire format. Renames & removals:
|
|
@@ -293,7 +293,12 @@ declare global {
|
|
|
293
293
|
displayOrder: number;
|
|
294
294
|
/** Monthly price in `currency` smallest units. `null` = sales-led / free. */
|
|
295
295
|
priceMonthlyCents: number | null;
|
|
296
|
-
/**
|
|
296
|
+
/**
|
|
297
|
+
* The YEARLY TOTAL, charged once per year, in `currency` smallest units —
|
|
298
|
+
* never a per-month figure. Divide by 12 for a monthly equivalent.
|
|
299
|
+
* Nothing enforces its ratio to `priceMonthlyCents`; the operator sets
|
|
300
|
+
* both. `null` = sales-led / free.
|
|
301
|
+
*/
|
|
297
302
|
priceAnnualCents: number | null;
|
|
298
303
|
/**
|
|
299
304
|
* Currency the prices are denominated in. `'ARS'` at launch; `'USD'`
|
|
@@ -313,14 +318,6 @@ declare global {
|
|
|
313
318
|
* `limit`.
|
|
314
319
|
*/
|
|
315
320
|
features: PlanFeature[];
|
|
316
|
-
/**
|
|
317
|
-
* @deprecated ALWAYS `[]`. The free-text card copy was retired: a plan
|
|
318
|
-
* card renders {@link Plan.highlights} instead, and no write accepts
|
|
319
|
-
* `bullets` any more (`POST`/`PATCH /platform/billing/plans` answer 400
|
|
320
|
-
* `VALIDATION_FAILED`). A value an old row still stores is ignored, never
|
|
321
|
-
* echoed. The key will be removed once the app's copy editor is gone.
|
|
322
|
-
*/
|
|
323
|
-
bullets: string[];
|
|
324
321
|
/**
|
|
325
322
|
* Keys worth calling out on this tier's card: highlight-eligible keys with
|
|
326
323
|
* status `live` or `service` whose grant improves on the next lower
|