@percayso-community/cayso-contracts 0.27.0 → 0.30.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/index.js CHANGED
@@ -92,6 +92,94 @@
92
92
  * this money surface gains that Piper's own contracts lack, since theirs share
93
93
  * one global version bumped across all twenty-two together (CAY-0026).
94
94
  *
95
+ * `0.29.0` → `0.30.0` publishes and SERVES Cayso's authorisation acknowledgement keys
96
+ * (CAY-0093): {@link ACKNOWLEDGEMENT_KEYS_ROUTE}, `GET /api/acknowledgement-keys`, an
97
+ * unauthenticated read outside `ROUTES`, described in the schema under `keyRoutes`;
98
+ * the key set it answers, {@link AcknowledgementKeySet} of
99
+ * {@link AcknowledgementPublicKey}, Ed25519 public JSON Web Keys and nothing private;
100
+ * and `CaysoApiErrorCode` gains `acknowledgement_signing_not_configured`, the route's
101
+ * closed door.
102
+ *
103
+ * The same version SERVES the standing authorisation (CAY-0094), published at `0.25.0`
104
+ * and answered until now by the router's `404`: `ROUTES.standingAuthorisation` answers
105
+ * {@link StandingAuthorisationResponse} with an acknowledgement signed under that key.
106
+ * It adds the owner's way to withdraw one: `ROUTES.revokeStandingAuthorisation`,
107
+ * `POST /api/cloud/standing-authorisation-revocations`, mapped to the new operation
108
+ * `'revoke-standing-authorisation'`, money-grade in `ASSURANCE_POLICY`; the client
109
+ * method `revokeStandingAuthorisation`; {@link StandingAuthorisationRevocationRequest},
110
+ * {@link StandingAuthorisationRevocationResponse} and the closed
111
+ * {@link StandingAuthorisationRevocationRefusal}, which `CaysoApiErrorCode` gains by
112
+ * reference; and the seam codes `standing_authorisation_store_not_configured`,
113
+ * `standing_authorisation_cap_ceiling_not_configured` and
114
+ * `standing_authorisation_life_ceiling_not_configured`.
115
+ *
116
+ * The same version publishes and SERVES binding a Node to a wallet (CMTY-0018 §4,
117
+ * CAY-0095): `ROUTES.bindNode`, `POST /api/cloud/node-bindings`, mapped to the new
118
+ * operation `'bind-node'`, money-grade in `ASSURANCE_POLICY`; the client method
119
+ * `bindNode`; {@link NodePresentationClaims}, {@link NodeBindingRequest},
120
+ * {@link NodeBindingResponse} and the closed {@link NodeBindingRefusal}. Beside it, the
121
+ * Contribution Store's read of whether a Node is bound: {@link NODE_BINDING_QUERY_ROUTE},
122
+ * `POST /api/cloud/node-binding-queries`, outside `ROUTES` and in the schema under
123
+ * `issuerRoutes`, authenticated by the registered Store issuer; {@link
124
+ * NodeBindingQueryClaims}, {@link NodeBindingQueryRequest}, the answer
125
+ * {@link NodeBindingStatus} — `nodeId` and `bound` and nothing else — and the closed
126
+ * {@link NodeBindingQueryRefusal}. `CaysoApiErrorCode` gains both unions by reference
127
+ * and the seam codes `node_binding_store_not_configured`, `core_node_ids_not_configured`
128
+ * and `contribution_store_issuer_not_configured`.
129
+ *
130
+ * The same version SERVES the Contribution Store's settlement assertion (CMTY-0018 §2,
131
+ * CAY-0096) at {@link CLOUD_SETTLEMENT_ROUTE}, published at `0.25.0` and answered until
132
+ * now by the router's `404`. A settled period writes one `contribution_settlement`
133
+ * movement per paid contribution row and one `consumption_settlement` per consumption
134
+ * row, so `MovementKind` and `MOVEMENT_KINDS` gain both. The closed refusal unions gain
135
+ * the members the write needs: {@link SettlementAssertionLevelRefusal} gains
136
+ * `settlement_period_not_recognised`, `settlement_period_not_ended` and
137
+ * `settlement_carve_contended`; {@link ContributionRowRefusal} gains
138
+ * `contribution_node_is_a_core_node` and `contribution_treasury_short`;
139
+ * {@link ConsumptionRowRefusal} gains `consumption_authorisation_not_in_force` and
140
+ * `consumption_wallet_short`. `CaysoApiErrorCode` gains them by reference and the seam
141
+ * code `cloud_settlement_store_not_configured`.
142
+ *
143
+ * BREAKING in the package's sense because closed tables grew: `ROUTES`,
144
+ * `ContractOperation`, `CaysoApiErrorCode`, `MovementKind` and the settlement's refusal
145
+ * unions. Additive on the wire (CAY-0086): no route a `0.29.0` consumer could reach
146
+ * changed, because the only ones that answer differently are the standing
147
+ * authorisation and the settlement assertion, which no deployment served before, and
148
+ * they answer the shapes `0.25.0` published, a member those shapes' unions gained, or a
149
+ * new seam code no served route emits. The operator movement list can now carry the two
150
+ * new kinds, and it is read only by the admin app in this tree, released with it. The
151
+ * two Node routes are ones a `0.29.0` consumer cannot name.
152
+ *
153
+ * `0.28.0` → `0.29.0` publishes and SERVES the Handle change (CAY-0091):
154
+ * `ROUTES.handleChange`, `POST /api/handle-changes`, mapped to the new operation
155
+ * `'change-handle'`, money-grade in `ASSURANCE_POLICY`; `ROUTES.handleChangeReceipt`,
156
+ * `GET /api/handle-changes/receipt`, mapped to the new read-scope operation
157
+ * `'read-handle-change-receipt'`; the assertion claim `handleChangeReference`, which
158
+ * travels with those two operations in both directions; the client methods
159
+ * `changeHandle` and `readHandleChangeReceipt`; the signed {@link HandleChangeReceipt}
160
+ * and its one encoding, {@link encodeHandleChangeReceiptStatement}; and
161
+ * `CaysoApiErrorCode` gains {@link HandleChangeRefusal} and
162
+ * {@link HandleChangeReceiptReadRefusal} by reference and the seam codes
163
+ * `handle_change_store_not_configured`, `handle_change_price_not_configured` and
164
+ * `handle_change_payee_not_configured`. BREAKING in the package's sense because closed
165
+ * tables grew. Additive on the wire: no route a `0.28.0` consumer calls changed or
166
+ * answers anything new, and a credential a `0.28.0` issuer mints carries neither the new
167
+ * scope keys nor the new claim (CAY-0086).
168
+ *
169
+ * `0.27.0` → `0.28.0` SERVES a Citizen publisher's marketplace sale (CAY-0090):
170
+ * `POST /api/marketplace/orders` settles a signed order whose payee is a
171
+ * `citizen_publisher` as one `marketplace_settlement`, answering the
172
+ * `MarketplaceSettlementReceiptStatement` `0.24.0` already published. The share is
173
+ * read from a new signed-order fact, `communityShareBasisPoints`, which Store Platform
174
+ * signs beside `allocationPolicyVersion`. {@link MarketplaceOrderRefusal} gains
175
+ * `allocation_share_out_of_range` and `payee_wallet_is_the_buyers`, and
176
+ * `allocation_policy_version_not_configured` is retired (kept, never answered). The
177
+ * operator `MovementKind` gains `marketplace_settlement`. BREAKING in the package's
178
+ * sense because closed tables grew. On the wire, every order a `0.27.0` consumer could
179
+ * present — one Store Platform signed without the new fact — is answered exactly as
180
+ * before, a Citizen publisher's with `third_party_marketplace_sale_not_served`; only an
181
+ * order carrying the new fact can reach a new code (CAY-0086).
182
+ *
95
183
  * `0.26.0` → `0.27.0` publishes and SERVES the Citizen transfer (CAY-0088):
