@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/errors.d.ts CHANGED
@@ -43,8 +43,9 @@
43
43
  */
44
44
  import type { FounderClaimRefusal } from './citizenship.js';
45
45
  import type { BuyBackRefusal, QuotePlacementRefusal, QuoteWithdrawalRefusal } from './citizen-market.js';
46
- import type { SettlementAssertionRefusal, StandingAuthorisationRefusal } from './cloud-settlement.js';
46
+ import type { SettlementAssertionRefusal, StandingAuthorisationRefusal, StandingAuthorisationRevocationRefusal, NodeBindingQueryRefusal, NodeBindingRefusal } from './cloud-settlement.js';
47
47
  import type { CitizenTransferRefusal } from './citizen-transfer.js';
48
+ import type { HandleChangeReceiptReadRefusal, HandleChangeRefusal } from './handle-change.js';
48
49
  import type { CommercialPaymentRefusal } from './commercial-payment.js';
49
50
  import type { MarketplaceReceiptReadRefusal } from './marketplace-receipt.js';
50
51
  import type { MarketplaceOrderRefusal, MarketplaceRefundRefusal } from './marketplace-settlement.js';
@@ -126,6 +127,21 @@ export type CaysoApiErrorCode =
126
127
  * transfer's refusal union.
127
128
  */
128
129
  | 'citizen_transfer_store_not_configured'
130
+ /**
131
+ * No Handle-change store is wired, so the route is closed (CAY-0091). It describes
132
+ * the deployment and not the payment, so it is not a member of the refusal union.
133
+ */
134
+ | 'handle_change_store_not_configured'
135
+ /**
136
+ * The Handle-change price is not configured on this deployment, so nothing can be
137
+ * charged (CAY-0091). An unset price is a closed door, never a free Handle change.
138
+ */
139
+ | 'handle_change_price_not_configured'
140
+ /**
141
+ * The Organisation Wallet a Handle change is charged to is not configured on this
142
+ * deployment (CAY-0091). There is no default payee, so the route is closed.
143
+ */
144
+ | 'handle_change_payee_not_configured'
129
145
  /**
130
146
  * The citizen market is shut on this deployment: no store is wired, or a figure
131
147
  * the book needs is not set in the canon and so not configured here (CAY-0080,
@@ -159,6 +175,59 @@ export type CaysoApiErrorCode =
159
175
  * start.
160
176
  */
161
177
  | 'receipt_signing_not_configured'
178
+ /**
179
+ * This deployment holds no key it may sign an authorisation acknowledgement with,
180
+ * so it publishes no acknowledgement key and signs no acknowledgement (CAY-0093).
181
+ * A closed door, never an empty key set: a verifier reading an empty set would
182
+ * learn nothing true.
183
+ */
184
+ | 'acknowledgement_signing_not_configured'
185
+ /**
186
+ * No standing-authorisation store is wired, so no Instance key can be bound and no
187
+ * authorisation presented or revoked (CAY-0094).
188
+ */
189
+ | 'standing_authorisation_store_not_configured'
190
+ /**
191
+ * The ceiling on what a holder may delegate to an Instance per period is not
192
+ * configured on this deployment, so no standing authorisation is acknowledged
193
+ * (CAY-0094, CAY-0024). The figure is the canon's; unset is a closed door and never
194
+ * "no limit", and it is not `cap_not_delegable`, which says the cap is too high.
195
+ */
196
+ | 'standing_authorisation_cap_ceiling_not_configured'
197
+ /**
198
+ * The ceiling on how long a standing authorisation may live is not configured on
199
+ * this deployment, so none is acknowledged (CAY-0094). The figure is the canon's;
200
+ * unset is a closed door and never "no limit", and it is not
201
+ * `authorisation_outlives_its_ceiling`, which says the authorisation is too long.
202
+ */
203
+ | 'standing_authorisation_life_ceiling_not_configured'
204
+ /**
205
+ * No Node-binding store is wired, so no Node can be bound and the Contribution
206
+ * Store's read of a Node's binding is not answered (CAY-0095). Never "unbound": a
207
+ * read that cannot look must not tell the Store a bound Node's rows are withheld.
208
+ */
209
+ | 'node_binding_store_not_configured'
210
+ /**
211
+ * This deployment has not been told which Node IDs are Core Nodes, so no Node is
212
+ * bound and the Store's read is not answered (CAY-0095): binding one, or answering for
213
+ * one, without knowing would let a Core Node, whose owner is the Operator, earn for a
214
+ * Citizen Wallet. Told "none" is a configuration; untold is a closed door.
215
+ */
216
+ | 'core_node_ids_not_configured'
217
+ /**
218
+ * No Contribution Store issuer is registered on this deployment, so no statement
219
+ * from the Store is verified and the Store's read of a Node's binding is not
220
+ * answered (CAY-0095). Not Store Platform's order keys, which
221
+ * are `marketplace_order_keys_not_configured`'s.
222
+ */
223
+ | 'contribution_store_issuer_not_configured'
224
+ /**
225
+ * No settlement store is wired — this deployment has no Treasury configured, so a
226
+ * contribution has nowhere to be paid from and a consumption nowhere to be paid to
227
+ * — and no settlement assertion is settled (CAY-0096). Never a refusal: the Store's
228
+ * period is not wrong, Cayso is not ready to read it.
229
+ */
230
+ | 'cloud_settlement_store_not_configured'
162
231
  /**
163
232
  * This deployment holds no registry of Store Platform order keys, so no signed
164
233
  * order can be verified and no marketplace operation is served (CAY-0083 §4).
@@ -171,11 +240,13 @@ export type CaysoApiErrorCode =
171
240
  */
