@nuanu-ai/agentify-contracts 0.3.2 → 0.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 +1 -1
- package/dist/api.d.ts +20 -7
- package/dist/api.js +56 -18
- package/dist/index.d.ts +13 -4
- package/dist/index.js +4 -3
- package/dist/merchant.d.ts +38 -0
- package/dist/merchant.js +72 -4
- package/dist/order-status.js +16 -3
- package/dist/results.d.ts +24 -0
- package/dist/results.js +41 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ The contract is versioned, and the version is how an SDK and a gateway agree
|
|
|
23
23
|
that they read the same vocabulary; a worker whose version the gateway does not
|
|
24
24
|
share stops at startup rather than half understanding a document. What the
|
|
25
25
|
merchant-facing side of all this looks like in use is at
|
|
26
|
-
<https://
|
|
26
|
+
<https://agentify.ad/docs/>.
|
|
27
27
|
|
|
28
28
|
## License
|
|
29
29
|
|
package/dist/api.d.ts
CHANGED
|
@@ -225,9 +225,11 @@ export declare const ReceiptListSchema: z.ZodObject<{
|
|
|
225
225
|
/**
|
|
226
226
|
* The question a merchant puts in the query string when listing orders.
|
|
227
227
|
*
|
|
228
|
-
* `open=true` narrows the list to the orders
|
|
229
|
-
*
|
|
230
|
-
*
|
|
228
|
+
* `open=true` narrows the list to the orders a restarted worker should walk:
|
|
229
|
+
* ones the merchant was handed and has not finished, and the two that stay
|
|
230
|
+
* open after the purchase itself is over, an order owing a refund and one
|
|
231
|
+
* delivered but never paid for. An order that was priced and never paid, and
|
|
232
|
+
* never reached the handler, is not in that narrowing. Leaving the field out
|
|
231
233
|
* asks for everything.
|
|
232
234
|
*
|
|
233
235
|
* The value is text and not a boolean, because that is what a query string
|
|
@@ -455,9 +457,9 @@ export declare const PurchaseRequestSchema: z.ZodObject<{
|
|
|
455
457
|
/**
|
|
456
458
|
* What became of a purchase, told to the agent that made it.
|
|
457
459
|
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
460
|
+
* The shape of the list is the decision rather than its length. This document
|
|
461
|
+
* is what the buyer is owed — where their order stands, what it cost them, the
|
|
462
|
+
* goods once those exist, and where to ask again — and it is deliberately
|
|
461
463
|
* smaller than the merchant's own view of the same order. It carries no
|
|
462
464
|
* merchant, no merchant's key for the product, none of the parameters the
|
|
463
465
|
* buyer sent and nothing about any other order, because whoever holds an
|
|
@@ -490,6 +492,7 @@ export declare const PurchaseRequestSchema: z.ZodObject<{
|
|
|
490
492
|
*/
|
|
491
493
|
export declare const AgentOrderStatusSchema: z.ZodObject<{
|
|
492
494
|
order_id: z.ZodString;
|
|
495
|
+
status_url: z.ZodURL;
|
|
493
496
|
status: z.ZodEnum<{
|
|
494
497
|
delivered: "delivered";
|
|
495
498
|
in_progress: "in_progress";
|
|
@@ -780,7 +783,7 @@ export type ErrorEnvelope = z.infer<typeof ErrorEnvelopeSchema>;
|
|
|
780
783
|
* has to act on it belongs to the route that sends it and to the sentence the
|
|
781
784
|
* refusal carries.
|
|
782
785
|
*/
|
|
783
|
-
export declare const ERROR_CODES: readonly ["body_too_large", "body_undecodable", "call_refused", "charset_unsupported", "encoding_unsupported", "gateway_failed", "key_made_for_a_cabinet", "key_opened_this_call", "malformed_body", "malformed_query", "merchant_departed", "no_such_item", "no_such_key", "no_such_order", "no_such_route", "not_a_cabinet_key", "not_authorised", "not_invited", "not_selling", "not_this_purchase", "order_closed_before_it_was_priced", "order_not_priced_yet", "params_do_not_fit", "payment_already_spent", "payment_not_taken", "payment_not_verified"];
|
|
786
|
+
export declare const ERROR_CODES: readonly ["body_too_large", "body_undecodable", "call_refused", "charset_unsupported", "encoding_unsupported", "gateway_failed", "key_made_for_a_cabinet", "key_opened_this_call", "malformed_body", "malformed_query", "merchant_departed", "no_such_item", "no_such_key", "no_such_order", "no_such_route", "not_a_cabinet_key", "not_authorised", "not_invited", "not_selling", "not_this_purchase", "order_closed_before_it_was_priced", "order_not_priced_yet", "params_do_not_fit", "payment_already_spent", "payment_not_taken", "payment_not_verified", "wallet_change_not_announced", "wallet_change_nobody_to_tell", "wallet_change_raced", "wallet_change_unconfirmed"];
|
|
784
787
|
/** One of the codes this gateway is known to refuse a call with. */
|
|
785
788
|
export type ErrorCode = (typeof ERROR_CODES)[number];
|
|
786
789
|
/**
|
|
@@ -1277,6 +1280,10 @@ export declare const API_ROUTES: Readonly<{
|
|
|
1277
1280
|
response: {
|
|
1278
1281
|
document: z.ZodObject<{
|
|
1279
1282
|
payout_wallet: z.ZodNullable<z.ZodString>;
|
|
1283
|
+
pending: z.ZodNullable<z.ZodObject<{
|
|
1284
|
+
payout_wallet: z.ZodString;
|
|
1285
|
+
takes_effect_at: z.ZodISODateTime;
|
|
1286
|
+
}, z.core.$strict>>;
|
|
1280
1287
|
}, z.core.$strict>;
|
|
1281
1288
|
};
|
|
1282
1289
|
};
|
|
@@ -1291,6 +1298,10 @@ export declare const API_ROUTES: Readonly<{
|
|
|
1291
1298
|
response: {
|
|
1292
1299
|
document: z.ZodObject<{
|
|
1293
1300
|
payout_wallet: z.ZodNullable<z.ZodString>;
|
|
1301
|
+
pending: z.ZodNullable<z.ZodObject<{
|
|
1302
|
+
payout_wallet: z.ZodString;
|
|
1303
|
+
takes_effect_at: z.ZodISODateTime;
|
|
1304
|
+
}, z.core.$strict>>;
|
|
1294
1305
|
}, z.core.$strict>;
|
|
1295
1306
|
};
|
|
1296
1307
|
};
|
|
@@ -1826,6 +1837,7 @@ export declare const API_ROUTES: Readonly<{
|
|
|
1826
1837
|
response: {
|
|
1827
1838
|
document: z.ZodObject<{
|
|
1828
1839
|
order_id: z.ZodString;
|
|
1840
|
+
status_url: z.ZodURL;
|
|
1829
1841
|
status: z.ZodEnum<{
|
|
1830
1842
|
delivered: "delivered";
|
|
1831
1843
|
in_progress: "in_progress";
|
|
@@ -1861,6 +1873,7 @@ export declare const API_ROUTES: Readonly<{
|
|
|
1861
1873
|
response: {
|
|
1862
1874
|
document: z.ZodObject<{
|
|
1863
1875
|
order_id: z.ZodString;
|
|
1876
|
+
status_url: z.ZodURL;
|
|
1864
1877
|
status: z.ZodEnum<{
|
|
1865
1878
|
delivered: "delivered";
|
|
1866
1879
|
in_progress: "in_progress";
|
package/dist/api.js
CHANGED
|
@@ -105,7 +105,7 @@ export const MerchantCardListSchema = z
|
|
|
105
105
|
cards: z.array(MerchantCardSchema),
|
|
106
106
|
})
|
|
107
107
|
.meta({
|
|
108
|
-
description: "A merchant's own catalog: every card they have published, and whether they are taking new orders at all. The merchant's own selling word is here as well as on each card because the two are different facts, and neither can be worked out from the other. A card reads open only where all of it holds at once: the merchant is selling, the card is not paused in its own right, the merchant has a name for it to be sold under,
|
|
108
|
+
description: "A merchant's own catalog: every card they have published, and whether they are taking new orders at all. The merchant's own selling word is here as well as on each card because the two are different facts, and neither can be worked out from the other. A card reads open only where all of it holds at once: the merchant is selling, the card is not paused in its own right, the merchant has a name for it to be sold under, on a deployment that settles on a real chain a wallet for the money to be paid into, and on the live deployment the operator's approval. So a card can read paused while this field reads open, and this field does not say which of the reasons it was. What does say is the refusal at the publish, whose findings about the merchant carry the codes no_seller_name, no_payout_wallet and no_operator_approval, and the merchant's own settings. This document does not say whether it is the whole catalog: paging is not designed, and when it is, this object grows the field that answers it.",
|
|
109
109
|
});
|
|
110
110
|
/**
|
|
111
111
|
* Every receipt this merchant has.
|
|
@@ -129,9 +129,11 @@ export const ReceiptListSchema = z
|
|
|
129
129
|
/**
|
|
130
130
|
* The question a merchant puts in the query string when listing orders.
|
|
131
131
|
*
|
|
132
|
-
* `open=true` narrows the list to the orders
|
|
133
|
-
*
|
|
134
|
-
*
|
|
132
|
+
* `open=true` narrows the list to the orders a restarted worker should walk:
|
|
133
|
+
* ones the merchant was handed and has not finished, and the two that stay
|
|
134
|
+
* open after the purchase itself is over, an order owing a refund and one
|
|
135
|
+
* delivered but never paid for. An order that was priced and never paid, and
|
|
136
|
+
* never reached the handler, is not in that narrowing. Leaving the field out
|
|
135
137
|
* asks for everything.
|
|
136
138
|
*
|
|
137
139
|
* The value is text and not a boolean, because that is what a query string
|
|
@@ -146,7 +148,7 @@ export const OrderListQuerySchema = z
|
|
|
146
148
|
open: z.enum(["true", "false"]).optional(),
|
|
147
149
|
})
|
|
148
150
|
.meta({
|
|
149
|
-
description: 'Which orders to list. Written as text because a query string carries text. "true" narrows the list to the orders
|
|
151
|
+
description: 'Which orders to list. Written as text because a query string carries text. "true" narrows the list to the orders a restarted worker should walk: ones the merchant was handed and has not finished, an order owing a refund, and one delivered but never paid for. An order that was priced and never paid, and never reached the handler, is not in that narrowing. Leaving the field out asks for everything.',
|
|
150
152
|
});
|
|
151
153
|
/**
|
|
152
154
|
* What a worker asks of one poll.
|
|
@@ -309,9 +311,9 @@ export const PurchaseRequestSchema = z
|
|
|
309
311
|
/**
|
|
310
312
|
* What became of a purchase, told to the agent that made it.
|
|
311
313
|
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
314
|
+
* The shape of the list is the decision rather than its length. This document
|
|
315
|
+
* is what the buyer is owed — where their order stands, what it cost them, the
|
|
316
|
+
* goods once those exist, and where to ask again — and it is deliberately
|
|
315
317
|
* smaller than the merchant's own view of the same order. It carries no
|
|
316
318
|
* merchant, no merchant's key for the product, none of the parameters the
|
|
317
319
|
* buyer sent and nothing about any other order, because whoever holds an
|
|
@@ -345,6 +347,38 @@ export const PurchaseRequestSchema = z
|
|
|
345
347
|
export const AgentOrderStatusSchema = z
|
|
346
348
|
.strictObject({
|
|
347
349
|
order_id: IdentifierSchema,
|
|
350
|
+
/**
|
|
351
|
+
* Where this order is read again: the whole address of its status route,
|
|
352
|
+
* scheme and host included.
|
|
353
|
+
*
|
|
354
|
+
* It exists for the agent that bought goods that come later. That agent
|
|
355
|
+
* holds this document and nothing else, it has already paid, and the
|
|
356
|
+
* goods are collected at this address. The path is not something it could
|
|
357
|
+
* work out from what it holds — the purchase was made at an address that
|
|
358
|
+
* names the product rather than the order — and a guess that misses is
|
|
359
|
+
* answered `no_such_route`, which says nothing about the order at all.
|
|
360
|
+
*
|
|
361
|
+
* Absolute, so that it is called as it stands: a bare path would have to
|
|
362
|
+
* be joined onto a host the agent was never told was the right one. It is
|
|
363
|
+
* built from the address the gateway is configured to answer as and never
|
|
364
|
+
* from the request that asked, because behind the proxy that ends an
|
|
365
|
+
* agent's TLS connection the request says plain http and names whatever
|
|
366
|
+
* host the proxy or the caller wrote. Plain http is allowed by the pattern
|
|
367
|
+
* all the same, because a gateway on a developer's own machine answers on
|
|
368
|
+
* it; a deployment's address is https because its configuration is.
|
|
369
|
+
*
|
|
370
|
+
* The scheme is a pattern rather than zod's own protocol option for the
|
|
371
|
+
* reason the price hook's is (`PriceCheckSchema` in `card.ts`): a pattern
|
|
372
|
+
* is what survives into the JSON Schema export, so a client generated from
|
|
373
|
+
* that document refuses a bare path as well. It is case-sensitive because
|
|
374
|
+
* a flag on a pattern does not survive that export, and a schema that read
|
|
375
|
+
* the scheme without regard to case would accept what the exported
|
|
376
|
+
* document refuses. Nothing is lost by it: the gateway's configuration
|
|
377
|
+
* already requires its public address in lower case.
|
|
378
|
+
*/
|
|
379
|
+
status_url: z
|
|
380
|
+
.url()
|
|
381
|
+
.regex(/^https?:\/\//, "an order's status address is a whole http or https address, not a path"),
|
|
348
382
|
status: OrderStatusSchema,
|
|
349
383
|
/**
|
|
350
384
|
* The price this order was priced at, or null where nobody ever named one
|
|
@@ -412,7 +446,7 @@ export const AgentOrderStatusSchema = z
|
|
|
412
446
|
refusal: RefusalSchema.optional(),
|
|
413
447
|
})
|
|
414
448
|
.meta({
|
|
415
|
-
description: 'What became of one purchase, in the words an agent and a merchant both read: where the order stands, what it was priced at, the goods once they are the buyer\'s, and why the merchant would not sell where that is what ended it. It is smaller than the merchant\'s own view of the same order on purpose — no merchant, no merchant\'s own key for the product, none of the purchase parameters and nothing about any other order. The price is what the buyer was asked for and not proof that anything was charged: an order that was priced and then ended without a sale still carries it, and the status is what says which happened. A null price means nobody ever named one for this order, and a null delivery means there are no goods here to hand over; both fields are always present, because an absent field is a silence a reader cannot tell from an oversight. "refusal" is the exception and is present only where a merchant refused: their own short code to branch on and their own sentence to show, carried across unchanged. The code is an open set — "out_of_stock", "invalid_params" and "cannot_fulfill" are read the same way by everybody, and a merchant whose reason fits none of them sends their own word, so an unfamiliar code has to fall through to the sentence rather than break a reader. An absent "refusal" means there is no refusal to quote and never that one was dropped, which leaves two endings still coarse: "rejected" also covers a product that was gone and a payment that failed its check, and neither of those was worded by anybody — the first because a price answer of "not available" carries no words, the second because it is refused at the door in an error envelope instead. A null delivery is likewise not a promise that no goods were ever made: a purchase whose charge failed or went unanswered can leave goods the buyer has not paid for, and this document withholds them rather than describing them. Every answer says whether the money behind the purchase was real: a gateway settling against nothing produces every other field here exactly as a real charge would, so a reader taking this for proof of a payment has to read that word first.',
|
|
449
|
+
description: 'What became of one purchase, in the words an agent and a merchant both read: where the order stands, what it was priced at, the goods once they are the buyer\'s, and why the merchant would not sell where that is what ended it. "status_url" is where this document is read again — the whole address of the order\'s status route, and the place an agent that bought goods that come later collects them. It is absolute and called as it stands, and it is the address the gateway is configured to answer as, never one taken from the request that asked. It is smaller than the merchant\'s own view of the same order on purpose — no merchant, no merchant\'s own key for the product, none of the purchase parameters and nothing about any other order. The price is what the buyer was asked for and not proof that anything was charged: an order that was priced and then ended without a sale still carries it, and the status is what says which happened. A null price means nobody ever named one for this order, and a null delivery means there are no goods here to hand over; both fields are always present, because an absent field is a silence a reader cannot tell from an oversight. "refusal" is the exception and is present only where a merchant refused: their own short code to branch on and their own sentence to show, carried across unchanged. The code is an open set — "out_of_stock", "invalid_params" and "cannot_fulfill" are read the same way by everybody, and a merchant whose reason fits none of them sends their own word, so an unfamiliar code has to fall through to the sentence rather than break a reader. An absent "refusal" means there is no refusal to quote and never that one was dropped, which leaves two endings still coarse: "rejected" also covers a product that was gone and a payment that failed its check, and neither of those was worded by anybody — the first because a price answer of "not available" carries no words, the second because it is refused at the door in an error envelope instead. A null delivery is likewise not a promise that no goods were ever made: a purchase whose charge failed or went unanswered can leave goods the buyer has not paid for, and this document withholds them rather than describing them. Every answer says whether the money behind the purchase was real: a gateway settling against nothing produces every other field here exactly as a real charge would, so a reader taking this for proof of a payment has to read that word first.',
|
|
416
450
|
});
|
|
417
451
|
/**
|
|
418
452
|
* The catalog as an agent reads it.
|
|
@@ -646,6 +680,10 @@ export const ERROR_CODES = Object.freeze([
|
|
|
646
680
|
"payment_already_spent",
|
|
647
681
|
"payment_not_taken",
|
|
648
682
|
"payment_not_verified",
|
|
683
|
+
"wallet_change_not_announced",
|
|
684
|
+
"wallet_change_nobody_to_tell",
|
|
685
|
+
"wallet_change_raced",
|
|
686
|
+
"wallet_change_unconfirmed",
|
|
649
687
|
]);
|
|
650
688
|
/**
|
|
651
689
|
* Every call of the surface, under the name it is known by in both programs.
|
|
@@ -680,7 +718,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
680
718
|
method: "POST",
|
|
681
719
|
path: "/v0/catalog/publish",
|
|
682
720
|
auth: "merchant_key",
|
|
683
|
-
description: "Publishes one product, or says what is wrong with the card. Republishing under the same merchant_item_id is how a card is changed rather than how a second one appears. The catalog identifier comes back beside ok, and from then on it is what an agent, a purchase and a receipt all use. A card that is not published comes back as ok:false under the code card_rejected, never retryable, with every finding named in the error's problems.
|
|
721
|
+
description: "Publishes one product, or says what is wrong with the card. Republishing under the same merchant_item_id is how a card is changed rather than how a second one appears. The catalog identifier comes back beside ok, and from then on it is what an agent, a purchase and a receipt all use. A card that is not published comes back as ok:false under the code card_rejected, never retryable, with every finding named in the error's problems. Three findings this can come back with are not about the card at all. A merchant who has not set the name their products are sold under gets no_seller_name, and the way past it is POST /v0/seller-name: a card published without one reaches a buyer's agent inside a payment request that names no seller. On a deployment that settles on a real chain, a merchant who has set no wallet gets no_payout_wallet, and the way past it is the Settings screen of the merchant's cabinet, where a person signed in sets one: the money from that card's sales is paid to the merchant's own address directly, and without one there is nowhere for it to go. On the live deployment, a merchant the operator has not admitted once gets no_operator_approval. That decision has no merchant API: test publication remains available, while live publication remains closed until the operator grants it. Every applicable finding comes back in the same problems list as whatever is wrong with the card, so one answer carries everything standing between this card and the catalog.",
|
|
684
722
|
request: CardSchema,
|
|
685
723
|
response: { document: PublishResultSchema },
|
|
686
724
|
},
|
|
@@ -723,7 +761,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
723
761
|
method: "POST",
|
|
724
762
|
path: "/v0/merchants",
|
|
725
763
|
auth: "none",
|
|
726
|
-
description: "Makes a merchant and the key whoever registered them will call as them with — both of those or neither. It takes no key because nobody registering has one yet; what stands in the door instead is an invitation code out of the gateway's own configuration, and a gateway with no code configured refuses every registration in the same words a wrong code gets, so this call is not a way of finding out whether registration is open. The key comes back once and is readable nowhere afterwards, and it is a key made for a cabinet: it is in no list of the merchant's keys and is not disabled through them, so no row for it comes back here — only the key itself. What the new merchant does not have is a name: they are listed under nothing until somebody sets one at POST /v0/seller-name, and until then publishing a card is refused, so a cabinet that registers a person and takes them straight to a publish screen has built a dead end. Nothing about an account, an address or a password reaches this call either: those belong to whatever signs a person in, on the other side of it. Unlike every other call on this surface that writes something, a repeat of this one is not safe and there is nothing here that could make it so: two calls make two merchants, and the caller holds a key to only the second. A caller whose connection drops before the answer arrives cannot find out from here whether the first landed — it has no key with which to ask — and the merchant it may have made cannot be swept away afterwards, because a merchant is what every card, order and receipt is owned by.",
|
|
764
|
+
description: "Makes a merchant and the key whoever registered them will call as them with — both of those or neither. This call is not on the public origin: only the cabinet makes it, from inside the stack, when a signed-in person presses its one control, and from outside the path answers as one the site does not have. It takes no key because nobody registering has one yet; what stands in the door instead is an invitation code out of the gateway's own configuration, and a gateway with no code configured refuses every registration in the same words a wrong code gets, so this call is not a way of finding out whether registration is open. The key comes back once and is readable nowhere afterwards, and it is a key made for a cabinet: it is in no list of the merchant's keys and is not disabled through them, so no row for it comes back here — only the key itself. What the new merchant does not have is a name: they are listed under nothing until somebody sets one at POST /v0/seller-name, and until then publishing a card is refused, so a cabinet that registers a person and takes them straight to a publish screen has built a dead end. Nothing about an account, an address or a password reaches this call either: those belong to whatever signs a person in, on the other side of it. Unlike every other call on this surface that writes something, a repeat of this one is not safe and there is nothing here that could make it so: two calls make two merchants, and the caller holds a key to only the second. A caller whose connection drops before the answer arrives cannot find out from here whether the first landed — it has no key with which to ask — and the merchant it may have made cannot be swept away afterwards, because a merchant is what every card, order and receipt is owned by.",
|
|
727
765
|
request: RegistrationRequestSchema,
|
|
728
766
|
response: { document: RegisteredMerchantSchema },
|
|
729
767
|
},
|
|
@@ -746,14 +784,14 @@ export const API_ROUTES = Object.freeze({
|
|
|
746
784
|
method: "GET",
|
|
747
785
|
path: "/v0/payout-wallet",
|
|
748
786
|
auth: "merchant_key",
|
|
749
|
-
description: "The address the sales of the merchant this call's own key belongs to are paid into. Payments here are not held by anybody on the way: a buyer's agent pays this address directly and no balance of the merchant's is ever held on our side, which is why the address has to be theirs and why this call exists. Null is the ordinary answer for a merchant who has set none, and it is an answer rather than a refusal — a merchant with no wallet exists and has a settings screen to draw. The address comes back in the mixed-case spelling a wallet shows, whichever of the two accepted spellings was sent to set it, so a screen showing it shows what the merchant copied out of their wallet character for character.",
|
|
787
|
+
description: "The address the sales of the merchant this call's own key belongs to are paid into now, and any change of it that is waiting. Payments here are not held by anybody on the way: a buyer's agent pays this address directly and no balance of the merchant's is ever held on our side, which is why the address has to be theirs and why this call exists. Any key of the merchant's reads it, the keys made for their own code included; only the merchant's cabinet sets it. Null is the ordinary answer for a merchant who has set none, and it is an answer rather than a refusal — a merchant with no wallet exists and has a settings screen to draw. The address comes back in the mixed-case spelling a wallet shows, whichever of the two accepted spellings was sent to set it, so a screen showing it shows what the merchant copied out of their wallet character for character. On the live deployment a replacement for an address already set takes effect forty-eight hours after it was announced to the merchant, and until then this answers with the address still paid and names the waiting one, with the moment it takes effect, under pending. Null there means nothing is waiting, which is always the answer on the test channel and in a sandbox.",
|
|
750
788
|
response: { document: PayoutWalletSchema },
|
|
751
789
|
},
|
|
752
790
|
set_payout_wallet: {
|
|
753
791
|
method: "POST",
|
|
754
792
|
path: "/v0/payout-wallet",
|
|
755
793
|
auth: "merchant_key",
|
|
756
|
-
description: "Sets the address the sales of the merchant this call's own key belongs to are paid into. The
|
|
794
|
+
description: "Sets the address the sales of the merchant this call's own key belongs to are paid into. Only the merchant's cabinet makes this call, with the key made for it, from inside the stack, when a person sets the wallet on its Settings screen: keys operate the shop, and where the shop's money goes is set through the cabinet. The public origin does not route this call at all, so from outside it is a path the site does not have; at the gateway a key made for the merchant's own code is refused under not_a_cabinet_key, for the first address as for any other, and nothing is written or announced. The first address a merchant sets applies at once; on the live deployment every cabinet account of the merchant is then told of it, and a message that cannot be sent refuses nothing. On the live deployment a different address after that does not: before anything is written, every account that names the merchant is sent a message saying what changes, when, and that it was asked for in the cabinet, and the change takes effect forty-eight hours after those messages were handed to the mail provider. Until then every payment request names the address that applies now, and the answer carries the waiting one under pending with the moment it takes effect. Asking again for the address already waiting changes nothing, sends no second message and restarts no clock, and answers with the same pending change, so a retry after a dropped connection is safe; a different address replaces the waiting one and starts the forty-eight hours again; asking for the address that applies now cancels the waiting change. On the test channel and in a sandbox every change applies at once and no message is sent. The answer is the wallet as it now stands, read back from what was written rather than echoed, in the mixed-case spelling a wallet shows. Setting the address that already applies, with nothing waiting, changes nothing and answers the same way. An address whose capital letters do not agree with the rest of it is refused and nothing is written, because those capitals are a checksum and letters that disagree mean a character is wrong — and an address that is wrong is another perfectly good address belonging to somebody else. What this call will not do is take an address away: null is refused, because without an address there is nowhere to send the money and every published card would quietly come off sale — ending the selling under the name of editing a setting; somebody reaching for that wants either a different address, which is this same call, or an end to selling, which is the pause. On a deployment that settles on a real chain, a merchant with no wallet set here cannot publish a card, and the refusal at the publish says so.",
|
|
757
795
|
request: PayoutWalletRequestSchema,
|
|
758
796
|
response: { document: PayoutWalletSchema },
|
|
759
797
|
},
|
|
@@ -783,14 +821,14 @@ export const API_ROUTES = Object.freeze({
|
|
|
783
821
|
method: "POST",
|
|
784
822
|
path: "/v0/keys/cabinet",
|
|
785
823
|
auth: "merchant_key",
|
|
786
|
-
description: "Makes a key for a cabinet to call as this merchant with, and hands it back once. It is a key of a different kind from the ones at /v0/keys: the merchant did not ask for it, never sees it, and it appears in no list of theirs — so nothing comes back but the key itself. What this is for is a cabinet that replaces its own credential every time somebody signs in, which is what keeps a copy of a cabinet's database from being a set of working keys for long. The call is refused to a key made for the merchant's own code, under not_a_cabinet_key: these two calls are the cabinet's own, and a merchant asking for one would be asking for a credential to a cabinet they are not standing in.",
|
|
824
|
+
description: "Makes a key for a cabinet to call as this merchant with, and hands it back once. This call and the forgetting beside it are not on the public origin: only the cabinet makes them, from inside the stack, and from outside the path answers as one the site does not have. It is a key of a different kind from the ones at /v0/keys: the merchant did not ask for it, never sees it, and it appears in no list of theirs — so nothing comes back but the key itself. What this is for is a cabinet that replaces its own credential every time somebody signs in, which is what keeps a copy of a cabinet's database from being a set of working keys for long. The call is refused to a key made for the merchant's own code, under not_a_cabinet_key: these two calls are the cabinet's own, and a merchant asking for one would be asking for a credential to a cabinet they are not standing in.",
|
|
787
825
|
response: { document: CabinetKeySchema },
|
|
788
826
|
},
|
|
789
827
|
forget_cabinet_key: {
|
|
790
828
|
method: "DELETE",
|
|
791
829
|
path: "/v0/keys/cabinet",
|
|
792
830
|
auth: "merchant_key",
|
|
793
|
-
description: "Removes the key this call was made with, and no other. It is removed rather than revoked: a merchant never issued one, never sees one and would never read a revoked one back, so a row kept for the history would be history for nobody. There are no parameters, and that is not a convenience — a key belonging to anybody else, this merchant included, is unreachable here by construction, because the only way to name a key is to be holding it. What a caller does with this is put a key of its own beyond use once it has stopped signing in with it: ask for a fresh key, write it down where the account is kept, then forget the one that was there. A caller that forgets first can be left naming a key that no longer exists, which is the one order that locks somebody out. Made a second time with the same key it is refused as a key that does not exist, which is safe and is the confirmation the first one landed: either way that key is gone and nothing else has moved. It is refused to a key made for the merchant's own code, under not_a_cabinet_key: those are revoked from the list they appear on, at an instant their owner can read back, and removing the row outright would take that history away.",
|
|
831
|
+
description: "Removes the key this call was made with, and no other. Like the call that makes such a key, it is not on the public origin: only the cabinet makes it, from inside the stack. It is removed rather than revoked: a merchant never issued one, never sees one and would never read a revoked one back, so a row kept for the history would be history for nobody. There are no parameters, and that is not a convenience — a key belonging to anybody else, this merchant included, is unreachable here by construction, because the only way to name a key is to be holding it. What a caller does with this is put a key of its own beyond use once it has stopped signing in with it: ask for a fresh key, write it down where the account is kept, then forget the one that was there. A caller that forgets first can be left naming a key that no longer exists, which is the one order that locks somebody out. Made a second time with the same key it is refused as a key that does not exist, which is safe and is the confirmation the first one landed: either way that key is gone and nothing else has moved. It is refused to a key made for the merchant's own code, under not_a_cabinet_key: those are revoked from the list they appear on, at an instant their owner can read back, and removing the row outright would take that history away.",
|
|
794
832
|
response: { document: ForgottenCabinetKeySchema },
|
|
795
833
|
},
|
|
796
834
|
get_order: {
|
|
@@ -804,7 +842,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
804
842
|
method: "GET",
|
|
805
843
|
path: "/v0/orders",
|
|
806
844
|
auth: "merchant_key",
|
|
807
|
-
description: "Orders and the states they are in. With open=true, only the ones
|
|
845
|
+
description: "Orders and the states they are in. With open=true, only the ones a restarted worker should walk — ones the merchant was handed and has not finished, which includes the two that stay open after the purchase itself is over, an order owing a refund and one delivered but never paid for. An order that was priced and never paid, and never reached the handler, is not in that narrowing; it is readable by its identifier, where its status is the buyer's word for a purchase that has not finished. One kind of order is not in this list at all, with or without the flag: one that closed before anybody named a price for it, because the product was gone or a price question went unanswered. Every row here is written in a document that carries a sale price and those orders have none, so they are readable one at a time by their identifier, where the refusal says what became of them. A merchant reconciling against this list is reconciling against the orders that were priced.",
|
|
808
846
|
query: OrderListQuerySchema,
|
|
809
847
|
response: { document: OrderListSchema },
|
|
810
848
|
},
|
|
@@ -874,7 +912,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
874
912
|
method: "POST",
|
|
875
913
|
path: "/x402/:item_id/purchase",
|
|
876
914
|
auth: "none",
|
|
877
|
-
description: "Buying one product. The payment is what stands in for authorisation, so there is no key on this call. It begins with the payment exchange of the x402 protocol: a call with no payment on it is answered with a challenge, which travels in a header and carries no document. What a paid purchase is answered with is the state of the order it made — the same document the status route answers with, whatever the card's mode and whether the purchase ended in the goods or in something else, so an agent that bought and an agent that came back later read one shape. No receipt of ours is in it: a receipt is the merchant's record of the sale and is read behind the merchant's key. What an agent is told about its own money is the price and the word for whether that money was real, and, where the payment executed as the last step of this exchange, the settlement the payment layer signs into a header on this answer — a card whose money moves as the order is opened has already spent that step, so no settlement comes back here and the two fields are the whole of it. The address answers on GET as well as on POST, because that is how the validators and crawlers that list a paid resource ask for it. An unpaid call that carries no document — a GET, or a POST with nothing or with an empty document — is answered with the challenge and never a purchase, and a GET is never read for payment; the challenge describes the purchase, which is a POST with a JSON body. An unpaid POST that carries that document is answered with the price of the very order it opened, and a document of some other shape is refused with the fields that are wrong. A product that is not on sale answers neither method with a challenge: it is refused, so that a catalog built from these challenges never carries a product nobody can buy.",
|
|
915
|
+
description: "Buying one product. The payment is what stands in for authorisation, so there is no key on this call. It begins with the payment exchange of the x402 protocol: a call with no payment on it is answered with a challenge, which travels in a header and carries no document. What a paid purchase is answered with is the state of the order it made — the same document the status route answers with, whatever the card's mode and whether the purchase ended in the goods or in something else, so an agent that bought and an agent that came back later read one shape. That document names, in status_url, the whole address where the order is read again, which is where goods that come later are collected. No receipt of ours is in it: a receipt is the merchant's record of the sale and is read behind the merchant's key. What an agent is told about its own money is the price and the word for whether that money was real, and, where the payment executed as the last step of this exchange, the settlement the payment layer signs into a header on this answer — a card whose money moves as the order is opened has already spent that step, so no settlement comes back here and the two fields are the whole of it. The address answers on GET as well as on POST, because that is how the validators and crawlers that list a paid resource ask for it. An unpaid call that carries no document — a GET, or a POST with nothing or with an empty document — is answered with the challenge and never a purchase, and a GET is never read for payment; the challenge describes the purchase, which is a POST with a JSON body. An unpaid POST that carries that document is answered with the price of the very order it opened, and a document of some other shape is refused with the fields that are wrong. A product that is not on sale answers neither method with a challenge: it is refused, so that a catalog built from these challenges never carries a product nobody can buy.",
|
|
878
916
|
request: PurchaseRequestSchema,
|
|
879
917
|
also_answers_on: ["GET"],
|
|
880
918
|
response: { document: AgentOrderStatusSchema },
|
|
@@ -883,7 +921,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
883
921
|
method: "GET",
|
|
884
922
|
path: "/x402/orders/:order_id/status",
|
|
885
923
|
auth: "order_id",
|
|
886
|
-
description: "What became of a purchase, for the agent that made it: where the order stands, what it sold for, and the goods once they are the buyer's. It is the route an agent that bought a product whose goods come later collects them on, and without it half a catalogue takes money and hands back an order nobody can act on.
|
|
924
|
+
description: "What became of a purchase, for the agent that made it: where the order stands, what it sold for, and the goods once they are the buyer's. It is the route an agent that bought a product whose goods come later collects them on, and without it half a catalogue takes money and hands back an order nobody can act on. Every answer that carries the order document names this address in status_url, whole and ready to call, the purchase's own answer included. An order whose goods come later is owed them by the delivery deadline its card carried when the order was opened, counted from its payment: fulfill_deadline_seconds where the card names one, and a day where it names none. An order still without goods at that deadline becomes refund_due, and a paid order the merchant refuses or leaves behind becomes it sooner: the merchant owes the buyer the goods or the money back. That is not an ending, and it carries no further deadline. Goods the merchant delivers after it still appear here and settle the debt, and the order becomes delivered. Nor does refund_due say whether the money has come back: the merchant returns it from their own wallet, the gateway has no way yet to record that they did, and until it has one no order moves on to refunded — a buyer already paid back still reads refund_due here. So an agent holding refund_due can still collect goods here, nothing here tells it when to stop asking, and its own wallet is where a refund shows. Knowing the order's identifier is the proof (ADR-0011), so this call takes no key: an agent has no account and no registration, and the identifier is handed to exactly one party. Two things follow for whoever mounts it. Which door a call is behind is read off auth and never off the address, whatever the prefixes happen to agree on today. And an identifier that names no order must be answered exactly as any other unknown one is, or the refusal becomes a way of counting the orders behind it.",
|
|
887
925
|
response: { document: AgentOrderStatusSchema },
|
|
888
926
|
},
|
|
889
927
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -33,8 +33,8 @@ export type { EvmAddress } from "./evm-address.js";
|
|
|
33
33
|
export { checksummedAddressOf, EvmAddressSchema } from "./evm-address.js";
|
|
34
34
|
export type { Acceptance, Delivery, HandlerAnswer, Refusal, RefusalCode } from "./handler.js";
|
|
35
35
|
export { AcceptanceSchema, DeliverySchema, HandlerAnswerSchema, RECOMMENDED_REFUSAL_CODES, RefusalCodeSchema, RefusalSchema, } from "./handler.js";
|
|
36
|
-
export type { CabinetKey, DisabledKey, ForgottenCabinetKey, IssuedKey, IssueKeyRequest, MerchantKey, MerchantKeyList, PayoutWallet, PayoutWalletRequest, RegisteredMerchant, RegistrationRequest, SellerName, SellerNameRequest, } from "./merchant.js";
|
|
37
|
-
export { CabinetKeySchema, DisabledKeySchema, ForgottenCabinetKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, MerchantKeySchema, PayoutWalletRequestSchema, PayoutWalletSchema, RegisteredMerchantSchema, RegistrationRequestSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
36
|
+
export type { CabinetKey, DisabledKey, ForgottenCabinetKey, IssuedKey, IssueKeyRequest, MerchantKey, MerchantKeyList, PayoutWallet, PayoutWalletRequest, PendingPayoutWallet, RegisteredMerchant, RegistrationRequest, SellerName, SellerNameRequest, } from "./merchant.js";
|
|
37
|
+
export { CabinetKeySchema, DisabledKeySchema, ForgottenCabinetKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, MerchantKeySchema, PayoutWalletRequestSchema, PayoutWalletSchema, PendingPayoutWalletSchema, RegisteredMerchantSchema, RegistrationRequestSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
38
38
|
export type { Order } from "./order.js";
|
|
39
39
|
export { OrderSchema } from "./order.js";
|
|
40
40
|
export type { OrderStatus } from "./order-status.js";
|
|
@@ -47,8 +47,8 @@ export type { QuotePurpose, QuoteRequest, QuoteResponse } from "./quote.js";
|
|
|
47
47
|
export { QuotePurposeSchema, QuoteRequestSchema, QuoteResponseSchema } from "./quote.js";
|
|
48
48
|
export type { Receipt, ReceiptOutcome } from "./receipt.js";
|
|
49
49
|
export { ReceiptOutcomeSchema, ReceiptSchema } from "./receipt.js";
|
|
50
|
-
export type { CallError, OrderCallResult, Problem, PublishResult } from "./results.js";
|
|
51
|
-
export { CARD_REJECTED, CallErrorSchema, ORDER_CALL_ERROR_CODES, ORDER_CALL_RESULTS, OrderCallResultSchema, ProblemSchema, PublishResultSchema, } from "./results.js";
|
|
50
|
+
export type { CallError, MerchantFinding, OrderCallResult, Problem, PublishResult, } from "./results.js";
|
|
51
|
+
export { CARD_REJECTED, CallErrorSchema, MERCHANT_FINDINGS, ORDER_CALL_ERROR_CODES, ORDER_CALL_RESULTS, OrderCallResultSchema, ProblemSchema, PublishResultSchema, } from "./results.js";
|
|
52
52
|
export type { SellingState } from "./selling.js";
|
|
53
53
|
export { SELLING_STATES, SellingStateSchema } from "./selling.js";
|
|
54
54
|
/**
|
|
@@ -76,6 +76,7 @@ export declare const schemas: Readonly<{
|
|
|
76
76
|
}, z.core.$strict>;
|
|
77
77
|
agent_order_status: z.ZodObject<{
|
|
78
78
|
order_id: z.ZodString;
|
|
79
|
+
status_url: z.ZodURL;
|
|
79
80
|
status: z.ZodEnum<{
|
|
80
81
|
delivered: "delivered";
|
|
81
82
|
in_progress: "in_progress";
|
|
@@ -615,10 +616,18 @@ export declare const schemas: Readonly<{
|
|
|
615
616
|
}>;
|
|
616
617
|
payout_wallet: z.ZodObject<{
|
|
617
618
|
payout_wallet: z.ZodNullable<z.ZodString>;
|
|
619
|
+
pending: z.ZodNullable<z.ZodObject<{
|
|
620
|
+
payout_wallet: z.ZodString;
|
|
621
|
+
takes_effect_at: z.ZodISODateTime;
|
|
622
|
+
}, z.core.$strict>>;
|
|
618
623
|
}, z.core.$strict>;
|
|
619
624
|
payout_wallet_request: z.ZodObject<{
|
|
620
625
|
payout_wallet: z.ZodPipe<z.ZodString, z.ZodString>;
|
|
621
626
|
}, z.core.$strict>;
|
|
627
|
+
pending_payout_wallet: z.ZodObject<{
|
|
628
|
+
payout_wallet: z.ZodString;
|
|
629
|
+
takes_effect_at: z.ZodISODateTime;
|
|
630
|
+
}, z.core.$strict>;
|
|
622
631
|
price_check: z.ZodUnion<readonly [z.ZodLiteral<"handler">, z.ZodObject<{
|
|
623
632
|
url: z.ZodURL;
|
|
624
633
|
}, z.core.$strict>]>;
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import { WorkerEnvelopeSchema } from "./envelope.js";
|
|
|
27
27
|
import { OrderEventSchema, RefundDueReasonSchema } from "./events.js";
|
|
28
28
|
import { EvmAddressSchema } from "./evm-address.js";
|
|
29
29
|
import { AcceptanceSchema, DeliverySchema, HandlerAnswerSchema, RefusalCodeSchema, RefusalSchema, } from "./handler.js";
|
|
30
|
-
import { CabinetKeySchema, DisabledKeySchema, ForgottenCabinetKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, MerchantKeySchema, PayoutWalletRequestSchema, PayoutWalletSchema, RegisteredMerchantSchema, RegistrationRequestSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
30
|
+
import { CabinetKeySchema, DisabledKeySchema, ForgottenCabinetKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, MerchantKeySchema, PayoutWalletRequestSchema, PayoutWalletSchema, PendingPayoutWalletSchema, RegisteredMerchantSchema, RegistrationRequestSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
31
31
|
import { OrderSchema } from "./order.js";
|
|
32
32
|
import { OrderStatusSchema } from "./order-status.js";
|
|
33
33
|
import { FieldSpecSchema, ParamNameSchema, ParamSpecSchema, ParamTypeSchema, } from "./param-spec.js";
|
|
@@ -42,14 +42,14 @@ export { WORKER_ENVELOPE_KINDS, WORKER_ENVELOPE_PAYLOADS, WorkerEnvelopeSchema,
|
|
|
42
42
|
export { ORDER_EVENT_TYPES, OrderEventSchema, RefundDueReasonSchema } from "./events.js";
|
|
43
43
|
export { checksummedAddressOf, EvmAddressSchema } from "./evm-address.js";
|
|
44
44
|
export { AcceptanceSchema, DeliverySchema, HandlerAnswerSchema, RECOMMENDED_REFUSAL_CODES, RefusalCodeSchema, RefusalSchema, } from "./handler.js";
|
|
45
|
-
export { CabinetKeySchema, DisabledKeySchema, ForgottenCabinetKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, MerchantKeySchema, PayoutWalletRequestSchema, PayoutWalletSchema, RegisteredMerchantSchema, RegistrationRequestSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
45
|
+
export { CabinetKeySchema, DisabledKeySchema, ForgottenCabinetKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, MerchantKeySchema, PayoutWalletRequestSchema, PayoutWalletSchema, PendingPayoutWalletSchema, RegisteredMerchantSchema, RegistrationRequestSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
46
46
|
export { OrderSchema } from "./order.js";
|
|
47
47
|
export { ORDER_STATUSES, OrderStatusSchema } from "./order-status.js";
|
|
48
48
|
export { FieldSpecSchema, ParamNameSchema, ParamSpecSchema, ParamTypeSchema, PROTOTYPE_KEY_IS_DROPPED, paramSpecToValidator, } from "./param-spec.js";
|
|
49
49
|
export { AmountSchema, CurrencyCodeSchema, IdentifierSchema, MoneySchema, SalePriceSchema, TimestampSchema, } from "./primitives.js";
|
|
50
50
|
export { QuotePurposeSchema, QuoteRequestSchema, QuoteResponseSchema } from "./quote.js";
|
|
51
51
|
export { ReceiptOutcomeSchema, ReceiptSchema } from "./receipt.js";
|
|
52
|
-
export { CARD_REJECTED, CallErrorSchema, ORDER_CALL_ERROR_CODES, ORDER_CALL_RESULTS, OrderCallResultSchema, ProblemSchema, PublishResultSchema, } from "./results.js";
|
|
52
|
+
export { CARD_REJECTED, CallErrorSchema, MERCHANT_FINDINGS, ORDER_CALL_ERROR_CODES, ORDER_CALL_RESULTS, OrderCallResultSchema, ProblemSchema, PublishResultSchema, } from "./results.js";
|
|
53
53
|
export { SELLING_STATES, SellingStateSchema } from "./selling.js";
|
|
54
54
|
/**
|
|
55
55
|
* The version of the public contract. It grows when the meaning of the fields
|
|
@@ -109,6 +109,7 @@ export const schemas = Object.freeze({
|
|
|
109
109
|
param_type: ParamTypeSchema,
|
|
110
110
|
payout_wallet: PayoutWalletSchema,
|
|
111
111
|
payout_wallet_request: PayoutWalletRequestSchema,
|
|
112
|
+
pending_payout_wallet: PendingPayoutWalletSchema,
|
|
112
113
|
price_check: PriceCheckSchema,
|
|
113
114
|
problem: ProblemSchema,
|
|
114
115
|
public_card: PublicCardSchema,
|
package/dist/merchant.d.ts
CHANGED
|
@@ -177,6 +177,25 @@ export declare const SellerNameSchema: z.ZodObject<{
|
|
|
177
177
|
export declare const SellerNameRequestSchema: z.ZodObject<{
|
|
178
178
|
seller_name: z.ZodPipe<z.ZodString, z.ZodString>;
|
|
179
179
|
}, z.core.$strict>;
|
|
180
|
+
/**
|
|
181
|
+
* A change of the wallet that has been asked for, announced, and has not taken
|
|
182
|
+
* effect yet.
|
|
183
|
+
*
|
|
184
|
+
* It exists because a replacement does not apply at once where the money is
|
|
185
|
+
* real (ADR-0019). The address a merchant is paid at is the one setting whose
|
|
186
|
+
* change redirects money, and any key of theirs reaches it — the cabinet's, or
|
|
187
|
+
* one sitting in their own server's environment — so on the live deployment a
|
|
188
|
+
* replacement is told to every account of the merchant first and takes effect
|
|
189
|
+
* forty-eight hours after that. What this document says is the two facts a
|
|
190
|
+
* merchant needs in that window: what replaces the address, and from when.
|
|
191
|
+
*
|
|
192
|
+
* Both are required. An address with no moment says nothing about when the
|
|
193
|
+
* money moves, and a moment with no address says it moves without saying where.
|
|
194
|
+
*/
|
|
195
|
+
export declare const PendingPayoutWalletSchema: z.ZodObject<{
|
|
196
|
+
payout_wallet: z.ZodString;
|
|
197
|
+
takes_effect_at: z.ZodISODateTime;
|
|
198
|
+
}, z.core.$strict>;
|
|
180
199
|
/**
|
|
181
200
|
* The wallet a merchant's sales are paid into, as the merchant reads it back.
|
|
182
201
|
*
|
|
@@ -200,9 +219,27 @@ export declare const SellerNameRequestSchema: z.ZodObject<{
|
|
|
200
219
|
* address in lower case they cannot tell it from a different address without
|
|
201
220
|
* comparing character by character. On the one field money is sent to, that
|
|
202
221
|
* glance is the whole of the checking anybody does.
|
|
222
|
+
*
|
|
223
|
+
* `pending` is the change waiting beside it, and it is always present for the
|
|
224
|
+
* same reason `payout_wallet` is: null says nothing is waiting, and an absent
|
|
225
|
+
* field would be a silence. It is the field that keeps a caller from taking its
|
|
226
|
+
* own write for a failure — a merchant who asked for a new address on the live
|
|
227
|
+
* deployment reads the old one back, correctly, for forty-eight hours, and
|
|
228
|
+
* without this they would ask again, or conclude the change was lost.
|
|
229
|
+
*
|
|
230
|
+
* It is carried without moving `CONTRACT_VERSION`, which is the one known
|
|
231
|
+
* exception to the rule that a new required field moves it (ADR-0006 §2): no
|
|
232
|
+
* worker of the SDK reads this route, so the version would stop every
|
|
233
|
+
* installed worker for a field none of them sees. What that costs is that a
|
|
234
|
+
* merchant's own code holding this schema from an older release of this
|
|
235
|
+
* package refuses the answer until the package is upgraded.
|
|
203
236
|
*/
|
|
204
237
|
export declare const PayoutWalletSchema: z.ZodObject<{
|
|
205
238
|
payout_wallet: z.ZodNullable<z.ZodString>;
|
|
239
|
+
pending: z.ZodNullable<z.ZodObject<{
|
|
240
|
+
payout_wallet: z.ZodString;
|
|
241
|
+
takes_effect_at: z.ZodISODateTime;
|
|
242
|
+
}, z.core.$strict>>;
|
|
206
243
|
}, z.core.$strict>;
|
|
207
244
|
/**
|
|
208
245
|
* What a merchant sends to change where their sales are paid.
|
|
@@ -270,6 +307,7 @@ export type SellerName = z.infer<typeof SellerNameSchema>;
|
|
|
270
307
|
export type SellerNameRequest = z.infer<typeof SellerNameRequestSchema>;
|
|
271
308
|
export type PayoutWallet = z.infer<typeof PayoutWalletSchema>;
|
|
272
309
|
export type PayoutWalletRequest = z.infer<typeof PayoutWalletRequestSchema>;
|
|
310
|
+
export type PendingPayoutWallet = z.infer<typeof PendingPayoutWalletSchema>;
|
|
273
311
|
export type MerchantKey = z.infer<typeof MerchantKeySchema>;
|
|
274
312
|
export type MerchantKeyList = z.infer<typeof MerchantKeyListSchema>;
|
|
275
313
|
export type IssueKeyRequest = z.infer<typeof IssueKeyRequestSchema>;
|
package/dist/merchant.js
CHANGED
|
@@ -51,6 +51,33 @@ import { IdentifierSchema, TimestampSchema } from "./primitives.js";
|
|
|
51
51
|
const KeyLabelSchema = z
|
|
52
52
|
.string()
|
|
53
53
|
.regex(/^\S(?:[\s\S]*\S)?$/u, "a label must not be empty or padded with spaces");
|
|
54
|
+
/**
|
|
55
|
+
* The longest label a key is issued with.
|
|
56
|
+
*
|
|
57
|
+
* A label used to have no bound, on the argument that no channel outside us
|
|
58
|
+
* carries it. One does now: on the live deployment the message that tells a
|
|
59
|
+
* merchant of a new key, or of a wallet change made with one, names the key
|
|
60
|
+
* by its label (ADR-0019), and that message is Agentify's words in somebody's
|
|
61
|
+
* inbox. A hundred characters is a line on a list and in a message, and
|
|
62
|
+
* longer than any name a person gives a worker.
|
|
63
|
+
*/
|
|
64
|
+
const LONGEST_KEY_LABEL = 100;
|
|
65
|
+
/**
|
|
66
|
+
* A label as a new key is issued with it: the rule above, on one line, and no
|
|
67
|
+
* longer than {@link LONGEST_KEY_LABEL}.
|
|
68
|
+
*
|
|
69
|
+
* Only the request carries the bound. The keys a merchant already holds are
|
|
70
|
+
* read back under whatever they were named, including a key issued at the
|
|
71
|
+
* server's terminal, because refusing the list over one old row would hide
|
|
72
|
+
* every key on it; the message that names such a key cuts it to one line of
|
|
73
|
+
* the same length itself.
|
|
74
|
+
*/
|
|
75
|
+
const IssuedKeyLabelSchema = KeyLabelSchema.max(LONGEST_KEY_LABEL, `a label is at most ${LONGEST_KEY_LABEL} characters, the one line a key is known by`).regex(
|
|
76
|
+
// Written as code-point ranges rather than a Unicode property, because this
|
|
77
|
+
// pattern is published in the JSON Schema a validator in another language
|
|
78
|
+
// reads, and not every one of those knows the property escapes.
|
|
79
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: control characters are what it refuses
|
|
80
|
+
/^[^\u0000-\u001F\u007F-\u009F\u2028\u2029]*$/u, "a label is one line: it cannot carry a line break, a tab or another control character");
|
|
54
81
|
/**
|
|
55
82
|
* The key itself, in the only form its owner will ever see it.
|
|
56
83
|
*
|
|
@@ -164,10 +191,10 @@ export const MerchantKeyListSchema = z
|
|
|
164
191
|
/** What a merchant sends to have a key made. */
|
|
165
192
|
export const IssueKeyRequestSchema = z
|
|
166
193
|
.strictObject({
|
|
167
|
-
label:
|
|
194
|
+
label: IssuedKeyLabelSchema,
|
|
168
195
|
})
|
|
169
196
|
.meta({
|
|
170
|
-
description: "What a merchant asks for when they want another key: the name they will know it by, and nothing else. There is nowhere here to put a secret, because a key is generated rather than chosen — one somebody picks is one somebody reuses somewhere else.",
|
|
197
|
+
description: "What a merchant asks for when they want another key: the name they will know it by, and nothing else. The name is one line of at most 100 characters, not empty and not padded with spaces; on the live deployment it is also how the message telling the merchant of the new key names it. There is nowhere here to put a secret, because a key is generated rather than chosen — one somebody picks is one somebody reuses somewhere else.",
|
|
171
198
|
});
|
|
172
199
|
/**
|
|
173
200
|
* A key that has just been made: the row, and the secret, once.
|
|
@@ -306,6 +333,31 @@ export const SellerNameRequestSchema = z
|
|
|
306
333
|
.meta({
|
|
307
334
|
description: "What a merchant sends to change the name their products are sold under. The same rule as the answer — at most 32 characters of printable ASCII, the catalog's rule rather than ours — and one difference: null is refused. A merchant goes from no name to a name and from one name to another, never back to none, because a payment request names the seller and there would be nobody to name: every card they have published would come off sale, which is an end to their selling arriving under the name of editing a setting. Somebody reaching for null wants one of two other things: a different name, which is this call with a different value, or an end to selling, which is the pause.",
|
|
308
335
|
});
|
|
336
|
+
/**
|
|
337
|
+
* A change of the wallet that has been asked for, announced, and has not taken
|
|
338
|
+
* effect yet.
|
|
339
|
+
*
|
|
340
|
+
* It exists because a replacement does not apply at once where the money is
|
|
341
|
+
* real (ADR-0019). The address a merchant is paid at is the one setting whose
|
|
342
|
+
* change redirects money, and any key of theirs reaches it — the cabinet's, or
|
|
343
|
+
* one sitting in their own server's environment — so on the live deployment a
|
|
344
|
+
* replacement is told to every account of the merchant first and takes effect
|
|
345
|
+
* forty-eight hours after that. What this document says is the two facts a
|
|
346
|
+
* merchant needs in that window: what replaces the address, and from when.
|
|
347
|
+
*
|
|
348
|
+
* Both are required. An address with no moment says nothing about when the
|
|
349
|
+
* money moves, and a moment with no address says it moves without saying where.
|
|
350
|
+
*/
|
|
351
|
+
export const PendingPayoutWalletSchema = z
|
|
352
|
+
.strictObject({
|
|
353
|
+
/** The address the merchant will be paid at once the wait is over. */
|
|
354
|
+
payout_wallet: EvmAddressSchema,
|
|
355
|
+
/** The moment it replaces the address paid now. */
|
|
356
|
+
takes_effect_at: TimestampSchema,
|
|
357
|
+
})
|
|
358
|
+
.meta({
|
|
359
|
+
description: "A replacement wallet that has been asked for and announced and has not taken effect yet. payout_wallet is the address sales will be paid into from takes_effect_at on, in the mixed-case spelling a wallet shows; until that moment every payment request still names the address paid now. The change takes effect then only if it is still the one waiting: asking for the address paid now cancels it, and asking for a different address replaces it and starts the wait again.",
|
|
360
|
+
});
|
|
309
361
|
/**
|
|
310
362
|
* The wallet a merchant's sales are paid into, as the merchant reads it back.
|
|
311
363
|
*
|
|
@@ -329,14 +381,30 @@ export const SellerNameRequestSchema = z
|
|
|
329
381
|
* address in lower case they cannot tell it from a different address without
|
|
330
382
|
* comparing character by character. On the one field money is sent to, that
|
|
331
383
|
* glance is the whole of the checking anybody does.
|
|
384
|
+
*
|
|
385
|
+
* `pending` is the change waiting beside it, and it is always present for the
|
|
386
|
+
* same reason `payout_wallet` is: null says nothing is waiting, and an absent
|
|
387
|
+
* field would be a silence. It is the field that keeps a caller from taking its
|
|
388
|
+
* own write for a failure — a merchant who asked for a new address on the live
|
|
389
|
+
* deployment reads the old one back, correctly, for forty-eight hours, and
|
|
390
|
+
* without this they would ask again, or conclude the change was lost.
|
|
391
|
+
*
|
|
392
|
+
* It is carried without moving `CONTRACT_VERSION`, which is the one known
|
|
393
|
+
* exception to the rule that a new required field moves it (ADR-0006 §2): no
|
|
394
|
+
* worker of the SDK reads this route, so the version would stop every
|
|
395
|
+
* installed worker for a field none of them sees. What that costs is that a
|
|
396
|
+
* merchant's own code holding this schema from an older release of this
|
|
397
|
+
* package refuses the answer until the package is upgraded.
|
|
332
398
|
*/
|
|
333
399
|
export const PayoutWalletSchema = z
|
|
334
400
|
.strictObject({
|
|
335
|
-
/** Where this merchant's sales are paid, or nothing at all. */
|
|
401
|
+
/** Where this merchant's sales are paid now, or nothing at all. */
|
|
336
402
|
payout_wallet: EvmAddressSchema.nullable(),
|
|
403
|
+
/** A replacement that has been announced and is waiting, or nothing. */
|
|
404
|
+
pending: PendingPayoutWalletSchema.nullable(),
|
|
337
405
|
})
|
|
338
406
|
.meta({
|
|
339
|
-
description: "The address a merchant's sales are paid into. Payments are not held by anybody on the way: a buyer's agent pays
|
|
407
|
+
description: "The address a merchant's sales are paid into, and any change of it that is waiting. Payments are not held by anybody on the way: a buyer's agent pays payout_wallet directly, and it is the payTo of every payment request made for this merchant's products now. Null means nobody has set one, which is where every merchant starts; the field is always present rather than left out, because an absent field is indistinguishable from a client that dropped it. The address comes back in the mixed-case spelling a wallet shows, whichever of the two accepted spellings was sent — so what a merchant reads back on a screen is character for character what they copied out of their wallet. On a deployment that settles on a real chain a merchant with no wallet here cannot publish a card, because the money from that card's sales would have nowhere to go. pending is a replacement that has been asked for and has not taken effect: on the live deployment a merchant who already has a wallet and asks for a different one is told of it by message, and the new address takes effect forty-eight hours later, so until takes_effect_at this answer names the address still paid and the waiting one beside it. A caller reading its old address back beside a pending change has not failed to write; the change is waiting. Null means nothing is waiting, which is every answer on the test channel and in a sandbox, where a change applies at once.",
|
|
340
408
|
});
|
|
341
409
|
/**
|
|
342
410
|
* What a merchant sends to change where their sales are paid.
|
package/dist/order-status.js
CHANGED
|
@@ -68,8 +68,10 @@ export const ORDER_STATUSES = Object.freeze([
|
|
|
68
68
|
*/
|
|
69
69
|
"rejected",
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
71
|
+
* Nobody can say whether the buyer was charged: the payment network was
|
|
72
|
+
* asked and never answered. The order may still be open — the goods may
|
|
73
|
+
* already be made — and a later read can still move. Closed is not what
|
|
74
|
+
* this word says.
|
|
73
75
|
*
|
|
74
76
|
* Deliberately not `rejected`, and this is the fifth gate in one value. An
|
|
75
77
|
* agent told its purchase did not happen goes and buys the same thing
|
|
@@ -88,7 +90,18 @@ export const ORDER_STATUSES = Object.freeze([
|
|
|
88
90
|
"expired",
|
|
89
91
|
/** The merchant left, and orders still open closed with them. */
|
|
90
92
|
"cancelled",
|
|
91
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* The money moved and the goods have not come: the merchant owes the buyer
|
|
95
|
+
* the goods or the money back. Not an ending, and it carries no deadline of
|
|
96
|
+
* its own. Goods the merchant delivers after it still reach the buyer, settle
|
|
97
|
+
* the debt and make the order `delivered`.
|
|
98
|
+
*
|
|
99
|
+
* What it cannot say is whether the money has already gone back. The
|
|
100
|
+
* merchant pays a refund from their own wallet and the gateway has no way yet
|
|
101
|
+
* to record that they did, so until it has one nothing moves an order on to
|
|
102
|
+
* `refunded`, and a buyer the merchant has already paid back still reads
|
|
103
|
+
* this word.
|
|
104
|
+
*/
|
|
92
105
|
"refund_due",
|
|
93
106
|
/** That debt has since been paid back to the buyer. */
|
|
94
107
|
"refunded",
|
package/dist/results.d.ts
CHANGED
|
@@ -194,6 +194,30 @@ export declare const CallErrorSchema: z.ZodObject<{
|
|
|
194
194
|
* writes the branch that reads it.
|
|
195
195
|
*/
|
|
196
196
|
export declare const CARD_REJECTED = "card_rejected";
|
|
197
|
+
/**
|
|
198
|
+
* The findings of a refused publish that are about the merchant rather than
|
|
199
|
+
* the card.
|
|
200
|
+
*
|
|
201
|
+
* Each arrives in the refusal's `problems` with an empty path, beside whatever
|
|
202
|
+
* is wrong with the card, and none of them is cleared by editing the card: the
|
|
203
|
+
* merchant has no name set for buyers to read, no wallet set for their sales to
|
|
204
|
+
* be paid into, or no approval from the operator for the live catalog. The
|
|
205
|
+
* name is set with a call of the merchant's own (`POST /v0/seller-name`) or in
|
|
206
|
+
* the cabinet; the wallet in the cabinet's Settings alone, since no key of the
|
|
207
|
+
* merchant's code may say where the money goes; and the approval is the
|
|
208
|
+
* operator's decision, with no call. The name is asked for everywhere, the
|
|
209
|
+
* wallet wherever a payment settles and the approval on the live deployment
|
|
210
|
+
* alone, as the publish route's description says; a program needs no copy of
|
|
211
|
+
* that rule, because it learns what is missing where it is refused, at the
|
|
212
|
+
* publish.
|
|
213
|
+
*/
|
|
214
|
+
export declare const MERCHANT_FINDINGS: Readonly<{
|
|
215
|
+
readonly NO_SELLER_NAME: "no_seller_name";
|
|
216
|
+
readonly NO_PAYOUT_WALLET: "no_payout_wallet";
|
|
217
|
+
readonly NO_OPERATOR_APPROVAL: "no_operator_approval";
|
|
218
|
+
}>;
|
|
219
|
+
/** One of the findings about the merchant, as its code travels on the wire. */
|
|
220
|
+
export type MerchantFinding = (typeof MERCHANT_FINDINGS)[keyof typeof MERCHANT_FINDINGS];
|
|
197
221
|
/**
|
|
198
222
|
* The answer to publishing a card: the catalog id, or what stands in its way.
|
|
199
223
|
*
|
package/dist/results.js
CHANGED
|
@@ -161,18 +161,27 @@ export const ProblemSchema = z
|
|
|
161
161
|
* value, and it covers two kinds of finding that a merchant tells apart by
|
|
162
162
|
* the words rather than by the shape: one about the whole of what was
|
|
163
163
|
* sent, and one about the merchant sending it — their having set no name
|
|
164
|
-
* for buyers to read,
|
|
164
|
+
* for buyers to read, no wallet for their sales to be paid into, or no
|
|
165
|
+
* operator approval for the live catalogue.
|
|
165
166
|
* Leaving the field out entirely would make an empty path
|
|
166
167
|
* indistinguishable from a path nobody filled in.
|
|
167
168
|
*/
|
|
168
169
|
path: z.array(z.string()),
|
|
169
|
-
/**
|
|
170
|
-
|
|
170
|
+
/**
|
|
171
|
+
* What kind of finding it is, for the code that reads it.
|
|
172
|
+
*
|
|
173
|
+
* Open, because a finding about a field carries whatever the check that
|
|
174
|
+
* found it calls it. The three about the merchant are promised, and they
|
|
175
|
+
* are described for the export for the reason the error's codes are.
|
|
176
|
+
*/
|
|
177
|
+
code: z.string().regex(/\S/, "a finding carries a code").meta({
|
|
178
|
+
description: 'What kind of finding it is, for the program that reads it. The set is open: a finding about a field of what was sent carries the name the check gave it. Three are promised, always with an empty path, and each says the merchant rather than the card is missing something, so no edit to the card clears it: "no_seller_name" (no name set for buyers to read), "no_payout_wallet" (no wallet set for the sales to be paid into, asked for wherever a payment settles) and "no_operator_approval" (the operator has not admitted this merchant to the live catalog, which only the operator can change).',
|
|
179
|
+
}),
|
|
171
180
|
/** The same finding in words, for the person who has to fix the card. */
|
|
172
181
|
message: z.string().regex(/\S/, "a finding carries an explanation a person can read"),
|
|
173
182
|
})
|
|
174
183
|
.meta({
|
|
175
|
-
description: 'One thing wrong with what was sent: where it is, a code for the program that reads it, and the same finding in words for the person who has to fix it. The path names the field, innermost last — ["params", "email", "type"] — and an empty path is a statement rather than a missing value: the finding is about the whole of what was sent, or about the sender — a merchant with no name set for buyers,
|
|
184
|
+
description: 'One thing wrong with what was sent: where it is, a code for the program that reads it, and the same finding in words for the person who has to fix it. The path names the field, innermost last — ["params", "email", "type"] — and an empty path is a statement rather than a missing value: the finding is about the whole of what was sent, or about the sender — a merchant with no name set for buyers, no wallet set for their sales to be paid into, or no operator approval for the live catalogue is refused with an empty path too — and not about any one field, which is also what a document that could not be read at all produces. The field is always present for that reason, because an absent path and an empty one would be indistinguishable. Findings never travel alone: they arrive as the problems list inside the error of a call that refused what it was handed — a card that was not published, a delivery that is not what its card declares, a body or a set of purchase parameters that did not fit.',
|
|
176
185
|
});
|
|
177
186
|
/**
|
|
178
187
|
* Why a call did not go through: a code to branch on, a sentence to print, and
|
|
@@ -202,7 +211,7 @@ export const CallErrorSchema = z.strictObject({
|
|
|
202
211
|
code: z.string().regex(/\S/, "an error carries a code").meta({
|
|
203
212
|
// Same reason as the refusal code: the dictionary travels with the field
|
|
204
213
|
// or it does not reach the reader the export exists for.
|
|
205
|
-
description: 'Why the call did not go through. The set is open, and five are promised to mean one thing each — but not on the same calls, and which call a code can arrive on is part of what is promised about it. Publishing a card is refused with one word and no other: "card_rejected" (the card was not published, and every finding standing between it and the catalog is named in the error\'s problems — the fields at fault, and the merchant\'s own missing name
|
|
214
|
+
description: 'Why the call did not go through. The set is open, and five are promised to mean one thing each — but not on the same calls, and which call a code can arrive on is part of what is promised about it. Publishing a card is refused with one word and no other: "card_rejected" (the card was not published, and every finding standing between it and the catalog is named in the error\'s problems — the fields at fault, and the merchant\'s own missing name, payout wallet or live operator approval where those are what is missing; it is never retryable, because the same card gets the same answer and what changes the outcome is fixing what the problems name). The calls that close an order — delivering, refusing, taking one on — are refused with the other four, and never with the first: "refund_already_settled" (the debt was paid back, so there is nothing left to deliver against). "order_already_closed" (the order reached an ending that no call reopens). "not_applicable_in_mode" (the call does not exist for this card\'s mode — refusing separately does not, in the synchronous one, where the handler\'s own answer is the refusal). "delivery_does_not_match_card" (the goods are not the ones the card for this order declares it delivers — nothing was written down, the problems name the fields that did not fit, and the message says whether the order still stands or has already ended). The last of those is retryable in a different sense from a lost connection: the call arrived and was understood, so sending the same goods again gives the same refusal, and what clears it is delivering what the card declares. It is not retryable at all where the order has already ended, because there is nothing left to deliver against.',
|
|
206
215
|
}),
|
|
207
216
|
message: z.string().regex(/\S/, "an error carries an explanation a person can read"),
|
|
208
217
|
retryable: z.boolean(),
|
|
@@ -218,7 +227,7 @@ export const CallErrorSchema = z.strictObject({
|
|
|
218
227
|
* is the field the whole shape is named after.
|
|
219
228
|
*/
|
|
220
229
|
problems: z.array(ProblemSchema).min(1).optional().meta({
|
|
221
|
-
description:
|
|
230
|
+
description: "What was wrong with what was sent, one finding at a time: where it is, a code for the program that reads it, and the same finding in words. Present where the call is refusing what it was handed — a card that was not published, a delivery that is not what its card declares — and absent where the refusal is about a state of the world instead: a refund already settled is about the order, not about a field of the request. Never empty where it is present, and a refused publish always carries it. This field is the complete account of what stands in the way, and it is the one to read the findings from. The error's \"message\" is a single line written to be read in a log and does not carry the list. Where what stands in the way is the merchant's own — no seller name, no payout wallet, no operator approval — the message names each of those plainly; for the rest it says how many findings there are, quotes one of them, and marks the place where a long one was cut — so a reader can always tell a short refusal from a shortened account of a long one.",
|
|
222
231
|
}),
|
|
223
232
|
});
|
|
224
233
|
/**
|
|
@@ -229,6 +238,28 @@ export const CallErrorSchema = z.strictObject({
|
|
|
229
238
|
* writes the branch that reads it.
|
|
230
239
|
*/
|
|
231
240
|
export const CARD_REJECTED = "card_rejected";
|
|
241
|
+
/**
|
|
242
|
+
* The findings of a refused publish that are about the merchant rather than
|
|
243
|
+
* the card.
|
|
244
|
+
*
|
|
245
|
+
* Each arrives in the refusal's `problems` with an empty path, beside whatever
|
|
246
|
+
* is wrong with the card, and none of them is cleared by editing the card: the
|
|
247
|
+
* merchant has no name set for buyers to read, no wallet set for their sales to
|
|
248
|
+
* be paid into, or no approval from the operator for the live catalog. The
|
|
249
|
+
* name is set with a call of the merchant's own (`POST /v0/seller-name`) or in
|
|
250
|
+
* the cabinet; the wallet in the cabinet's Settings alone, since no key of the
|
|
251
|
+
* merchant's code may say where the money goes; and the approval is the
|
|
252
|
+
* operator's decision, with no call. The name is asked for everywhere, the
|
|
253
|
+
* wallet wherever a payment settles and the approval on the live deployment
|
|
254
|
+
* alone, as the publish route's description says; a program needs no copy of
|
|
255
|
+
* that rule, because it learns what is missing where it is refused, at the
|
|
256
|
+
* publish.
|
|
257
|
+
*/
|
|
258
|
+
export const MERCHANT_FINDINGS = Object.freeze({
|
|
259
|
+
NO_SELLER_NAME: "no_seller_name",
|
|
260
|
+
NO_PAYOUT_WALLET: "no_payout_wallet",
|
|
261
|
+
NO_OPERATOR_APPROVAL: "no_operator_approval",
|
|
262
|
+
});
|
|
232
263
|
/**
|
|
233
264
|
* The error a refused publish carries: the shared shape, with the findings made
|
|
234
265
|
* required.
|
|
@@ -236,11 +267,10 @@ export const CARD_REJECTED = "card_rejected";
|
|
|
236
267
|
* "Refused, and here is nothing" is the one answer a merchant cannot act on,
|
|
237
268
|
* and publishing is the call where that would be easiest to send — a card is
|
|
238
269
|
* refused precisely because something about it is wrong, so there is always
|
|
239
|
-
* something to name. Not every finding is about the card
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* than handing it over one round trip at a time.
|
|
270
|
+
* something to name. Not every finding is about the card: the merchant's own
|
|
271
|
+
* missing settings (`MERCHANT_FINDINGS`) ride in the same list, so one answer
|
|
272
|
+
* carries everything standing between this card and the catalog rather than
|
|
273
|
+
* handing it over one round trip at a time.
|
|
244
274
|
*/
|
|
245
275
|
const PublishRefusalSchema = CallErrorSchema.extend({
|
|
246
276
|
problems: z.array(ProblemSchema).min(1),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuanu-ai/agentify-contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The Agentify wire contract as code: the schemas for cards, orders, price checks and receipts that the gateway and the merchant SDK both read.",
|
|
6
6
|
"keywords": [
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"zod-schemas",
|
|
10
10
|
"json-schema"
|
|
11
11
|
],
|
|
12
|
-
"homepage": "https://
|
|
12
|
+
"homepage": "https://agentify.ad/docs/",
|
|
13
13
|
"license": "Apache-2.0",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|