96
184
  * `ROUTES.citizenTransfer`, `POST /api/citizen-transfers`, mapped to the new
97
185
  * operation `'make-citizen-transfer'`, money-grade in `ASSURANCE_POLICY`; the client
@@ -538,7 +626,7 @@
538
626
  * have needed a breaking bump on their own. Under semver below `1.0.0` the minor
539
627
  * is where a breaking change goes, so the minor moves and the patch does not.
540
628
  */
541
- export const CONTRACT_VERSION = '0.27.0';
629
+ export const CONTRACT_VERSION = '0.30.0';
542
630
  /** The package's own name, so a consumer can name what it depends on. */
543
631
  export const packageName = '@percayso-community/cayso-contracts';
544
632
  /**
@@ -562,6 +650,18 @@ export { ROUTES } from './routes.js';
562
650
  * no operation, no assurance bar and no client method.
563
651
  */
564
652
  export { CLOUD_SETTLEMENT_ROUTE } from './routes.js';
653
+ /**
654
+ * Where the Contribution Store asks whether a Node is bound (CAY-0095). A value beside
655
+ * `ROUTES` and never in it, for the settlement path's reason: it is authenticated by
656
+ * the registered Store issuer, not by a person.
657
+ */
658
+ export { NODE_BINDING_QUERY_ROUTE } from './routes.js';
659
+ /**
660
+ * Where Cayso publishes its authorisation acknowledgement keys (CAY-0093). A value
661
+ * beside `ROUTES` and never in it: an unauthenticated read of a public key carries no
662
+ * identity, so it has no operation, no assurance bar and no client method.
663
+ */
664
+ export { ACKNOWLEDGEMENT_KEYS_ROUTE } from './routes.js';
565
665
  /**
566
666
  * The purchase lifecycle's runtime half (CAY-0032): which statuses a purchase
567
667
  * never leaves, the predicate over them, and the window an authorisation holds its
@@ -672,3 +772,8 @@ export { REQUEST_RATE_LIMITED } from './errors.js';
672
772
  * one of the four.
673
773
  */