172
241
  | 'marketplace_order_store_not_configured'
173
242
  /**
174
- * The signed order pays a Citizen publisher, and this version serves the
175
- * house-publisher sale only (CAY-0082 §2). Nothing was checked against the payee and
176
- * nothing moved. A seam code rather than a {@link MarketplaceOrderRefusal}, because it
177
- * describes this deployment and not the order; the third-party sale retires it when
178
- * it ships.
243
+ * The signed order pays a Citizen publisher and carries no Community share
244
+ * (`communityShareBasisPoints`): Store Platform signed it before CAY-0090 put the
245
+ * share in the order, so Cayso has no figure to divide the price by. Nothing was
246
+ * checked against the payee and nothing moved. Before the share was a fact every
247
+ * Citizen publisher's order was answered this way; now only one without it is.
248
+ * A seam code rather than a {@link MarketplaceOrderRefusal}, because it describes
249
+ * what the deployments in the path speak and not the order.
179
250
  */
180
251
  | 'third_party_marketplace_sale_not_served'
181
252
  /** The request body or parameters did not satisfy the declared schema. */
@@ -183,7 +254,7 @@ export type CaysoApiErrorCode =
183
254
  /** There is no such purchase under this caller's wallet. */
184
255
  | 'not_found'
185
256
  /** Something failed on the way and the refusal discloses nothing further. */
