@nuanu-ai/agentify-contracts 0.7.0 → 0.8.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/dist/api.d.ts +208 -118
- package/dist/api.js +56 -60
- package/dist/card.d.ts +28 -34
- package/dist/card.js +163 -53
- package/dist/envelope.d.ts +46 -0
- package/dist/index.d.ts +194 -27
- package/dist/index.js +15 -9
- package/dist/merchant.d.ts +17 -118
- package/dist/merchant.js +21 -174
- package/dist/order-status.d.ts +2 -1
- package/dist/order-status.js +13 -1
- package/dist/order.d.ts +17 -0
- package/dist/order.js +13 -0
- package/dist/quote.d.ts +6 -0
- package/dist/quote.js +10 -0
- package/dist/receipt.d.ts +8 -5
- package/dist/receipt.js +13 -6
- package/dist/results.d.ts +14 -6
- package/dist/results.js +16 -7
- package/dist/seller-site.d.ts +30 -0
- package/dist/seller-site.js +43 -0
- package/dist/ship-to.d.ts +50 -0
- package/dist/ship-to.js +76 -0
- package/dist/shipment.d.ts +42 -0
- package/dist/shipment.js +112 -0
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -42,23 +42,23 @@
|
|
|
42
42
|
* later by a merchant who took an order on and now has the goods or has run
|
|
43
43
|
* out of them. The order machine keeps the same two apart, and in the
|
|
44
44
|
* synchronous mode it is the returned answer that exists and the explicit
|
|
45
|
-
* calls that do not.
|
|
46
|
-
* of that decision, read alone, leaves the synchronous handler with no address
|
|
47
|
-
* at all.
|
|
45
|
+
* calls that do not. ADR-0004 §2 settles this.
|
|
48
46
|
*/
|
|
49
47
|
import { z } from "zod";
|
|
50
48
|
import { CardSchema, FulfillmentSchema, MerchantCardSchema, PublicCardSchema, SellerSchema, } from "./card.js";
|
|
51
49
|
import { WorkerEnvelopeSchema } from "./envelope.js";
|
|
52
50
|
import { AcceptanceSchema, DeliverySchema, HandlerAnswerSchema, RefusalSchema } from "./handler.js";
|
|
53
|
-
import {
|
|
51
|
+
import { DisabledKeySchema, IssuedKeySchema, IssueKeyRequestSchema, MerchantKeyListSchema, PayoutWalletSchema, SellerNameRequestSchema, SellerNameSchema, } from "./merchant.js";
|
|
54
52
|
import { OrderSchema } from "./order.js";
|
|
55
53
|
import { OrderStatusSchema } from "./order-status.js";
|
|
56
54
|
import { ParamNameSchema } from "./param-spec.js";
|
|
57
|
-
import { IdentifierSchema, OpenWordSchema, SalePriceSchema } from "./primitives.js";
|
|
55
|
+
import { IdentifierSchema, OpenWordSchema, SalePriceSchema, TimestampSchema, } from "./primitives.js";
|
|
58
56
|
import { QuoteResponseSchema } from "./quote.js";
|
|
59
57
|
import { ReceiptSchema } from "./receipt.js";
|
|
60
58
|
import { CallErrorSchema, OrderCallResultSchema, PublishResultSchema } from "./results.js";
|
|
61
59
|
import { SellingStateSchema } from "./selling.js";
|
|
60
|
+
import { ShipToSchema } from "./ship-to.js";
|
|
61
|
+
import { RecordedShipmentSchema } from "./shipment.js";
|
|
62
62
|
/**
|
|
63
63
|
* An order together with the word for where it stands.
|
|
64
64
|
*
|
|
@@ -304,9 +304,17 @@ export const PurchaseRequestSchema = z
|
|
|
304
304
|
// The same dropped key as everywhere this contract parses free-form names;
|
|
305
305
|
// see `PROTOTYPE_KEY_IS_DROPPED` in `param-spec.ts`.
|
|
306
306
|
params: z.record(ParamNameSchema, z.unknown()),
|
|
307
|
+
/**
|
|
308
|
+
* Where a parcel goes (ADR-0032). Required on the purchase of a card whose
|
|
309
|
+
* fulfillment is "ship", and refused on any other: only a parcel needs an
|
|
310
|
+
* address, and one sent with anything else would be a buyer's details
|
|
311
|
+
* handed over for nothing. Sent again with the payment it must be the one
|
|
312
|
+
* that was priced, or be left out.
|
|
313
|
+
*/
|
|
314
|
+
ship_to: ShipToSchema.optional(),
|
|
307
315
|
})
|
|
308
316
|
.meta({
|
|
309
|
-
description: "What an agent supplies to buy: the purchase parameters, empty for a product that needs none. The names are held to the shape a card could have declared and no further — that these values fit this card is checked against that card at the moment of purchase.",
|
|
317
|
+
description: "What an agent supplies to buy: the purchase parameters, empty for a product that needs none, and for a parcel the address it goes to. The names are held to the shape a card could have declared and no further — that these values fit this card is checked against that card at the moment of purchase. ship_to is required when the card's fulfillment is \"ship\" and refused on any other card. The merchant's price question receives only its locality; the merchant receives the whole address once the order is paid. Sent again with the payment it must be the same address, or be left out, in which case the payment is for the address that was priced; a different one is refused before the payment is checked, and is a new purchase. That holds while Agentify still holds the address: once it has let go of it — the order taken on, ended, or owing a refund without being taken on — there is nothing to compare with, a payment's ship_to is checked for its shape only, and the answer is the order as it stands.",
|
|
310
318
|
});
|
|
311
319
|
/**
|
|
312
320
|
* What became of a purchase, told to the agent that made it.
|
|
@@ -344,6 +352,15 @@ export const PurchaseRequestSchema = z
|
|
|
344
352
|
* payment that failed its check both still arrive as a bare `rejected`,
|
|
345
353
|
* because neither was worded by anybody.
|
|
346
354
|
*/
|
|
355
|
+
/**
|
|
356
|
+
* A shipment's expected window as an agent reads it: open, as the shipment
|
|
357
|
+
* around it is, so a field added to the window later is ignored by an agent
|
|
358
|
+
* built before it rather than making the whole status unreadable (ADR-0006
|
|
359
|
+
* §5). Opening it makes a new schema, which carries none of the old one's
|
|
360
|
+
* description, so the description is carried across.
|
|
361
|
+
*/
|
|
362
|
+
const closedWindow = RecordedShipmentSchema.shape.estimated_delivery.unwrap();
|
|
363
|
+
const openWindow = closedWindow.loose().meta(closedWindow.meta() ?? {});
|
|
347
364
|
export const AgentOrderStatusSchema = z
|
|
348
365
|
.looseObject({
|
|
349
366
|
order_id: IdentifierSchema,
|
|
@@ -415,12 +432,33 @@ export const AgentOrderStatusSchema = z
|
|
|
415
432
|
* says null for exactly as long as that is true.
|
|
416
433
|
*/
|
|
417
434
|
delivered: DeliverySchema.nullable(),
|
|
435
|
+
/**
|
|
436
|
+
* A parcel's shipment once its merchant has recorded it, and null until
|
|
437
|
+
* then (ADR-0033). Present on a parcel's order and on no other.
|
|
438
|
+
*
|
|
439
|
+
* It is beside `delivered` rather than in it because nothing reached the
|
|
440
|
+
* agent: what the merchant handed a carrier is not goods in hand, and
|
|
441
|
+
* `delivered` stays null on a parcel for that reason. It is the last thing
|
|
442
|
+
* Agentify knows about the parcel.
|
|
443
|
+
*/
|
|
444
|
+
shipment: RecordedShipmentSchema.extend({ estimated_delivery: openWindow.optional() })
|
|
445
|
+
.loose()
|
|
446
|
+
.nullable()
|
|
447
|
+
.optional(),
|
|
448
|
+
/**
|
|
449
|
+
* When a parcel has to be with its carrier by, as an absolute instant: the
|
|
450
|
+
* card's time to ship counted from the charge, and null until the order is
|
|
451
|
+
* paid (ADR-0033). Present on a parcel's order and on no other. A parcel
|
|
452
|
+
* not shipped by then leaves its merchant owing a refund, which this
|
|
453
|
+
* document then says.
|
|
454
|
+
*/
|
|
455
|
+
ship_by: TimestampSchema.nullable().optional(),
|
|
418
456
|
/**
|
|
419
457
|
* Whether the money behind this purchase was real.
|
|
420
458
|
*
|
|
421
459
|
* The receipt a merchant reads carries this word already, and the buyer's
|
|
422
460
|
* own view of the same purchase is the one place it matters more: a
|
|
423
|
-
* sandbox settles against nothing (ADR-
|
|
461
|
+
* sandbox settles against nothing (ADR-0020) and every other field here
|
|
424
462
|
* reads exactly as it would after a real charge. Without it, this document
|
|
425
463
|
* is indistinguishable from proof of a purchase that moved money, which is
|
|
426
464
|
* the one thing it must never be mistaken for.
|
|
@@ -466,7 +504,7 @@ export const AgentOrderStatusSchema = z
|
|
|
466
504
|
seller: SellerSchema.loose(),
|
|
467
505
|
})
|
|
468
506
|
.meta({
|
|
469
|
-
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 account, 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. "seller" is who sold it, as the merchant gave it and as the catalog shows it beside their cards: the name and the site of their shop, which Agentify did not check, and the site is where to take what this document cannot answer. "status" is a word whose known values are listed beside it, and more may be added: a word a reader does not know is not an ending it knows, so it asks again later and does not buy again on its strength. This document and every part inside it may also gain fields; a reader ignores the ones it does not know.',
|
|
507
|
+
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 account, 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. A parcel\'s order also carries "shipment", its merchant\'s record of handing it to a carrier and null until then, and "ship_by", the instant it has to be with a carrier by and null until it is paid; no other order carries either. On a parcel "delivered" stays null, because nothing reached the agent: its status reads "shipped" once the shipment is recorded, and that is the last word Agentify has about it. "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. "seller" is who sold it, as the merchant gave it and as the catalog shows it beside their cards: the name and the site of their shop, which Agentify did not check, and the site is where to take what this document cannot answer. "status" is a word whose known values are listed beside it, and more may be added: a word a reader does not know is not an ending it knows, so it asks again later and does not buy again on its strength. This document and every part inside it may also gain fields; a reader ignores the ones it does not know.',
|
|
470
508
|
});
|
|
471
509
|
/**
|
|
472
510
|
* The catalog as an agent reads it.
|
|
@@ -508,15 +546,8 @@ export const cardsOf = (page) => page.items.flatMap((item) => {
|
|
|
508
546
|
const mode = FulfillmentSchema.safeParse(read.data.fulfillment);
|
|
509
547
|
return mode.success ? [{ ...read.data, fulfillment: mode.data }] : [];
|
|
510
548
|
});
|
|
511
|
-
/**
|
|
512
|
-
|
|
513
|
-
*
|
|
514
|
-
* `DELETE` is here for the one call that removes rows rather than marking them,
|
|
515
|
-
* and it earns the third verb rather than being folded into a POST: what it
|
|
516
|
-
* does to a key is not what disabling one does, and a surface that spelled both
|
|
517
|
-
* as a POST would be inviting a reader to think it was.
|
|
518
|
-
*/
|
|
519
|
-
export const HTTP_METHODS = Object.freeze(["GET", "POST", "DELETE"]);
|
|
549
|
+
/** The methods this surface uses. */
|
|
550
|
+
export const HTTP_METHODS = Object.freeze(["GET", "POST"]);
|
|
520
551
|
/**
|
|
521
552
|
* Which door a call is behind.
|
|
522
553
|
*
|
|
@@ -704,7 +735,6 @@ export const ERROR_CODES = Object.freeze([
|
|
|
704
735
|
"charset_unsupported",
|
|
705
736
|
"encoding_unsupported",
|
|
706
737
|
"gateway_failed",
|
|
707
|
-
"key_made_for_a_dashboard",
|
|
708
738
|
"key_opened_this_call",
|
|
709
739
|
"malformed_body",
|
|
710
740
|
"malformed_query",
|
|
@@ -713,9 +743,7 @@ export const ERROR_CODES = Object.freeze([
|
|
|
713
743
|
"no_such_key",
|
|
714
744
|
"no_such_order",
|
|
715
745
|
"no_such_route",
|
|
716
|
-
"not_a_dashboard_key",
|
|
717
746
|
"not_authorised",
|
|
718
|
-
"not_invited",
|
|
719
747
|
"not_selling",
|
|
720
748
|
"not_this_purchase",
|
|
721
749
|
"order_closed_before_it_was_priced",
|
|
@@ -724,10 +752,8 @@ export const ERROR_CODES = Object.freeze([
|
|
|
724
752
|
"payment_already_spent",
|
|
725
753
|
"payment_not_taken",
|
|
726
754
|
"payment_not_verified",
|
|
727
|
-
"
|
|
728
|
-
"
|
|
729
|
-
"wallet_change_raced",
|
|
730
|
-
"wallet_change_unconfirmed",
|
|
755
|
+
"ship_to_changed",
|
|
756
|
+
"ship_to_does_not_fit",
|
|
731
757
|
]);
|
|
732
758
|
/**
|
|
733
759
|
* Every call of the surface, under the name it is known by in both programs.
|
|
@@ -801,14 +827,6 @@ export const API_ROUTES = Object.freeze({
|
|
|
801
827
|
description: "Starts selling again. Cards paused in their own right stay paused: stopping all selling did not forget which they were, and putting them all back on sale would sell products their merchant took off. The answer is the whole catalog, so which cards actually came back is a fact rather than an inference. A merchant who has left is refused: leaving closed the orders that were open and left refunds owed, and this switch unwinds none of it, so a departure is not undone here.",
|
|
802
828
|
response: { document: MerchantCardListSchema },
|
|
803
829
|
},
|
|
804
|
-
register_merchant: {
|
|
805
|
-
method: "POST",
|
|
806
|
-
path: "/v0/merchants",
|
|
807
|
-
auth: "none",
|
|
808
|
-
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 dashboard 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 dashboard: 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 dashboard 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.",
|
|
809
|
-
request: RegistrationRequestSchema,
|
|
810
|
-
response: { document: RegisteredMerchantSchema },
|
|
811
|
-
},
|
|
812
830
|
get_seller_name: {
|
|
813
831
|
method: "GET",
|
|
814
832
|
path: "/v0/seller-name",
|
|
@@ -828,29 +846,21 @@ export const API_ROUTES = Object.freeze({
|
|
|
828
846
|
method: "GET",
|
|
829
847
|
path: "/v0/payout-wallet",
|
|
830
848
|
auth: "merchant_key",
|
|
831
|
-
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
|
|
832
|
-
response: { document: PayoutWalletSchema },
|
|
833
|
-
},
|
|
834
|
-
set_payout_wallet: {
|
|
835
|
-
method: "POST",
|
|
836
|
-
path: "/v0/payout-wallet",
|
|
837
|
-
auth: "merchant_key",
|
|
838
|
-
description: "Sets the address the sales of the merchant this call's own key belongs to are paid into. Only the merchant's dashboard 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 dashboard. 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_dashboard_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 dashboard 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 dashboard, 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.",
|
|
839
|
-
request: PayoutWalletRequestSchema,
|
|
849
|
+
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; none sets it. A person signed in to the merchant's dashboard sets it on its Settings screen. On the live deployment a first address applies at once and is announced afterwards, and a replacement is told to every account of the merchant first and waits. 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.",
|
|
840
850
|
response: { document: PayoutWalletSchema },
|
|
841
851
|
},
|
|
842
852
|
list_keys: {
|
|
843
853
|
method: "GET",
|
|
844
854
|
path: "/v0/keys",
|
|
845
855
|
auth: "merchant_key",
|
|
846
|
-
description: "The keys the merchant this call's own key belongs to made for their own code, the revoked ones among them, and never the keys themselves. A merchant who has only ever signed into a dashboard has none of these, and an empty list is that answer rather than a fault: the
|
|
856
|
+
description: "The keys the merchant this call's own key belongs to made for their own code, the revoked ones among them, and never the keys themselves. A merchant who has only ever signed into a dashboard has none of these, and an empty list is that answer rather than a fault: the dashboard calls with no key. Whether the list is all of the rest is not something this document claims either: paging is not designed, and the absence of a field about it is not a promise that there is no more. The answer also names the key the call was made with, as this_call, and that field is the reason this is not a bare list: a merchant cannot disable the key their own call was made with, so a screen drawn without knowing which key that is would offer a button the gateway refuses. It is always one of the keys listed, since every key is one the merchant issued. Every row also says when a call was last seen on that key, which is the field a screen offering to revoke one is worth drawing at all — and it is a recorded answer rather than an exact one, lagging by minutes, and blank both for a key nothing has called and for one made before this gateway began recording, which nothing here tells apart. This call is itself one of those calls, so the key it was made with reads as used at about this moment.",
|
|
847
857
|
response: { document: MerchantKeyListSchema },
|
|
848
858
|
},
|
|
849
859
|
issue_key: {
|
|
850
860
|
method: "POST",
|
|
851
861
|
path: "/v0/keys",
|
|
852
862
|
auth: "merchant_key",
|
|
853
|
-
description: "Issues another key for the merchant's own code, to the merchant this call's own key belongs to. The key is generated here and never taken from the caller, and it comes back exactly once — what is kept afterwards is a digest, so nothing can show it again. A merchant with several keys can hand one to each worker and revoke one without touching the others, which is the whole reason a key is a row.
|
|
863
|
+
description: "Issues another key for the merchant's own code, to the merchant this call's own key belongs to. The key is generated here and never taken from the caller, and it comes back exactly once — what is kept afterwards is a digest, so nothing can show it again. A merchant with several keys can hand one to each worker and revoke one without touching the others, which is the whole reason a key is a row. The merchant's dashboard issues keys the same way, and every key a merchant has is one they see, name and revoke.",
|
|
854
864
|
request: IssueKeyRequestSchema,
|
|
855
865
|
response: { document: IssuedKeySchema },
|
|
856
866
|
},
|
|
@@ -858,23 +868,9 @@ export const API_ROUTES = Object.freeze({
|
|
|
858
868
|
method: "POST",
|
|
859
869
|
path: "/v0/keys/:key_id/disable",
|
|
860
870
|
auth: "merchant_key",
|
|
861
|
-
description: "Stops one of this merchant's keys working, from that instant, and touches no other key. Disabling a key that is already disabled changes nothing and answers the same way, keeping the instant it was first revoked at, so a retry after a dropped connection is safe.
|
|
871
|
+
description: "Stops one of this merchant's keys working, from that instant, and touches no other key. Disabling a key that is already disabled changes nothing and answers the same way, keeping the instant it was first revoked at, so a retry after a dropped connection is safe. Two refusals are worth knowing before a screen is built on this. A key belonging to another merchant is answered exactly as a key that does not exist, so this call is not a way of counting somebody else's keys. And the key this call was made with cannot be disabled by it — that one click and no more: the refusal is about the key in front of it, so a merchant holding two keys of their own can still disable either with the other, and two such calls at one moment can leave them with none of their own. That is not refused here or anywhere, and what it costs is their own code going quiet rather than the way back in, which is signing in to the dashboard with the link mailed to them.",
|
|
862
872
|
response: { document: DisabledKeySchema },
|
|
863
873
|
},
|
|
864
|
-
issue_dashboard_key: {
|
|
865
|
-
method: "POST",
|
|
866
|
-
path: "/v0/keys/dashboard",
|
|
867
|
-
auth: "merchant_key",
|
|
868
|
-
description: "Makes a key for a dashboard 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 dashboard 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 dashboard that replaces its own credential every time somebody signs in, which is what keeps a copy of a dashboard'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_dashboard_key: these two calls are the dashboard's own, and a merchant asking for one would be asking for a credential to a dashboard they are not standing in.",
|
|
869
|
-
response: { document: DashboardKeySchema },
|
|
870
|
-
},
|
|
871
|
-
forget_dashboard_key: {
|
|
872
|
-
method: "DELETE",
|
|
873
|
-
path: "/v0/keys/dashboard",
|
|
874
|
-
auth: "merchant_key",
|
|
875
|
-
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 dashboard 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_dashboard_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.",
|
|
876
|
-
response: { document: ForgottenDashboardKeySchema },
|
|
877
|
-
},
|
|
878
874
|
get_order: {
|
|
879
875
|
method: "GET",
|
|
880
876
|
path: "/v0/orders/:order_id",
|
|
@@ -917,7 +913,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
917
913
|
method: "POST",
|
|
918
914
|
path: "/v0/orders/:order_id/deliver",
|
|
919
915
|
auth: "merchant_key",
|
|
920
|
-
description: "The goods for an order the merchant took on earlier — the asynchronous mode's closure verb, called by the merchant rather than by the SDK. Idempotent by the order's identifier: called again after a dropped connection it delivers nothing twice and charges nothing twice, so repeating it is safe and keeping a note of what was already sent is not needed. A late call is accepted too — where the delivery deadline has passed and the refund has not yet been paid out, delivering closes the debt.",
|
|
916
|
+
description: "The goods for an order the merchant took on earlier — the asynchronous mode's closure verb, called by the merchant rather than by the SDK. Idempotent by the order's identifier: called again after a dropped connection it delivers nothing twice and charges nothing twice, so repeating it is safe and keeping a note of what was already sent is not needed. A late call is accepted too — where the delivery deadline has passed and the refund has not yet been paid out, delivering closes the debt. On a parcel's order the body is its shipment instead of goods (the shipment document: a carrier, a tracking number or null, and optionally a tracking page and an expected window). Agentify records the instant the call arrived as when the parcel shipped, the order reads shipped, and the shipment cannot be changed afterwards: the same one sent again succeeds, and a different one is refused with shipment_already_recorded.",
|
|
921
917
|
request: DeliverySchema,
|
|
922
918
|
response: { document: OrderCallResponseSchema },
|
|
923
919
|
},
|
|
@@ -965,7 +961,7 @@ export const API_ROUTES = Object.freeze({
|
|
|
965
961
|
method: "GET",
|
|
966
962
|
path: "/x402/orders/:order_id/status",
|
|
967
963
|
auth: "order_id",
|
|
968
|
-
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
|
|
964
|
+
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 only to the parties to the sale — the agent that bought, its merchant and Agentify — and appears in no catalog or listing. 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.",
|
|
969
965
|
response: { document: AgentOrderStatusSchema },
|
|
970
966
|
},
|
|
971
967
|
});
|
package/dist/card.d.ts
CHANGED
|
@@ -33,12 +33,16 @@ import type { Money } from "./primitives.js";
|
|
|
33
33
|
* `sync` — in the answer to the purchase, and the payment executes last, after
|
|
34
34
|
* the merchant has delivered. `async` — later, by a separate call, and the
|
|
35
35
|
* payment executes at the moment of purchase. `confirm` — the merchant is
|
|
36
|
-
* asked first, and the payment executes right after they say yes.
|
|
36
|
+
* asked first, and the payment executes right after they say yes. `ship` — a
|
|
37
|
+
* parcel the merchant hands to a carrier (ADR-0033): the payment executes at
|
|
38
|
+
* the moment of purchase, as in `async`, and the order carries the buyer's
|
|
39
|
+
* address until the merchant takes it on, or it ends without them.
|
|
37
40
|
*/
|
|
38
41
|
export declare const FulfillmentSchema: z.ZodEnum<{
|
|
39
42
|
sync: "sync";
|
|
40
43
|
async: "async";
|
|
41
44
|
confirm: "confirm";
|
|
45
|
+
ship: "ship";
|
|
42
46
|
}>;
|
|
43
47
|
/**
|
|
44
48
|
* How the price and availability of this card are asked for, if they are.
|
|
@@ -66,30 +70,6 @@ export declare const PriceCheckSchema: z.ZodUnion<readonly [z.ZodLiteral<"handle
|
|
|
66
70
|
* wherever a merchant's listing name is written down.
|
|
67
71
|
*/
|
|
68
72
|
export declare const ServiceNameSchema: z.ZodString;
|
|
69
|
-
/**
|
|
70
|
-
* The address of a seller's own shop on the web, where an agent takes what an
|
|
71
|
-
* order cannot answer (ADR-0034).
|
|
72
|
-
*
|
|
73
|
-
* Only an https origin, because anything after the host — a path, a query, a
|
|
74
|
-
* fragment — would be text of the merchant's own reaching every agent that
|
|
75
|
-
* reads the card, which is the free text the decision refuses. The host is the
|
|
76
|
-
* one part the merchant writes, so it is held to a domain name too: labels of
|
|
77
|
-
* letters, digits and hyphens, at most 253 characters, ending in a zone of
|
|
78
|
-
* letters or a punycode one. Anything a URL parser keeps as written would
|
|
79
|
-
* otherwise pass — a sentence of instructions, a quote, a host of any length —
|
|
80
|
-
* and so would a single word or an IP address, which point other people's
|
|
81
|
-
* agents into somebody's own network. What the pattern cannot do is tell a
|
|
82
|
-
* public name from a private one: a name in a zone kept for local networks,
|
|
83
|
-
* or a public one whose address leads into one, passes, and so does a
|
|
84
|
-
* hyphenated sentence of up to 253 characters that is a valid name. That is
|
|
85
|
-
* why an agent is told, beside every site, that nobody checked it.
|
|
86
|
-
*
|
|
87
|
-
* The pattern says all that in a form the JSON Schema export keeps, and it
|
|
88
|
-
* stops the check where it fails, so an address copied with a slash at the end
|
|
89
|
-
* is told once. Asking the URL parser for the origin catches what the pattern
|
|
90
|
-
* leaves, such as a punycode label the parser would write differently.
|
|
91
|
-
*/
|
|
92
|
-
export declare const SellerSiteSchema: z.ZodString;
|
|
93
73
|
/**
|
|
94
74
|
* Who sells, as an agent reads it beside a product and on an order: the name
|
|
95
75
|
* the merchant sells under and the site of their shop (ADR-0034).
|
|
@@ -139,7 +119,7 @@ export declare const CardSchema: z.ZodObject<{
|
|
|
139
119
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
140
120
|
title: z.ZodOptional<z.ZodString>;
|
|
141
121
|
}, z.core.$strict>>>>;
|
|
142
|
-
result: z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
122
|
+
result: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
143
123
|
type: z.ZodEnum<{
|
|
144
124
|
string: "string";
|
|
145
125
|
number: "number";
|
|
@@ -148,18 +128,20 @@ export declare const CardSchema: z.ZodObject<{
|
|
|
148
128
|
}>;
|
|
149
129
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
150
130
|
title: z.ZodOptional<z.ZodString>;
|
|
151
|
-
}, z.core.$strict
|
|
131
|
+
}, z.core.$strict>>>>;
|
|
152
132
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
153
133
|
fulfillment: z.ZodDefault<z.ZodEnum<{
|
|
154
134
|
sync: "sync";
|
|
155
135
|
async: "async";
|
|
156
136
|
confirm: "confirm";
|
|
137
|
+
ship: "ship";
|
|
157
138
|
}>>;
|
|
158
139
|
price_check: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"handler">, z.ZodObject<{
|
|
159
140
|
url: z.ZodURL;
|
|
160
141
|
}, z.core.$strict>]>>;
|
|
161
142
|
confirm_deadline_seconds: z.ZodOptional<z.ZodInt>;
|
|
162
143
|
fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
|
|
144
|
+
ship_within_seconds: z.ZodOptional<z.ZodInt>;
|
|
163
145
|
}, z.core.$strict>;
|
|
164
146
|
export type Fulfillment = z.infer<typeof FulfillmentSchema>;
|
|
165
147
|
export type PriceCheck = z.infer<typeof PriceCheckSchema>;
|
|
@@ -186,7 +168,8 @@ export type CardInput = Omit<Card, "price" | "params" | "result" | "fulfillment"
|
|
|
186
168
|
price: Money | string;
|
|
187
169
|
/** Each field whole, or written as its type word alone: `email: 'string'`. */
|
|
188
170
|
params?: ParamSpecInput;
|
|
189
|
-
|
|
171
|
+
/** Left out on a parcel's card, whose mode fixes what the agent receives. */
|
|
172
|
+
result?: ParamSpecInput;
|
|
190
173
|
/** Left out on a card that is delivered in the answer to the purchase. */
|
|
191
174
|
fulfillment?: Fulfillment;
|
|
192
175
|
};
|
|
@@ -200,7 +183,11 @@ export type CardInput = Omit<Card, "price" | "params" | "result" | "fulfillment"
|
|
|
200
183
|
* place that picks.
|
|
201
184
|
*/
|
|
202
185
|
export declare const purchaseCheckFor: (card: Card) => z.ZodType;
|
|
203
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* The check this card's delivery is held to: the goods its `result` declared,
|
|
188
|
+
* or for a parcel, which is not delivered with goods at all, its shipment
|
|
189
|
+
* (ADR-0033).
|
|
190
|
+
*/
|
|
204
191
|
export declare const deliveryCheckFor: (card: Card) => z.ZodType;
|
|
205
192
|
/**
|
|
206
193
|
* The fields of a card as an agent reads it in a catalog.
|
|
@@ -271,7 +258,7 @@ export declare const PublicCardSchema: z.ZodObject<{
|
|
|
271
258
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
272
259
|
title: z.ZodOptional<z.ZodString>;
|
|
273
260
|
}, z.core.$loose>>>;
|
|
274
|
-
result: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
261
|
+
result: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
275
262
|
type: z.ZodEnum<{
|
|
276
263
|
string: "string";
|
|
277
264
|
number: "number";
|
|
@@ -280,7 +267,7 @@ export declare const PublicCardSchema: z.ZodObject<{
|
|
|
280
267
|
}>;
|
|
281
268
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
282
269
|
title: z.ZodOptional<z.ZodString>;
|
|
283
|
-
}, z.core.$loose
|
|
270
|
+
}, z.core.$loose>>>;
|
|
284
271
|
price_checked_at_purchase: z.ZodBoolean;
|
|
285
272
|
seller: z.ZodObject<{
|
|
286
273
|
name: z.ZodNullable<z.ZodString>;
|
|
@@ -290,9 +277,11 @@ export declare const PublicCardSchema: z.ZodObject<{
|
|
|
290
277
|
sync: "sync";
|
|
291
278
|
async: "async";
|
|
292
279
|
confirm: "confirm";
|
|
280
|
+
ship: "ship";
|
|
293
281
|
}>, z.ZodString]>;
|
|
294
282
|
fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
|
|
295
283
|
confirm_deadline_seconds: z.ZodOptional<z.ZodInt>;
|
|
284
|
+
ship_within_seconds: z.ZodOptional<z.ZodInt>;
|
|
296
285
|
}, z.core.$loose>;
|
|
297
286
|
export type PublicCard = z.infer<typeof PublicCardSchema>;
|
|
298
287
|
/**
|
|
@@ -379,7 +368,10 @@ export interface BazaarDeclaration {
|
|
|
379
368
|
readonly input: Record<string, unknown>;
|
|
380
369
|
/** The JSON Schema that body is held to, derived from the card's `params`. */
|
|
381
370
|
readonly inputSchema: Record<string, unknown>;
|
|
382
|
-
/**
|
|
371
|
+
/**
|
|
372
|
+
* An example of what arrives on delivery, derived from the card's `result`,
|
|
373
|
+
* or for a parcel the record of its shipment.
|
|
374
|
+
*/
|
|
383
375
|
readonly output: {
|
|
384
376
|
readonly example: Record<string, unknown>;
|
|
385
377
|
};
|
|
@@ -444,7 +436,7 @@ export declare const MerchantCardSchema: z.ZodObject<{
|
|
|
444
436
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
445
437
|
title: z.ZodOptional<z.ZodString>;
|
|
446
438
|
}, z.core.$strict>>>>;
|
|
447
|
-
result: z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
439
|
+
result: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
448
440
|
type: z.ZodEnum<{
|
|
449
441
|
string: "string";
|
|
450
442
|
number: "number";
|
|
@@ -453,18 +445,20 @@ export declare const MerchantCardSchema: z.ZodObject<{
|
|
|
453
445
|
}>;
|
|
454
446
|
required: z.ZodOptional<z.ZodBoolean>;
|
|
455
447
|
title: z.ZodOptional<z.ZodString>;
|
|
456
|
-
}, z.core.$strict
|
|
448
|
+
}, z.core.$strict>>>>;
|
|
457
449
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
458
450
|
fulfillment: z.ZodDefault<z.ZodEnum<{
|
|
459
451
|
sync: "sync";
|
|
460
452
|
async: "async";
|
|
461
453
|
confirm: "confirm";
|
|
454
|
+
ship: "ship";
|
|
462
455
|
}>>;
|
|
463
456
|
price_check: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"handler">, z.ZodObject<{
|
|
464
457
|
url: z.ZodURL;
|
|
465
458
|
}, z.core.$strict>]>>;
|
|
466
459
|
confirm_deadline_seconds: z.ZodOptional<z.ZodInt>;
|
|
467
460
|
fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
|
|
461
|
+
ship_within_seconds: z.ZodOptional<z.ZodInt>;
|
|
468
462
|
}, z.core.$strict>;
|
|
469
463
|
selling: z.ZodEnum<{
|
|
470
464
|
open: "open";
|