674
774
  export { MARKETPLACE_RECEIPT_SIGNATURE_ALGORITHM, encodeMarketplaceReceiptStatement, } from './marketplace-receipt.js';
775
+ /**
776
+ * The one encoding of a Handle-change receipt statement, called by the signer and by
777
+ * Percayso ID's verifier (CAY-0091).
778
+ */
779
+ export { encodeHandleChangeReceiptStatement } from './handle-change.js';
@@ -12,8 +12,10 @@
12
12
  *
13
13
  * **This is the contract surface only.** Nothing here settles anything. Since
14
14
  * `0.24.0` a route serves `settle-marketplace-order` for a house-publisher sale
15
- * (`ROUTES.marketplaceOrder`); the third-party sale and the refund are not served. The sale table, the registry of Store Platform order
16
- * keys and the ledger stay in this proprietary tree (CAY-0083 §3).
15
+ * (`ROUTES.marketplaceOrder`), and since `0.28.0` for a Citizen publisher's sale too,
16
+ * as one `marketplace_settlement` with a publisher leg and a Community leg (CAY-0090).
17
+ * The refund is not served, for either kind of sale. The sale table, the registry of
18
+ * Store Platform order keys and the ledger stay in this proprietary tree (CAY-0083 §3).
17
19
  *
18
20
  * ## Two operations, because two authorities are checked
19
21
  *
@@ -41,7 +43,9 @@
41
43
  * disagree eventually. What Cayso reads from them, once verified, is CAY-0082's
42
44
  * list — the order digest, the checkout's idempotency key, the price, the paying
43
45
  * wallet, the payee wallet or the house-publisher fact, and the allocation-policy
44
- * version.
46
+ * version — and, since `0.28.0`, the Community's share in basis points, which Store
47
+ * Platform snapshots into the checkout from its allocation policy and signs beside the
48
+ * version (CAY-0090, amending CAY-0082 §3).
45
49
  *
46
50
  * **Nothing about the sale is taken from the caller's word.** The house-publisher
47
51
  * fact, the payee wallet, the price and the idempotency key are all inside the
@@ -198,17 +202,33 @@ export type MarketplaceOrderRefusal =
198
202
  */
199
203
  | 'idempotency_key_reused_for_a_different_order'
200
204
  /**
201
- * The allocation-policy version the order names has no figure configured here, so
202
- * a third-party sale's split cannot be computed. A closed door, never a default
203
- * split. A house-publisher sale has no split and never meets it.
205
+ * RETIRED in `0.28.0`, and never answered since. It was published for a Cayso that
206
+ * would hold each allocation-policy version's figure itself; CAY-0090 put the figure
207
+ * in Store Platform's signed order instead, so no version can be "not configured"
208
+ * here. Kept in the union so a consumer's exhaustive map keeps compiling; a consumer
209
+ * may stop rendering it.
204
210
  */
205
211
  | 'allocation_policy_version_not_configured'
212
+ /**
213
+ * The Community's share the signed order carries (`communityShareBasisPoints`) is not
214
+ * a whole number from 0 to 10000, or, for a Citizen publisher's sale, leaves the
215
+ * publisher leg or the Community leg at zero cents at this price. A leg is a lot that
216
+ * arrives, and a lot of no cents is not one (CAY-0078, CAY-0090), so a share of 0 or
217
+ * 10000, or a price too small to split, is refused rather than settled with one leg.
218
+ */
219
+ | 'allocation_share_out_of_range'
206
220
  /** No wallet has the payee's id. */
207
221
  | 'payee_wallet_not_found'
208
222
  /** The payee's wallet is an Organisation Wallet or the Treasury. A paid sale's publisher is a Citizen (CAY-0082 §8). */
209
223
  | 'payee_wallet_not_a_citizens'
210
224
  /** No Citizen is bound to the payee's wallet now, for example because the binding was erased. */
211
225
  | 'payee_wallet_has_no_live_binding'