186
- | 'internal_error' | PurchaseFailureReason | PurchaseCancelRefusalReason | FounderClaimRefusal | CommercialPaymentRefusal | CitizenTransferRefusal | QuotePlacementRefusal | QuoteWithdrawalRefusal | BuyBackRefusal | MarketplaceReceiptReadRefusal | MarketplaceOrderRefusal | MarketplaceRefundRefusal | StandingAuthorisationRefusal | SettlementAssertionRefusal;
257
+ | 'internal_error' | PurchaseFailureReason | PurchaseCancelRefusalReason | FounderClaimRefusal | CommercialPaymentRefusal | CitizenTransferRefusal | HandleChangeRefusal | HandleChangeReceiptReadRefusal | QuotePlacementRefusal | QuoteWithdrawalRefusal | BuyBackRefusal | MarketplaceReceiptReadRefusal | MarketplaceOrderRefusal | MarketplaceRefundRefusal | StandingAuthorisationRefusal | StandingAuthorisationRevocationRefusal | NodeBindingRefusal | NodeBindingQueryRefusal | SettlementAssertionRefusal;
187
258
  /**
188
259
  * The body of every refusal on this surface: one code, and nothing beside it.
189
260
  *
@@ -0,0 +1,189 @@
1
+ /**
2
+ * `handle-change` — a Citizen's Handle change, charged by Cayso, and the signed receipt
3
+ * Percayso ID relies on before it changes the Handle record (CAY-0091).
4
+ *
5
+ * Every Handle change after approval is charged in Cayso (Percayso ID's onboarding PRD
6
+ * §7.2). Cayso holds the price and makes the charge; Percayso ID changes the Handle only
7
+ * once Cayso has answered with a receipt. Served at `ROUTES.handleChange`, under the
8
+ * operation `'change-handle'`, and read back at `ROUTES.handleChangeReceipt`, under
9
+ * `'read-handle-change-receipt'`.
10
+ *
11
+ * ## Who calls it
12
+ *
13
+ * Percayso ID, over its back channel, as it presents a founder claim. The Citizen
14
+ * confirms on Percayso ID's own pages; Percayso ID mints a `change-handle` assertion for
15
+ * that interactive session — never from the background source (CAY-0070) — and presents
16
+ * it here. The assertion's `sub` is the Citizen ID.
17
+ *
18
+ * ## One `charge` for a Community service, or nothing
19
+ *
20
+ * The charge is one `charge` movement from the Citizen's own Citizen Wallet to the
21
+ * Organisation Wallet of the organisation that operates Percayso ID, named in Cayso's
22
+ * configuration — never a Citizen Wallet (CAY-0084). A Handle change is a Community
23
+ * service (CAY-0076, as extended by CAY-0091), and a `charge` may draw restricted lots
24
+ * like any charge, so restricted and unrestricted cents are drawn together. There is no
25
+ * sterling leg and so no lifecycle: the answer is a {@link HandleChangeCharged} carrying
26
+ * the signed receipt, or a {@link HandleChangeRefused} meaning nothing moved.
27
+ *
28
+ * ## Nothing in the request names anything
29
+ *
30
+ * There is no request body. The paying wallet is the verified subject's own Citizen
31
+ * Wallet, resolved inside the service (CAY-0021). The price is Cayso's configuration.
32
+ * The change reference — the single-use reference Percayso ID issued when it reserved
33
+ * the proposed Handle — is carried INSIDE the signed assertion, as
34
+ * `handleChangeReference`, because a reference named in a body would be the caller's
35
+ * claim about which Handle change is theirs. Cayso never learns the Handle.
36
+ *
37
+ * ## At most one charge per change reference
38
+ *
39
+ * The change reference is the charge's key. The first presentation charges; a later
40
+ * presentation of the same reference for the same Citizen, under a fresh assertion,
41
+ * charges nothing and answers the receipt of the charge already made — so Percayso ID,
42
+ * having had no response, retries with the same reference and is answered idempotently.
43
+ * A reference already charged to another wallet is refused. The same assertion
44
+ * presented twice never reaches this far: its `jti` is single-use, and the replay is
45
+ * refused at the gate.
46
+ *
47
+ * ## The receipt is a statement Cayso signs
48
+ *
49
+ * {@link HandleChangeReceipt} is a {@link HandleChangeReceiptStatement} and an `ES256`
50
+ * signature over {@link encodeHandleChangeReceiptStatement} of it, made with Cayso's
51
+ * receipt key (CAY-0083 §1, as amended by CAY-0091) and published in the same key set
52
+ * as a marketplace receipt's. It is BOUND to the charge: it names the change reference
53
+ * and the issuer and `jti` of the assertion the charge was made under, which Percayso ID
54
+ * minted and alone can tie to a Citizen. It names a wallet id and never a Percayso
55
+ * identity (CAY-0006, CAY-0054): there is no `sub` and no Handle.
56
+ *
57
+ * ## Was this reference charged? A receipt or "no charge", never "pending"
58
+ *
59
+ * {@link HandleChangeReceiptReadResponse} answers the read Percayso ID makes before it
60
+ * releases a held Handle: the receipt of the charge the reference landed, or
61
+ * `no-charge` — nothing was charged under this reference for this Citizen. There is no
62
+ * `pending`: a movement is written or it is not (CAY-0023). A read writes no row and
63
+ * moves nothing.
64
+ *
65
+ * ## The bytes that are signed, and why they cannot be a marketplace receipt
66
+ *
67
+ * {@link encodeHandleChangeReceiptStatement} is the one encoding, called by the signer
68
+ * and by every verifier: the statement's fields in the order the interface declares
69
+ * them, as UTF-8 JSON with no whitespace, refusing any field it does not name. Its first
70
+ * field is `"reason":"handle-change"`, and no marketplace receipt has a `reason` field —
71
+ * that encoder refuses one — so the one key signing both cannot make either read as the
72
+ * other.
73
+ *
74
+ * ## What is not here
75
+ *
76
+ * No figure: the price is a canon figure, configured, and the receipt carries the cents
77
+ * that moved. No key material and no verifier: which keys Percayso ID trusts is Percayso
78
+ * ID's configuration, empty by default.
79
+ */
80
+ import type { MarketplaceReceiptKeyId, MarketplaceReceiptLeg } from './marketplace-receipt.js';
81
+ import type { Millis } from './wallet.js';
82
+ /**
83
+ * What Cayso signs about one Handle-change charge. Every field is signed, including
84
+ * `keyId`, so which key signed is part of what is signed.
85
+ */
86
+ export interface HandleChangeReceiptStatement {
87
+ /** The reason for the charge. Always the literal, and always first in the encoding. */
88
+ readonly reason: 'handle-change';
89
+ /** The act: one `charge`, from the payer to the payee. */
90
+ readonly movementKind: 'charge';
91
+ /** The movement that carried the cents. */
92
+ readonly movementId: string;
93
+ /** The change reference charged for, exactly as Percayso ID minted it into the assertion. */
94
+ readonly handleChangeReference: string;
95
+ /** The issuer of the assertion the charge was made under. */
96
+ readonly assertionIssuer: string;
97
+ /** The `jti` of the assertion the charge was made under. */
98
+ readonly assertionId: string;
99
+ /** The paying wallet: the Citizen's own Citizen Wallet. */
100
+ readonly payerWalletId: string;
101
+ /** The whole price, to the configured Organisation Wallet, as the cents that moved. */
102
+ readonly payeeLeg: MarketplaceReceiptLeg;
103
+ /** When the movement was written. */
104
+ readonly writtenAt: Millis;
105
+ /** The receipt key the signature was made with. */
106
+ readonly keyId: MarketplaceReceiptKeyId;
107
+ }
108
+ /** A receipt: the statement, and Cayso's signature over its encoding. */
109
+ export interface HandleChangeReceipt {
110
+ readonly statement: HandleChangeReceiptStatement;
111
+ /**
112
+ * `ES256` over {@link encodeHandleChangeReceiptStatement}`(statement)`: `r || s`, 64
113
+ * bytes, as unpadded base64url.
114
+ */
115
+ readonly signature: string;
116
+ }
117
+ /** The Handle change was charged, by this request or by an earlier one for the same reference. */
118
+ export interface HandleChangeCharged {
119
+ readonly outcome: 'charged';
120
+ readonly receipt: HandleChangeReceipt;
121
+ }
122
+ /** The charge was refused, with one member of the closed union. Nothing was written. */
123
+ export interface HandleChangeRefused {
124
+ readonly outcome: 'refused';
125
+ readonly error: HandleChangeRefusal;
126
+ }
127
+ /** The ONE declared answer to a Handle change, discriminated by `outcome`. */
128
+ export type HandleChangeResponse = HandleChangeCharged | HandleChangeRefused;
129
+ /**
130
+ * Why a Handle change was refused: CAY-0091's set, closed. Every member means the same
131
+ * thing about money: nothing moved.
132
+ */
133
+ export type HandleChangeRefusal =
134
+ /**
135
+ * The verification method is outside the money-grade assurance profile
136
+ * (`ASSURANCE_POLICY['change-handle']`). `dev-bypass` is never inside it.
137
+ */
138
+ 'assurance_not_money_grade'
139
+ /** The verified subject resolves to no Citizen Wallet. A Handle change never provisions one. */
140
+ | 'payer_has_no_citizen_wallet'
141
+ /** The payer's cents, restricted and unrestricted together, are short of the price. */
142
+ | 'cents_insufficient'
143
+ /** A holding the charge would draw is frozen. */
144
+ | 'cents_frozen'
145
+ /** The change reference has already been charged, to another wallet. */
146
+ | 'handle_change_reference_charged_to_another_wallet'
147
+ /** Too many concurrent draws on the paying wallet. Nothing moved; retry with the same reference. */
148
+ | 'carve_contended';
149
+ /** The reference was charged for this Citizen: the receipt of that charge. */
150
+ export interface HandleChangeReceiptFound {
151
+ readonly outcome: 'receipt';
152
+ readonly receipt: HandleChangeReceipt;
153
+ }
154
+ /**
155
+ * Nothing was charged under this reference for this Citizen. Never "pending": there is
156
+ * no pending charge.
157
+ */
158
+ export interface HandleChangeNoCharge {
159
+ readonly outcome: 'no-charge';
160
+ }
161
+ /**
162
+ * Why the read could not be answered. Closed, and a refusal is never a statement about
163
+ * the reference: a caller must not read one as "no charge".
164
+ */
165
+ export type HandleChangeReceiptReadRefusal =
166
+ /**
167
+ * No wallet is bound to the verified subject now, so there is no paying wallet to ask
168
+ * about, and whether the reference was charged is not known.
169
+ */
170
+ 'payer_has_no_citizen_wallet'
171
+ /** The reference was charged, to another wallet. */
172
+ | 'handle_change_reference_charged_to_another_wallet';
173
+ /** The read was refused, with one reason. Nothing was written. */
174
+ export interface HandleChangeReceiptReadRefused {
175
+ readonly outcome: 'refused';
176
+ readonly error: HandleChangeReceiptReadRefusal;
177
+ }
178
+ /** The ONE declared answer to the read: a receipt, "no charge", or a refusal. Never "pending". */
179
+ export type HandleChangeReceiptReadResponse = HandleChangeReceiptFound | HandleChangeNoCharge | HandleChangeReceiptReadRefused;
180
+ /**
181
+ * The exact bytes a Handle-change receipt's signature is computed over.
182
+ *
183
+ * Builds a fresh object from the statement's named fields, in a fixed order, so the
184
+ * encoding depends on nothing but their values. THROWS a `TypeError` for anything that
185
+ * is not exactly a {@link HandleChangeReceiptStatement}: a wrong literal, a missing or
186
+ * extra field, a string field that is not a string, or cents or a time that is not a
187
+ * safe whole number no less than zero.
188
+ */
189
+ export declare function encodeHandleChangeReceiptStatement(statement: HandleChangeReceiptStatement): Uint8Array<ArrayBuffer>;
@@ -0,0 +1,96 @@
1
+ /*
2
+ * Copyright 2026 Percayso Community
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ // --- The encoding ------------------------------------------------------------
17
+ /** The statement's own fields, in the order they are encoded. */
18
+ const FIELDS = [
19
+ 'reason',
20
+ 'movementKind',
21
+ 'movementId',
22
+ 'handleChangeReference',
23
+ 'assertionIssuer',
24
+ 'assertionId',
25
+ 'payerWalletId',
26
+ 'payeeLeg',
27
+ 'writtenAt',
28
+ 'keyId',
29
+ ];
30
+ /** Every string field, each of which must be a string when it arrives. */
31
+ const STRING_FIELDS = [
32
+ 'movementId',
33
+ 'handleChangeReference',
34
+ 'assertionIssuer',
35
+ 'assertionId',
36
+ 'payerWalletId',
37
+ 'keyId',
38
+ ];
39
+ /** The fields of a leg, in the order they are encoded. */
40
+ const LEG_FIELDS = ['walletId', 'cents'];
41
+ /**
42
+ * The exact bytes a Handle-change receipt's signature is computed over.
43
+ *
44
+ * Builds a fresh object from the statement's named fields, in a fixed order, so the
45
+ * encoding depends on nothing but their values. THROWS a `TypeError` for anything that
46
+ * is not exactly a {@link HandleChangeReceiptStatement}: a wrong literal, a missing or
47
+ * extra field, a string field that is not a string, or cents or a time that is not a
48
+ * safe whole number no less than zero.
49
+ */
50
+ export function encodeHandleChangeReceiptStatement(statement) {
51
+ const value = statement;
52
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
53
+ throw new TypeError('a Handle-change receipt statement is an object');
54
+ }
55
+ requireExactly(value, FIELDS, 'a Handle-change receipt carries exactly its own fields');
56
+ if (value['reason'] !== 'handle-change' || value['movementKind'] !== 'charge') {
57
+ throw new TypeError('a Handle-change receipt is for a Handle change made by a charge');
58
+ }
59
+ for (const field of STRING_FIELDS) {
60
+ if (typeof value[field] !== 'string') {
61
+ throw new TypeError('every identifier of a Handle-change receipt is a string');
62
+ }
63
+ }
64
+ requireWholeNumber(value['writtenAt'], 'a Handle-change receipt is written at whole milliseconds');
65
+ const canonical = {};
66
+ for (const field of FIELDS) {
67
+ canonical[field] = field === 'payeeLeg' ? canonicalLeg(value[field]) : value[field];
68
+ }
69
+ return new TextEncoder().encode(JSON.stringify(canonical));
70
+ }
71
+ /** A leg rebuilt in its fixed order, or a refusal. */
72
+ function canonicalLeg(leg) {
73
+ if (typeof leg !== 'object' || leg === null || Array.isArray(leg)) {
74
+ throw new TypeError('a Handle-change receipt leg is an object');
75
+ }
76
+ const value = leg;
77
+ requireExactly(value, LEG_FIELDS, 'a Handle-change receipt leg carries a wallet id and cents only');
78
+ if (typeof value['walletId'] !== 'string') {
79
+ throw new TypeError('a Handle-change receipt leg names its wallet by id');
80
+ }
81
+ requireWholeNumber(value['cents'], 'a Handle-change receipt leg carries whole cents');
82
+ return { walletId: value['walletId'], cents: value['cents'] };
83
+ }
84
+ /** Refuse an object whose own keys are not exactly `fields`. */
85
+ function requireExactly(value, fields, category) {
86
+ const keys = Object.keys(value);
87
+ if (keys.length !== fields.length || !fields.every((field) => Object.hasOwn(value, field))) {
88
+ throw new TypeError(category);
89
+ }
90
+ }
91
+ /** Refuse anything that is not a safe whole number no less than zero. */
92
+ function requireWholeNumber(value, category) {
93
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
94
+ throw new TypeError(category);
95
+ }
96
+ }
package/dist/index.d.ts CHANGED
@@ -76,6 +76,94 @@
76
76
  * this money surface gains that Piper's own contracts lack, since theirs share