226
+ /**
227
+ * The payee's wallet is the buyer's own: a publisher buying their own listing. A
228
+ * movement never runs from a wallet to itself, so nothing is paid and nothing is
229
+ * written (CAY-0090).
230
+ */
231
+ | 'payee_wallet_is_the_buyers'
212
232
  /**
213
233
  * A third-party sale: the buyer's unrestricted cents are short. Restricted cents
214
234
  * are never counted and never drawn for one (CAY-0076), so a wallet holding enough
@@ -85,7 +85,7 @@ export declare const OPERATOR_READ_ROUTES: {
85
85
  * movement list's `kind` filter refuses anything outside it (`400 invalid_kind`), and
86
86
  * every row's `kind` is one of these.
87
87
  */
88
- export type MovementKind = 'issuance' | 'purchase' | 'grant' | 'charge' | 'payout' | 'transfer' | 'burn' | 'forfeit' | 'commercial_payment' | 'quoted_sale' | 'buy_back' | 'quoted_sale_compensation';
88
+ export type MovementKind = 'issuance' | 'purchase' | 'grant' | 'charge' | 'payout' | 'transfer' | 'burn' | 'forfeit' | 'commercial_payment' | 'quoted_sale' | 'buy_back' | 'quoted_sale_compensation' | 'marketplace_settlement' | 'contribution_settlement' | 'consumption_settlement';
89
89
  /** Every {@link MovementKind}, in the service's order — for a filter a person picks from. */
90
90
  export declare const MOVEMENT_KINDS: readonly MovementKind[];
91
91
  /**
@@ -96,6 +96,16 @@ export declare const MOVEMENT_KINDS: readonly MovementKind[];
96
96
  * `fromWalletId` is null when the cents came from unissued (an issuance) and
97
97
  * `toWalletId` is null when they went back to it (a burn, a forfeiture). Both are
98
98
  * wallet ids — the operator-facing handle — and never an identity.
99
+ *
100
+ * A `marketplace_settlement` lands in two wallets (CAY-0082 §1): `toWalletId` is the
101
+ * publisher's Citizen Wallet and `cents` the whole price the buyer paid. The Community
102
+ * leg's share of it went to the Treasury inside the same movement, and the row does not
103
+ * itemise it; the signed receipt names both legs (CAY-0090).
104
+ *
105
+ * A `contribution_settlement` runs from the Treasury to a Node's wallet, and a
106
+ * `consumption_settlement` from an Instance's wallet to the Treasury: one per row of a
107
+ * settled Cloud period (CAY-0096). Neither row names the Node, the authorisation or
108
+ * the period; the wallet ids are the handle here as everywhere.
99
109
  */
100
110
  export interface OperatorMovementRow {
101
111
  /** The row's own opaque handle: a stable list key, not an identity. */
package/dist/operator.js CHANGED
@@ -45,4 +45,7 @@ export const MOVEMENT_KINDS = [
45
45
  'quoted_sale',
46
46
  'buy_back',
47
47
  'quoted_sale_compensation',
48
+ 'marketplace_settlement',
49
+ 'contribution_settlement',
50
+ 'consumption_settlement',
48
51
  ];
package/dist/routes.d.ts CHANGED
@@ -84,6 +84,16 @@
84
84
  * Wallet, resolved inside `apps/api`, because a sending wallet the caller named would
85
85
  * be the caller's claim about whose cents these are (CAY-0021).
86
86
  *
87
+ * ## Why `handleChange` and `handleChangeReceipt` take nothing but the credential
88
+ *
89
+ * `POST /api/handle-changes` is a Citizen's Handle change, charged by Cayso, and
90
+ * `GET /api/handle-changes/receipt` asks whether a change reference was charged
91
+ * (CAY-0091). Nothing either request could carry is the caller's to say: the paying
92
+ * wallet is the verified subject's own, the price is Cayso's configuration, and the
93
+ * change reference is inside the signed assertion. So there is nothing to send but the
94
+ * credential, as with the founder claim. They are two paths because they are two
95
+ * operations, and one path carries one scope requirement at the gate.
96
+ *
87
97
  * ## Why the citizen market is FOUR PATHS, and none of them names a wallet
88
98
  *
89
99
  * `citizenMarket` reads the book, `placeQuote` places a quote, and `withdrawQuote`
@@ -109,13 +119,34 @@
109
119
  * authorisation under the owner's assertion (`present-standing-authorisation`,
110
120
  * CMTY-0018 §1). A person is behind it, so it is classified by a person's
111
121
  * assurance like every other entry. It names no wallet: the wallet is the verified
112
- * holder's own. It is published before it is served.
122
+ * holder's own. Published at `0.25.0` and served from `0.30.0` (CAY-0094).
123
+ *
124
+ * `revokeStandingAuthorisation` withdraws one (`revoke-standing-authorisation`). It
125
+ * is its own path for citizenship's reason, and a `POST` for cancelling's: nothing is
126
+ * deleted. The authorisation's row stays, and so does its Instance key's binding to
127
+ * the wallet; the revocation is a row of its own beside them. The body names the
128
+ * authorisation's `jti` and no wallet.
129
+ *
130
+ * `bindNode` binds a Node to the wallet its presenting Instance key is already bound
131
+ * to (`bind-node`, CAY-0095), under the owner's assertion. A person is behind it, so
132
+ * it is classified by a person's assurance. The body carries the Node ID signed by the
133
+ * Instance key and that key's public half, and no wallet: the wallet is the one the
134
+ * key is bound to, which must be the verified holder's own. A `POST` to a collection
135
+ * of bindings, because a Node is bound once and a repeat answers the same.
113
136
  *
114
137
  * The Contribution Store's settlement assertion is presented by no person. Its path
115
138
  * is {@link CLOUD_SETTLEMENT_ROUTE}, outside this table, because every entry here is
116
139
  * mapped in `OPERATION_FOR_ROUTE` to the assurance a person needs, and `null` there
117
140
  * means "carries no identity", which is false of an assertion a registered issuer
118
- * signed.
141
+ * signed. The Store's read of whether a Node is bound,
142
+ * {@link NODE_BINDING_QUERY_ROUTE}, is outside it for the same reason.
143
+ *
144
+ * ## Why Cayso's acknowledgement keys are outside this table too
145
+ *
146
+ * {@link ACKNOWLEDGEMENT_KEYS_ROUTE} publishes the public half of the key Cayso signs
147
+ * an authorisation acknowledgement with. It carries no identity at all, so it is not
148
+ * a person's operation either, and it is read by the Percayso Cloud's software rather
149
+ * than by a person's, so the client has no method for it.
119
150
  */