77
77
  * one global version bumped across all twenty-two together (CAY-0026).
78
78
  *
79
+ * `0.29.0` → `0.30.0` publishes and SERVES Cayso's authorisation acknowledgement keys
80
+ * (CAY-0093): {@link ACKNOWLEDGEMENT_KEYS_ROUTE}, `GET /api/acknowledgement-keys`, an
81
+ * unauthenticated read outside `ROUTES`, described in the schema under `keyRoutes`;
82
+ * the key set it answers, {@link AcknowledgementKeySet} of
83
+ * {@link AcknowledgementPublicKey}, Ed25519 public JSON Web Keys and nothing private;
84
+ * and `CaysoApiErrorCode` gains `acknowledgement_signing_not_configured`, the route's
85
+ * closed door.
86
+ *
87
+ * The same version SERVES the standing authorisation (CAY-0094), published at `0.25.0`
88
+ * and answered until now by the router's `404`: `ROUTES.standingAuthorisation` answers
89
+ * {@link StandingAuthorisationResponse} with an acknowledgement signed under that key.
90
+ * It adds the owner's way to withdraw one: `ROUTES.revokeStandingAuthorisation`,
91
+ * `POST /api/cloud/standing-authorisation-revocations`, mapped to the new operation
92
+ * `'revoke-standing-authorisation'`, money-grade in `ASSURANCE_POLICY`; the client
93
+ * method `revokeStandingAuthorisation`; {@link StandingAuthorisationRevocationRequest},
94
+ * {@link StandingAuthorisationRevocationResponse} and the closed
95
+ * {@link StandingAuthorisationRevocationRefusal}, which `CaysoApiErrorCode` gains by
96
+ * reference; and the seam codes `standing_authorisation_store_not_configured`,
97
+ * `standing_authorisation_cap_ceiling_not_configured` and
98
+ * `standing_authorisation_life_ceiling_not_configured`.
99
+ *
100
+ * The same version publishes and SERVES binding a Node to a wallet (CMTY-0018 §4,
101
+ * CAY-0095): `ROUTES.bindNode`, `POST /api/cloud/node-bindings`, mapped to the new
102
+ * operation `'bind-node'`, money-grade in `ASSURANCE_POLICY`; the client method
103
+ * `bindNode`; {@link NodePresentationClaims}, {@link NodeBindingRequest},
104
+ * {@link NodeBindingResponse} and the closed {@link NodeBindingRefusal}. Beside it, the
105
+ * Contribution Store's read of whether a Node is bound: {@link NODE_BINDING_QUERY_ROUTE},
106
+ * `POST /api/cloud/node-binding-queries`, outside `ROUTES` and in the schema under
107
+ * `issuerRoutes`, authenticated by the registered Store issuer; {@link
108
+ * NodeBindingQueryClaims}, {@link NodeBindingQueryRequest}, the answer
109
+ * {@link NodeBindingStatus} — `nodeId` and `bound` and nothing else — and the closed
110
+ * {@link NodeBindingQueryRefusal}. `CaysoApiErrorCode` gains both unions by reference
111
+ * and the seam codes `node_binding_store_not_configured`, `core_node_ids_not_configured`
112
+ * and `contribution_store_issuer_not_configured`.
113
+ *
114
+ * The same version SERVES the Contribution Store's settlement assertion (CMTY-0018 §2,
115
+ * CAY-0096) at {@link CLOUD_SETTLEMENT_ROUTE}, published at `0.25.0` and answered until
116
+ * now by the router's `404`. A settled period writes one `contribution_settlement`
117
+ * movement per paid contribution row and one `consumption_settlement` per consumption
118
+ * row, so `MovementKind` and `MOVEMENT_KINDS` gain both. The closed refusal unions gain
119
+ * the members the write needs: {@link SettlementAssertionLevelRefusal} gains
120
+ * `settlement_period_not_recognised`, `settlement_period_not_ended` and
121
+ * `settlement_carve_contended`; {@link ContributionRowRefusal} gains
122
+ * `contribution_node_is_a_core_node` and `contribution_treasury_short`;
123
+ * {@link ConsumptionRowRefusal} gains `consumption_authorisation_not_in_force` and
124
+ * `consumption_wallet_short`. `CaysoApiErrorCode` gains them by reference and the seam
125
+ * code `cloud_settlement_store_not_configured`.
126
+ *
127
+ * BREAKING in the package's sense because closed tables grew: `ROUTES`,
128
+ * `ContractOperation`, `CaysoApiErrorCode`, `MovementKind` and the settlement's refusal
129
+ * unions. Additive on the wire (CAY-0086): no route a `0.29.0` consumer could reach
130
+ * changed, because the only ones that answer differently are the standing
131
+ * authorisation and the settlement assertion, which no deployment served before, and
132
+ * they answer the shapes `0.25.0` published, a member those shapes' unions gained, or a
133
+ * new seam code no served route emits. The operator movement list can now carry the two
134
+ * new kinds, and it is read only by the admin app in this tree, released with it. The
135
+ * two Node routes are ones a `0.29.0` consumer cannot name.
136
+ *
137
+ * `0.28.0` → `0.29.0` publishes and SERVES the Handle change (CAY-0091):
138
+ * `ROUTES.handleChange`, `POST /api/handle-changes`, mapped to the new operation
139
+ * `'change-handle'`, money-grade in `ASSURANCE_POLICY`; `ROUTES.handleChangeReceipt`,
140
+ * `GET /api/handle-changes/receipt`, mapped to the new read-scope operation
141
+ * `'read-handle-change-receipt'`; the assertion claim `handleChangeReference`, which
142
+ * travels with those two operations in both directions; the client methods
143
+ * `changeHandle` and `readHandleChangeReceipt`; the signed {@link HandleChangeReceipt}
144
+ * and its one encoding, {@link encodeHandleChangeReceiptStatement}; and
145
+ * `CaysoApiErrorCode` gains {@link HandleChangeRefusal} and
146
+ * {@link HandleChangeReceiptReadRefusal} by reference and the seam codes
147
+ * `handle_change_store_not_configured`, `handle_change_price_not_configured` and
148
+ * `handle_change_payee_not_configured`. BREAKING in the package's sense because closed
149
+ * tables grew. Additive on the wire: no route a `0.28.0` consumer calls changed or
150
+ * answers anything new, and a credential a `0.28.0` issuer mints carries neither the new
151
+ * scope keys nor the new claim (CAY-0086).
152
+ *
153
+ * `0.27.0` → `0.28.0` SERVES a Citizen publisher's marketplace sale (CAY-0090):
154
+ * `POST /api/marketplace/orders` settles a signed order whose payee is a
155
+ * `citizen_publisher` as one `marketplace_settlement`, answering the
156
+ * `MarketplaceSettlementReceiptStatement` `0.24.0` already published. The share is
157
+ * read from a new signed-order fact, `communityShareBasisPoints`, which Store Platform
158
+ * signs beside `allocationPolicyVersion`. {@link MarketplaceOrderRefusal} gains
159
+ * `allocation_share_out_of_range` and `payee_wallet_is_the_buyers`, and
160
+ * `allocation_policy_version_not_configured` is retired (kept, never answered). The
161
+ * operator `MovementKind` gains `marketplace_settlement`. BREAKING in the package's
162
+ * sense because closed tables grew. On the wire, every order a `0.27.0` consumer could
163
+ * present — one Store Platform signed without the new fact — is answered exactly as
164
+ * before, a Citizen publisher's with `third_party_marketplace_sale_not_served`; only an
165
+ * order carrying the new fact can reach a new code (CAY-0086).
166
+ *
79
167
  * `0.26.0` → `0.27.0` publishes and SERVES the Citizen transfer (CAY-0088):
80
168
  * `ROUTES.citizenTransfer`, `POST /api/citizen-transfers`, mapped to the new
81
169
  * operation `'make-citizen-transfer'`, money-grade in `ASSURANCE_POLICY`; the client
@@ -522,7 +610,7 @@
522
610
  * have needed a breaking bump on their own. Under semver below `1.0.0` the minor
523
611
  * is where a breaking change goes, so the minor moves and the patch does not.
524
612
  */
525
- export declare const CONTRACT_VERSION: "0.27.0";
613
+ export declare const CONTRACT_VERSION: "0.30.0";
526
614
  /** The package's own name, so a consumer can name what it depends on. */
527
615
  export declare const packageName = "@percayso-community/cayso-contracts";
528
616
  /**
@@ -546,6 +634,18 @@ export { ROUTES } from './routes.js';
546
634
  * no operation, no assurance bar and no client method.
547
635
  */
548
636
  export { CLOUD_SETTLEMENT_ROUTE } from './routes.js';
637
+ /**
638
+ * Where the Contribution Store asks whether a Node is bound (CAY-0095). A value beside
639
+ * `ROUTES` and never in it, for the settlement path's reason: it is authenticated by
640
+ * the registered Store issuer, not by a person.
641
+ */
642
+ export { NODE_BINDING_QUERY_ROUTE } from './routes.js';
643
+ /**
644
+ * Where Cayso publishes its authorisation acknowledgement keys (CAY-0093). A value
645
+ * beside `ROUTES` and never in it: an unauthenticated read of a public key carries no
646
+ * identity, so it has no operation, no assurance bar and no client method.
647
+ */
648
+ export { ACKNOWLEDGEMENT_KEYS_ROUTE } from './routes.js';
549
649
  /**
550
650
  * The purchase lifecycle's runtime half (CAY-0032): which statuses a purchase
551
651
  * never leaves, the predicate over them, and the window an authorisation holds its
@@ -656,6 +756,11 @@ export { REQUEST_RATE_LIMITED } from './errors.js';
656
756
  * one of the four.
657
757
  */
658
758
  export { MARKETPLACE_RECEIPT_SIGNATURE_ALGORITHM, encodeMarketplaceReceiptStatement, } from './marketplace-receipt.js';
759
+ /**
760
+ * The one encoding of a Handle-change receipt statement, called by the signer and by
761
+ * Percayso ID's verifier (CAY-0091).
762
+ */
763
+ export { encodeHandleChangeReceiptStatement } from './handle-change.js';
659
764
  export type { PositiveCents } from './money.js';
660
765
  export type { CaysoApiErrorCode, CaysoErrorResponse } from './errors.js';
661
766
  export type { HolderType, Millis, Cents, WalletRecord, Balance, Allowance, WalletView, CaysoWallet, } from './wallet.js';
@@ -663,10 +768,11 @@ export type { SignUpGrantTerms, SignUpGrant, CitizenshipNotProvisioned, Citizens
663
768
  export type { OrganisationView } from './organisation.js';
664
769
  export type { CommercialPaymentAuthority, CommercialPaymentRequest, CommercialPayment, CommercialPaymentMade, CommercialPaymentRefused, CommercialPaymentResponse, CommercialPaymentRefusal, } from './commercial-payment.js';
665
770
  export type { CitizenTransferRequest, CitizenTransfer, CitizenTransferMade, CitizenTransferRefused, CitizenTransferResponse, CitizenTransferRefusal, } from './citizen-transfer.js';
771
+ export type { HandleChangeReceiptStatement, HandleChangeReceipt, HandleChangeCharged, HandleChangeRefused, HandleChangeResponse, HandleChangeRefusal, HandleChangeReceiptFound, HandleChangeNoCharge, HandleChangeReceiptReadRefusal, HandleChangeReceiptReadRefused, HandleChangeReceiptReadResponse, } from './handle-change.js';
666
772
  export type { QuoteSide, QuoteRequest, Quote, QuotePlaced, QuoteRefused, QuoteResponse, QuoteEntryRefusal, QuotePlacementRefusal, QuoteWithdrawalRequest, QuoteWithdrawal, QuoteWithdrawn, QuoteWithdrawalRefused, QuoteWithdrawalResponse, QuoteWithdrawalRefusal, BuyBackRequest, BuyBack, BuyBackMade, BuyBackRefused, BuyBackResponse, BuyBackRefusal, BookLevel, QuoteStatus, QuoteWithdrawalReason, OwnQuote, OwnQuoteNotWithdrawn, OwnQuoteWithdrawn, CitizenMarketView, CitizenMarketViewed, CitizenMarketViewRefusal, CitizenMarketViewRefused, CitizenMarketResponse, } from './citizen-market.js';
667
773
  export type { MarketplaceReceiptSignatureAlgorithm, MarketplaceReceiptKeyId, MarketplaceSaleKind, MarketplaceReceiptLeg, MarketplaceSettlementReceiptStatement, HousePublisherChargeReceiptStatement, ThirdPartyRefundReceiptStatement, HousePublisherRefundReceiptStatement, MarketplaceReceiptStatement, MarketplaceReceipt, MarketplaceReceiptReadRequest, MarketplaceReceiptFound, MarketplaceNoMovement, MarketplaceReceiptReadRefusal, MarketplaceReceiptReadRefused, MarketplaceReceiptReadResponse, } from './marketplace-receipt.js';
668
774
  export type { StoreSignedStatement, MarketplaceOrderRequest, MarketplaceRefundRequest, MarketplaceOrderReceipt, MarketplaceRefundReceipt, MarketplaceOrderSettled, MarketplaceOrderRefused, MarketplaceOrderResponse, MarketplaceOrderRefusal, MarketplaceRefundSettled, MarketplaceRefundRefused, MarketplaceRefundResponse, MarketplaceRefundRefusal, } from './marketplace-settlement.js';
669
- export type { InstanceKeyId, SettlementPeriodRule, SettlementPeriodId, NodeId, ContributionStoreIssuer, PercaysoCloudAudience, StandingAuthorisationClaims, StandingAuthorisationRequest, AuthorisationAcknowledgementClaims, StandingAuthorisationAcknowledged, StandingAuthorisationRefused, StandingAuthorisationResponse, StandingAuthorisationRefusal, ContributionType, SettlementPeriod, ContributionWithheldReason, ContributionQualified, ContributionWithheld, ContributionQualification, ContributionRow, ConsumptionRow, SettlementTotals, SettlementAssertionClaims, SettlementAssertionRequest, SettlementAssertionSettled, SettlementAssertionRefused, ContributionRowRefused, ConsumptionRowRefused, SettlementAssertionResponse, SettlementAssertionLevelRefusal, ContributionRowRefusal, ConsumptionRowRefusal, SettlementAssertionRefusal, } from './cloud-settlement.js';
775
+ export type { InstanceKeyId, SettlementPeriodRule, SettlementPeriodId, NodeId, ContributionStoreIssuer, PercaysoCloudAudience, StandingAuthorisationClaims, StandingAuthorisationRequest, AuthorisationAcknowledgementClaims, AcknowledgementKeyId, AcknowledgementPublicKey, AcknowledgementKeySet, StandingAuthorisationAcknowledged, StandingAuthorisationRefused, StandingAuthorisationResponse, StandingAuthorisationRefusal, StandingAuthorisationRevocationRequest, StandingAuthorisationRevoked, StandingAuthorisationRevocationRefused, StandingAuthorisationRevocationResponse, StandingAuthorisationRevocationRefusal, NodePresentationClaims, NodeBindingRequest, NodeBound, NodeBindingRefused, NodeBindingResponse, NodeBindingRefusal, NodeBindingQueryClaims, NodeBindingQueryRequest, NodeBindingStatus, NodeBindingQueryRefused, NodeBindingQueryRefusal, ContributionType, SettlementPeriod, ContributionWithheldReason, ContributionQualified, ContributionWithheld, ContributionQualification, ContributionRow, ConsumptionRow, SettlementTotals, SettlementAssertionClaims, SettlementAssertionRequest, SettlementAssertionSettled, SettlementAssertionRefused, ContributionRowRefused, ConsumptionRowRefused, SettlementAssertionResponse, SettlementAssertionLevelRefusal, ContributionRowRefusal, ConsumptionRowRefusal, SettlementAssertionRefusal, } from './cloud-settlement.js';
670
776
  export type { PurchaseRequest, PurchaseAuthorised, PurchaseTerminal, PurchaseUnresolved, PurchaseRefused, PurchaseAuthorisationResponse, PurchaseFailureReason, PurchaseStatus, LivePurchaseStatus, TerminalPurchaseStatus, PurchaseCancelRefusalReason, PurchaseCancelled, PurchaseCancelRefused, PurchaseCancelResponse, PurchaseResult, } from './purchase.js';
671
777
  export type { VerificationMethod, VerificationStatus, SubjectPersonhood, AssertionClaims, AssertionHeader, AssertionEnvelope, ContractOperation, InternalOperation, ScopeKey, } from './assertion.js';
672
778
  export type { VerificationEvidence, EvidenceStatement, MethodDecision, MethodDecisions, AssuranceRequired, AssuranceNotRequired, OperationAssurance, AssuranceRefusalReason, AssuranceAssessment, } from './assurance.js';