120
151
  export declare const ROUTES: {
121
152
  readonly wallet: {
@@ -158,6 +189,14 @@ export declare const ROUTES: {
158
189
  readonly method: "POST";
159
190
  readonly path: "/api/citizen-transfers";
160
191
  };
192
+ readonly handleChange: {
193
+ readonly method: "POST";
194
+ readonly path: "/api/handle-changes";
195
+ };
196
+ readonly handleChangeReceipt: {
197
+ readonly method: "GET";
198
+ readonly path: "/api/handle-changes/receipt";
199
+ };
161
200
  readonly citizenMarket: {
162
201
  readonly method: "GET";
163
202
  readonly path: "/api/citizen-market";
@@ -182,6 +221,14 @@ export declare const ROUTES: {
182
221
  readonly method: "POST";
183
222
  readonly path: "/api/cloud/standing-authorisations";
184
223
  };
224
+ readonly revokeStandingAuthorisation: {
225
+ readonly method: "POST";
226
+ readonly path: "/api/cloud/standing-authorisation-revocations";
227
+ };
228
+ readonly bindNode: {
229
+ readonly method: "POST";
230
+ readonly path: "/api/cloud/node-bindings";
231
+ };
185
232
  readonly version: {
186
233
  readonly method: "GET";
187
234
  readonly path: "/api/version";
@@ -199,9 +246,45 @@ export declare const ROUTES: {
199
246
  * in {@link ROUTES}, whose every entry is classified by a person's assurance. The
200
247
  * client has no method for it, because no person's software calls it.
201
248
  *
202
- * Published before it is served.
249
+ * Published at `0.25.0` and served from `0.30.0` (CAY-0096): a settled period is one
250
+ * `contribution_settlement` movement per paid contribution row and one
251
+ * `consumption_settlement` movement per consumption row, written whole or not at all.
203
252
  */
204
253
  export declare const CLOUD_SETTLEMENT_ROUTE: {
205
254
  readonly method: "POST";
206
255
  readonly path: "/api/cloud/settlement-assertions";
207
256
  };
257
+ /**
258
+ * Where the Percayso Cloud's Contribution Store asks whether one Node is bound to a
259
+ * wallet (CMTY-0018 §4, CAY-0095), so it can carry an unbound Node's rows withheld
260
+ * (`node_not_bound`) rather than pay them to nobody.
261
+ *
262
+ * **Authenticated by the registered Store issuer, exactly as
263
+ * {@link CLOUD_SETTLEMENT_ROUTE} is, and never by a person.** The body is the Store's
264
+ * own signed query, naming the one Node it asks about, so a captured query answers
265
+ * for that Node and no other. A person issuer's key is never the Store's, so a query
266
+ * a person signed is refused. It answers `{ nodeId, bound }` and nothing else: no
267
+ * wallet, holder, Citizen or date crosses to the Cloud. A `POST` because the question
268
+ * travels signed in the body; nothing is written. Not in {@link ROUTES}, and no
269
+ * client method, because no person's software calls it.
270
+ */
271
+ export declare const NODE_BINDING_QUERY_ROUTE: {
272
+ readonly method: "POST";
273
+ readonly path: "/api/cloud/node-binding-queries";
274
+ };
275
+ /**
276
+ * Where Cayso publishes the public half of every key it signs an authorisation
277
+ * acknowledgement with (CMTY-0018 §1, CMTY-0022 row 9): a JSON Web Key Set the
278
+ * Percayso Cloud reads to verify an acknowledgement an Instance hands it.
279
+ *
280
+ * **An unauthenticated read**, because a public key is public: it carries no
281
+ * identity, names no wallet and moves nothing. Not in {@link ROUTES}, whose every
282
+ * entry is classified by a person's assurance, and no client method, because no
283
+ * person's software calls it. A deployment holding no acknowledgement key answers
284
+ * `503 acknowledgement_signing_not_configured`, never an empty set a verifier would
285
+ * read as "Cayso signs nothing".
286
+ */
287
+ export declare const ACKNOWLEDGEMENT_KEYS_ROUTE: {
288
+ readonly method: "GET";
289
+ readonly path: "/api/acknowledgement-keys";
290
+ };
package/dist/routes.js CHANGED
@@ -99,6 +99,16 @@
99
99
  * Wallet, resolved inside `apps/api`, because a sending wallet the caller named would
100
100
  * be the caller's claim about whose cents these are (CAY-0021).
101
101
  *
102
+ * ## Why `handleChange` and `handleChangeReceipt` take nothing but the credential
103
+ *
104
+ * `POST /api/handle-changes` is a Citizen's Handle change, charged by Cayso, and
105
+ * `GET /api/handle-changes/receipt` asks whether a change reference was charged
106
+ * (CAY-0091). Nothing either request could carry is the caller's to say: the paying
107
+ * wallet is the verified subject's own, the price is Cayso's configuration, and the
108
+ * change reference is inside the signed assertion. So there is nothing to send but the
109
+ * credential, as with the founder claim. They are two paths because they are two
110
+ * operations, and one path carries one scope requirement at the gate.
111
+ *
102
112
  * ## Why the citizen market is FOUR PATHS, and none of them names a wallet
103
113
  *
104
114
  * `citizenMarket` reads the book, `placeQuote` places a quote, and `withdrawQuote`
@@ -124,13 +134,34 @@
124
134
  * authorisation under the owner's assertion (`present-standing-authorisation`,
125
135
  * CMTY-0018 §1). A person is behind it, so it is classified by a person's
126
136
  * assurance like every other entry. It names no wallet: the wallet is the verified
127
- * holder's own. It is published before it is served.
137
+ * holder's own. Published at `0.25.0` and served from `0.30.0` (CAY-0094).
138
+ *
139
+ * `revokeStandingAuthorisation` withdraws one (`revoke-standing-authorisation`). It
140
+ * is its own path for citizenship's reason, and a `POST` for cancelling's: nothing is
141
+ * deleted. The authorisation's row stays, and so does its Instance key's binding to
142
+ * the wallet; the revocation is a row of its own beside them. The body names the
143
+ * authorisation's `jti` and no wallet.
144
+ *
145
+ * `bindNode` binds a Node to the wallet its presenting Instance key is already bound
146
+ * to (`bind-node`, CAY-0095), under the owner's assertion. A person is behind it, so
147
+ * it is classified by a person's assurance. The body carries the Node ID signed by the
148
+ * Instance key and that key's public half, and no wallet: the wallet is the one the
149
+ * key is bound to, which must be the verified holder's own. A `POST` to a collection
150
+ * of bindings, because a Node is bound once and a repeat answers the same.
128
151
  *
129
152
  * The Contribution Store's settlement assertion is presented by no person. Its path
130
153
  * is {@link CLOUD_SETTLEMENT_ROUTE}, outside this table, because every entry here is
131
154
  * mapped in `OPERATION_FOR_ROUTE` to the assurance a person needs, and `null` there
132
155
  * means "carries no identity", which is false of an assertion a registered issuer
133
- * signed.
156
+ * signed. The Store's read of whether a Node is bound,
157
+ * {@link NODE_BINDING_QUERY_ROUTE}, is outside it for the same reason.
158
+ *
159
+ * ## Why Cayso's acknowledgement keys are outside this table too
160
+ *
161
+ * {@link ACKNOWLEDGEMENT_KEYS_ROUTE} publishes the public half of the key Cayso signs
162
+ * an authorisation acknowledgement with. It carries no identity at all, so it is not
163
+ * a person's operation either, and it is read by the Percayso Cloud's software rather
164
+ * than by a person's, so the client has no method for it.
134
165
  */
135
166
  export const ROUTES = {
136
167
  wallet: { method: 'GET', path: '/api/wallet' },
@@ -143,12 +174,19 @@ export const ROUTES = {
143
174
  purchaseCancel: { method: 'POST', path: '/api/purchases/:purchaseId/cancel' },
144
175
  commercialPayment: { method: 'POST', path: '/api/commercial-payments' },
145
176
  citizenTransfer: { method: 'POST', path: '/api/citizen-transfers' },
177
+ handleChange: { method: 'POST', path: '/api/handle-changes' },
178
+ handleChangeReceipt: { method: 'GET', path: '/api/handle-changes/receipt' },
146
179
  citizenMarket: { method: 'GET', path: '/api/citizen-market' },
147
180
  placeQuote: { method: 'POST', path: '/api/quotes' },
148
181
  withdrawQuote: { method: 'POST', path: '/api/quote-withdrawals' },
149
182
  requestBuyBack: { method: 'POST', path: '/api/buy-backs' },
150
183
  marketplaceOrder: { method: 'POST', path: '/api/marketplace/orders' },
151
184
  standingAuthorisation: { method: 'POST', path: '/api/cloud/standing-authorisations' },
185
+ revokeStandingAuthorisation: {
186
+ method: 'POST',
187
+ path: '/api/cloud/standing-authorisation-revocations',
188
+ },
189
+ bindNode: { method: 'POST', path: '/api/cloud/node-bindings' },
152
190
  version: { method: 'GET', path: '/api/version' },
153
191
  };
154
192
  /**
@@ -163,9 +201,45 @@ export const ROUTES = {
163
201
  * in {@link ROUTES}, whose every entry is classified by a person's assurance. The
164
202
  * client has no method for it, because no person's software calls it.
165
203
  *
166
- * Published before it is served.
204
+ * Published at `0.25.0` and served from `0.30.0` (CAY-0096): a settled period is one
205
+ * `contribution_settlement` movement per paid contribution row and one
206
+ * `consumption_settlement` movement per consumption row, written whole or not at all.
167
207
  */
168
208
  export const CLOUD_SETTLEMENT_ROUTE = {
169
209
  method: 'POST',
170
210
  path: '/api/cloud/settlement-assertions',
171
211
  };
212
+ /**
213
+ * Where the Percayso Cloud's Contribution Store asks whether one Node is bound to a
214
+ * wallet (CMTY-0018 §4, CAY-0095), so it can carry an unbound Node's rows withheld
215
+ * (`node_not_bound`) rather than pay them to nobody.
216
+ *
217
+ * **Authenticated by the registered Store issuer, exactly as
218
+ * {@link CLOUD_SETTLEMENT_ROUTE} is, and never by a person.** The body is the Store's
219
+ * own signed query, naming the one Node it asks about, so a captured query answers
220
+ * for that Node and no other. A person issuer's key is never the Store's, so a query
221
+ * a person signed is refused. It answers `{ nodeId, bound }` and nothing else: no
222
+ * wallet, holder, Citizen or date crosses to the Cloud. A `POST` because the question
223
+ * travels signed in the body; nothing is written. Not in {@link ROUTES}, and no
224
+ * client method, because no person's software calls it.
225
+ */
226
+ export const NODE_BINDING_QUERY_ROUTE = {
227
+ method: 'POST',
228
+ path: '/api/cloud/node-binding-queries',
229
+ };
230
+ /**
231
+ * Where Cayso publishes the public half of every key it signs an authorisation
232
+ * acknowledgement with (CMTY-0018 §1, CMTY-0022 row 9): a JSON Web Key Set the
233
+ * Percayso Cloud reads to verify an acknowledgement an Instance hands it.
234
+ *
235
+ * **An unauthenticated read**, because a public key is public: it carries no
236
+ * identity, names no wallet and moves nothing. Not in {@link ROUTES}, whose every
237
+ * entry is classified by a person's assurance, and no client method, because no
238
+ * person's software calls it. A deployment holding no acknowledgement key answers
239
+ * `503 acknowledgement_signing_not_configured`, never an empty set a verifier would
240
+ * read as "Cayso signs nothing".
241
+ */
242
+ export const ACKNOWLEDGEMENT_KEYS_ROUTE = {
243
+ method: 'GET',
244
+ path: '/api/acknowledgement-keys',
245
+ };
@@ -23,7 +23,8 @@
23
23
  * consumer's business, Piper's or the Percayso Cloud's, and a schema that
24
24
  * enumerated the operator surface would have published it (CAY-0026, Amendment 3;
25
25
  * CLAUDE.md). The Contribution Store's settlement path is published, but under
26
- * `issuerRoutes`, apart from the routes a person calls. The generator only ever sees this package, so the
26
+ * `issuerRoutes`, apart from the routes a person calls, and Cayso's acknowledgement keys
27
+ * under `keyRoutes`. The generator only ever sees this package, so the
27
28
  * internal surface is absent by construction.
28
29
  *
29
30
  * The one part of the operator surface that IS published — the three reads on the
@@ -129,10 +130,19 @@ export interface ContractSchema {
129
130
  /**
130
131
  * The routes authenticated by a registered issuer (CAY-0030) rather than by a
131
132
  * person, and therefore not in `ROUTES`: today the Contribution Store's
132
- * settlement path (`CLOUD_SETTLEMENT_ROUTE`, CMTY-0018 §2). Kept apart from
133
+ * settlement path (`CLOUD_SETTLEMENT_ROUTE`, CMTY-0018 §2) and its read of whether a
134
+ * Node is bound (`NODE_BINDING_QUERY_ROUTE`, CAY-0095). Kept apart from
133
135
  * {@link routes} so that no consumer reads one as the other.
134
136
  */
135
137
  readonly issuerRoutes: Readonly<Record<string, SchemaRoute>>;
138
+ /**
139
+ * The unauthenticated reads that publish the public half of a key Cayso signs
140
+ * with, and therefore not in `ROUTES` either: today the authorisation
141
+ * acknowledgement keys (`ACKNOWLEDGEMENT_KEYS_ROUTE`, CAY-0093). No credential
142
+ * travels with them, so they are apart from both {@link routes} and
143
+ * {@link issuerRoutes}.
144
+ */
145
+ readonly keyRoutes: Readonly<Record<string, SchemaRoute>>;
136
146
  readonly types: Readonly<Record<string, SchemaType>>;
137
147
  /**
138
148
  * The operator reads an operator app's server calls, and their types — under
package/dist/schema.d.ts CHANGED
@@ -10,15 +10,27 @@
10
10
  * none of this, and importing it does nothing but hand back a frozen data value
11
11
  * and its types (CLAUDE.md: packages have no side effects on import).
12
12
  *
13
- * ## This is a diagnostic, NOT a replacement for depending on the package
13
+ * ## A published, versioned surface — and the one a Go consumer depends on
14
14
  *
15
- * The schema exists so a running deployment can *report* the surface it was built
16
- * against — for the version endpoint, for the contract test, for an operator
17
- * eyeballing a mismatch. It is emphatically not a runtime type system: a consumer
18
- * gets its compile-time guarantees by depending on `@percayso-community/cayso-contracts` and its
19
- * types, which do not exist at runtime to be fetched. Fetching this schema to
20
- * drive validation instead of depending on the package would re-implement, badly,
21
- * the guarantee the package already gives for free (CAY-0026, and the README).
15
+ * Two consumers read this descriptor, in two ways, and both are depending on the
16
+ * package (CAY-0026 Amendment 3; CMTY-0018 §3 as amended):
17
+ *
18
+ * - **A TypeScript consumer imports the types** and the compiler holds the
19
+ * surface; for it this descriptor is a tool *about* the contract — the version
20
+ * endpoint, the CI contract test, an operator eyeballing a mismatch — and never
21
+ * a runtime type system standing in for the import.
22
+ * - **A consumer in another language generates from this entry point of the
23
+ * published tarball at a pinned version**, and fails its own build when its
24
+ * generated types drift from the schema. The Percayso Cloud is that consumer: it
25
+ * is written in Go, cannot import a TypeScript type, and generates its types for
26
+ * the two seams in `cloud-settlement` from the tarball it pins. The pin is its
27
+ * lockfile entry and the regeneration is its compile. The schema ships as a JS
28
+ * module only, which is why the generator reads the tarball.
29
+ *
30
+ * What is refused is reading the schema OFF THE WIRE (`GET /api/version/schema`)
31
+ * as a substitute for pinning the package: that couples a consumer's build to a
32
+ * deployment's uptime and replaces a pinned version with whatever is deployed. The
33
+ * endpoint reports a running deployment; the package is the contract (the README).
22
34
  */
23
35
  export type { ContractSchema, ScalarKind, SchemaProperty, SchemaOperatorRoute, SchemaOperatorSurface, SchemaRoute, SchemaType, SchemaTypeNode, } from './schema-types.js';
24
36
  export { CONTRACT_SCHEMA } from './contract-schema.generated.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percayso-community/cayso-contracts",
3
- "version": "0.27.0",
3
+ "version": "0.30.0",
4
4
  "description": "The versioned capability contract surface through which anything outside this repository reads a wallet. Published; keep it the surface of every consumer outside this tree, Piper and the Percayso Cloud, and nothing internal.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {