@percayso-community/cayso-contracts 0.24.0 → 0.26.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
@@ -39,10 +39,11 @@
39
39
  * to the unions that own them, so neither can grow a member this union does not
40
40
  * carry. The founder claim's refusals are included the same way, and so are the
41
41
  * commercial payment's, the citizen market's, the marketplace status read's and the
42
- * two marketplace settlements'.
42
+ * two marketplace settlements', and the Percayso Cloud's two seams'.
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
47
  import type { CommercialPaymentRefusal } from './commercial-payment.js';
47
48
  import type { MarketplaceReceiptReadRefusal } from './marketplace-receipt.js';
48
49
  import type { MarketplaceOrderRefusal, MarketplaceRefundRefusal } from './marketplace-settlement.js';
@@ -175,7 +176,7 @@ export type CaysoApiErrorCode =
175
176
  /** There is no such purchase under this caller's wallet. */
176
177
  | 'not_found'
177
178
  /** Something failed on the way and the refusal discloses nothing further. */
178
- | 'internal_error' | PurchaseFailureReason | PurchaseCancelRefusalReason | FounderClaimRefusal | CommercialPaymentRefusal | QuotePlacementRefusal | QuoteWithdrawalRefusal | BuyBackRefusal | MarketplaceReceiptReadRefusal | MarketplaceOrderRefusal | MarketplaceRefundRefusal;
179
+ | 'internal_error' | PurchaseFailureReason | PurchaseCancelRefusalReason | FounderClaimRefusal | CommercialPaymentRefusal | QuotePlacementRefusal | QuoteWithdrawalRefusal | BuyBackRefusal | MarketplaceReceiptReadRefusal | MarketplaceOrderRefusal | MarketplaceRefundRefusal | StandingAuthorisationRefusal | SettlementAssertionRefusal;
179
180
  /**
180
181
  * The body of every refusal on this surface: one code, and nothing beside it.
181
182
  *
package/dist/index.d.ts CHANGED
@@ -57,8 +57,13 @@
57
57
  * same cents. It is compile-time data with no side effects, and it enforces
58
58
  * nothing.
59
59
  *
60
- * This is the *Piper-facing surface only*. Peer types, admin types, holdings and
61
- * carves are deliberately not exported here; they are not a consumer's business.
60
+ * This is the surface of every consumer outside this tree (CAY-0026, Amendment 3):
61
+ * Piper first, and the Percayso Cloud second, whose two seams with Cayso arrive from
62
+ * `cloud-settlement`. Peer types, admin types, holdings and carves are deliberately
63
+ * not exported here; they are not a consumer's business. The three operator reads an
64
+ * operator app's server calls are published, but on their own entry point,
65
+ * `@percayso-community/cayso-contracts/operator` (CAY-0026, Amendment 4), and nothing
66
+ * here re-exports them: none of this barrel's consumers is an operator.
62
67
  * And it carries **no numbers** — amounts, rates, tiers, schedules and thresholds
63
68
  * live in the canon PRD and are read from one place, never restated here.
64
69
  */
@@ -71,6 +76,28 @@
71
76
  * this money surface gains that Piper's own contracts lack, since theirs share
72
77
  * one global version bumped across all twenty-two together (CAY-0026).
73
78
  *
79
+ * `0.25.0` → `0.26.0` publishes the operator read surface on its own entry point,
80
+ * `@percayso-community/cayso-contracts/operator` (CAY-0026 Amendment 4), and describes
81
+ * it in the schema under `operator`: the movement list, the purchase list and the
82
+ * quickening ladder, with their scopes, query inputs, rows, pages and closed refusal
83
+ * bodies. Nothing new is served — the three routes answered these shapes already —
84
+ * and nothing in this barrel changed, so no closed table grew: `ROUTES`,
85
+ * `ContractOperation` and `CaysoApiErrorCode` are as `0.25.0` published them. It is
86
+ * additive in the package's sense and on the wire (CAY-0086).
87
+ *
88
+ * `0.24.0` → `0.25.0` publishes the Percayso Cloud's two seams with Cayso (CMTY-0018
89
+ * §3) and serves neither. `ROUTES` gains `standingAuthorisation`, where an Instance
90
+ * presents its owner's standing authorisation under the owner's assertion, with the
91
+ * client method `presentStandingAuthorisation`; the Contribution Store's settlement
92
+ * path is published as {@link CLOUD_SETTLEMENT_ROUTE}, outside `ROUTES`, and in the
93
+ * schema under `issuerRoutes`. The claim types of both documents and of Cayso's
94
+ * acknowledgement arrive from `cloud-settlement`, carrying no Instance ID (CAY-0059
95
+ * §6) and no figure. It is BREAKING in the package's sense because three closed
96
+ * tables grew: `ROUTES`, `ContractOperation` (with `'present-standing-authorisation'`,
97
+ * money-grade in `ASSURANCE_POLICY`) and `CaysoApiErrorCode`, which gains the two
98
+ * seams' refusal unions by reference. It is additive on the wire: no route a
99
+ * `0.24.0` consumer calls changed or answers anything new (CAY-0086).
100
+ *
74
101
  * `0.23.0` → `0.24.0` SERVES `settle-marketplace-order` for a house-publisher sale
75
102
  * at `ROUTES.marketplaceOrder` (CAY-0082 §2, CAY-0083 §3), with the client method
76
103
  * `settleMarketplaceOrder` and three seam codes: `marketplace_order_keys_not_configured`,
@@ -486,7 +513,7 @@
486
513
  * have needed a breaking bump on their own. Under semver below `1.0.0` the minor
487
514
  * is where a breaking change goes, so the minor moves and the patch does not.
488
515
  */
489
- export declare const CONTRACT_VERSION: "0.24.0";
516
+ export declare const CONTRACT_VERSION: "0.26.0";
490
517
  /** The package's own name, so a consumer can name what it depends on. */
491
518
  export declare const packageName = "@percayso-community/cayso-contracts";
492
519
  /**
@@ -503,6 +530,13 @@ export { WALLET_CAPABILITY } from './wallet.js';
503
530
  */
504
531
  export { PURCHASE_CAPABILITY } from './purchase.js';
505
532
  export { ROUTES } from './routes.js';
533
+ /**
534
+ * Where the Percayso Cloud's Contribution Store presents a settlement assertion
535
+ * (CMTY-0018 §2). A value beside `ROUTES` and never in it: the path is
536
+ * authenticated by a registered Store issuer (CAY-0030), not by a person, so it has
537
+ * no operation, no assurance bar and no client method.
538
+ */
539
+ export { CLOUD_SETTLEMENT_ROUTE } from './routes.js';
506
540
  /**
507
541
  * The purchase lifecycle's runtime half (CAY-0032): which statuses a purchase
508
542
  * never leaves, the predicate over them, and the window an authorisation holds its
@@ -622,6 +656,7 @@ export type { CommercialPaymentAuthority, CommercialPaymentRequest, CommercialPa
622
656
  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';
623
657
  export type { MarketplaceReceiptSignatureAlgorithm, MarketplaceReceiptKeyId, MarketplaceSaleKind, MarketplaceReceiptLeg, MarketplaceSettlementReceiptStatement, HousePublisherChargeReceiptStatement, ThirdPartyRefundReceiptStatement, HousePublisherRefundReceiptStatement, MarketplaceReceiptStatement, MarketplaceReceipt, MarketplaceReceiptReadRequest, MarketplaceReceiptFound, MarketplaceNoMovement, MarketplaceReceiptReadRefusal, MarketplaceReceiptReadRefused, MarketplaceReceiptReadResponse, } from './marketplace-receipt.js';
624
658
  export type { StoreSignedStatement, MarketplaceOrderRequest, MarketplaceRefundRequest, MarketplaceOrderReceipt, MarketplaceRefundReceipt, MarketplaceOrderSettled, MarketplaceOrderRefused, MarketplaceOrderResponse, MarketplaceOrderRefusal, MarketplaceRefundSettled, MarketplaceRefundRefused, MarketplaceRefundResponse, MarketplaceRefundRefusal, } from './marketplace-settlement.js';
659
+ 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';
625
660
  export type { PurchaseRequest, PurchaseAuthorised, PurchaseTerminal, PurchaseUnresolved, PurchaseRefused, PurchaseAuthorisationResponse, PurchaseFailureReason, PurchaseStatus, LivePurchaseStatus, TerminalPurchaseStatus, PurchaseCancelRefusalReason, PurchaseCancelled, PurchaseCancelRefused, PurchaseCancelResponse, PurchaseResult, } from './purchase.js';
626
661
  export type { VerificationMethod, VerificationStatus, SubjectPersonhood, AssertionClaims, AssertionHeader, AssertionEnvelope, ContractOperation, InternalOperation, ScopeKey, } from './assertion.js';
627
662
  export type { VerificationEvidence, EvidenceStatement, MethodDecision, MethodDecisions, AssuranceRequired, AssuranceNotRequired, OperationAssurance, AssuranceRefusalReason, AssuranceAssessment, } from './assurance.js';
package/dist/index.js CHANGED
@@ -72,8 +72,13 @@
72
72
  * same cents. It is compile-time data with no side effects, and it enforces
73
73
  * nothing.
74
74
  *
75
- * This is the *Piper-facing surface only*. Peer types, admin types, holdings and
76
- * carves are deliberately not exported here; they are not a consumer's business.
75
+ * This is the surface of every consumer outside this tree (CAY-0026, Amendment 3):
76
+ * Piper first, and the Percayso Cloud second, whose two seams with Cayso arrive from
77
+ * `cloud-settlement`. Peer types, admin types, holdings and carves are deliberately
78
+ * not exported here; they are not a consumer's business. The three operator reads an
79
+ * operator app's server calls are published, but on their own entry point,
80
+ * `@percayso-community/cayso-contracts/operator` (CAY-0026, Amendment 4), and nothing
81
+ * here re-exports them: none of this barrel's consumers is an operator.
77
82
  * And it carries **no numbers** — amounts, rates, tiers, schedules and thresholds
78
83
  * live in the canon PRD and are read from one place, never restated here.
79
84
  */
@@ -87,6 +92,28 @@
87
92
  * this money surface gains that Piper's own contracts lack, since theirs share
88
93
  * one global version bumped across all twenty-two together (CAY-0026).
89
94
  *
95
+ * `0.25.0` → `0.26.0` publishes the operator read surface on its own entry point,
96
+ * `@percayso-community/cayso-contracts/operator` (CAY-0026 Amendment 4), and describes
97
+ * it in the schema under `operator`: the movement list, the purchase list and the
98
+ * quickening ladder, with their scopes, query inputs, rows, pages and closed refusal
99
+ * bodies. Nothing new is served — the three routes answered these shapes already —
100
+ * and nothing in this barrel changed, so no closed table grew: `ROUTES`,
101
+ * `ContractOperation` and `CaysoApiErrorCode` are as `0.25.0` published them. It is
102
+ * additive in the package's sense and on the wire (CAY-0086).
103
+ *
104
+ * `0.24.0` → `0.25.0` publishes the Percayso Cloud's two seams with Cayso (CMTY-0018
105
+ * §3) and serves neither. `ROUTES` gains `standingAuthorisation`, where an Instance
106
+ * presents its owner's standing authorisation under the owner's assertion, with the
107
+ * client method `presentStandingAuthorisation`; the Contribution Store's settlement
108
+ * path is published as {@link CLOUD_SETTLEMENT_ROUTE}, outside `ROUTES`, and in the
109
+ * schema under `issuerRoutes`. The claim types of both documents and of Cayso's
110
+ * acknowledgement arrive from `cloud-settlement`, carrying no Instance ID (CAY-0059
111
+ * §6) and no figure. It is BREAKING in the package's sense because three closed
112
+ * tables grew: `ROUTES`, `ContractOperation` (with `'present-standing-authorisation'`,
113
+ * money-grade in `ASSURANCE_POLICY`) and `CaysoApiErrorCode`, which gains the two
114
+ * seams' refusal unions by reference. It is additive on the wire: no route a
115
+ * `0.24.0` consumer calls changed or answers anything new (CAY-0086).
116
+ *
90
117
  * `0.23.0` → `0.24.0` SERVES `settle-marketplace-order` for a house-publisher sale
91
118
  * at `ROUTES.marketplaceOrder` (CAY-0082 §2, CAY-0083 §3), with the client method
92
119
  * `settleMarketplaceOrder` and three seam codes: `marketplace_order_keys_not_configured`,
@@ -502,7 +529,7 @@
502
529
  * have needed a breaking bump on their own. Under semver below `1.0.0` the minor
503
530
  * is where a breaking change goes, so the minor moves and the patch does not.
504
531
  */
505
- export const CONTRACT_VERSION = '0.24.0';
532
+ export const CONTRACT_VERSION = '0.26.0';
506
533
  /** The package's own name, so a consumer can name what it depends on. */
507
534
  export const packageName = '@percayso-community/cayso-contracts';
508
535
  /**
@@ -519,6 +546,13 @@ export { WALLET_CAPABILITY } from './wallet.js';
519
546
  */
520
547
  export { PURCHASE_CAPABILITY } from './purchase.js';
521
548
  export { ROUTES } from './routes.js';
549
+ /**
550
+ * Where the Percayso Cloud's Contribution Store presents a settlement assertion
551
+ * (CMTY-0018 §2). A value beside `ROUTES` and never in it: the path is
552
+ * authenticated by a registered Store issuer (CAY-0030), not by a person, so it has
553
+ * no operation, no assurance bar and no client method.
554
+ */
555
+ export { CLOUD_SETTLEMENT_ROUTE } from './routes.js';
522
556
  /**
523
557
  * The purchase lifecycle's runtime half (CAY-0032): which statuses a purchase
524
558
  * never leaves, the predicate over them, and the window an authorisation holds its
@@ -0,0 +1,298 @@
1
+ /**
2
+ * `@percayso-community/cayso-contracts/operator` — the operator READ surface, on its
3
+ * own entry point: three reads and nothing else (CAY-0026, Amendment 4).
4
+ *
5
+ * - `GET /api/operator/movements` — the movement list, under `list-movements-as-operator`.
6
+ * - `GET /api/operator/purchases` — the purchase list, under `list-purchases-as-operator`.
7
+ * - `GET /api/operator/quickenings` — the quickening ladder, under
8
+ * `read-quickening-ladder-as-operator`.
9
+ *
10
+ * ## Who calls this, and from where
11
+ *
12
+ * An operator app's SERVER. Cayso answers no browser: it serves no CORS headers and
13
+ * that does not change here, so a page that wants these reads asks its own server,
14
+ * and that server calls Cayso with an operator's minted assertion. Publishing the
15
+ * shapes lets that server type what it sends and what it is answered, instead of
16
+ * keeping a hand-copied mirror that drifts from the routes.
17
+ *
18
+ * ## Why its own entry point, and not the barrel
19
+ *
20
+ * `@percayso-community/cayso-contracts` is the surface Piper and the Percayso Cloud
21
+ * read. None of them is an operator, and none of them should be handed an operator
22
+ * vocabulary to grow a dependency on. So nothing here is re-exported from the barrel,
23
+ * and the schema describes it under its own key (`operator`), apart from the routes
24
+ * a person calls. A consumer that never imports this subpath never sees it.
25
+ *
26
+ * ## What it carries, and what it deliberately does not
27
+ *
28
+ * - **The three reads only.** The operator surface is larger than this — the wallet
29
+ * lookup, the resolver, the market alarms, the founder lapse — and all of it stays
30
+ * unpublished. Widening this entry point is a further amendment to CAY-0026, not
31
+ * an edit to this file.
32
+ * - **No peer, holdings or carve type.** A row here is a movement or a purchase as
33
+ * an operator LIST shows it, never a holding and never the carve that produced it.
34
+ * - **The wallet id is the handle.** No row carries a Percayso identity, an
35
+ * attribution or the acting party: an operator list must not be casually a
36
+ * directory of identities (CAY-0006).
37
+ * - **Money is {@link Cents}.** An integer count, never formatted; the ladder's
38
+ * `publishedValuePence` is a field read from the deployment, never a value fixed
39
+ * here.
40
+ * - **No numbers.** The page-size cap, the page-number cap and the wallet-id filter's
41
+ * length bound are the service's, and a consumer that copied them would hold a
42
+ * second home for each.
43
+ *
44
+ * ## The API is the source of truth
45
+ *
46
+ * Every shape here is the one `apps/api` serves, and a test in `apps/api` drives the
47
+ * three routes and fails on any field the service sends that this file does not
48
+ * describe. Where an earlier hand-written client disagreed with the service, the
49
+ * service won.
50
+ */
51
+ import type { PurchaseFailureReason, PurchaseStatus } from './purchase.js';
52
+ import type { Cents } from './wallet.js';
53
+ /**
54
+ * The scope an operator's assertion must name for each read. A closed union: a route
55
+ * here refuses a credential that does not name what it is about to do, exactly as a
56
+ * contract-surface route does (`403 assertion_scope_refused`).
57
+ */
58
+ export type OperatorReadScope = 'list-movements-as-operator' | 'list-purchases-as-operator' | 'read-quickening-ladder-as-operator';
59
+ /** One published operator read: its method, its path and the scope it requires. */
60
+ export interface OperatorReadRoute {
61
+ readonly method: 'GET';
62
+ readonly path: string;
63
+ readonly scope: OperatorReadScope;
64
+ }
65
+ /** The three reads, by name. The paths and scopes are the service's own. */
66
+ export declare const OPERATOR_READ_ROUTES: {
67
+ readonly movements: {
68
+ readonly method: "GET";
69
+ readonly path: "/api/operator/movements";
70
+ readonly scope: "list-movements-as-operator";
71
+ };
72
+ readonly purchases: {
73
+ readonly method: "GET";
74
+ readonly path: "/api/operator/purchases";
75
+ readonly scope: "list-purchases-as-operator";
76
+ };
77
+ readonly quickenings: {
78
+ readonly method: "GET";
79
+ readonly path: "/api/operator/quickenings";
80
+ readonly scope: "read-quickening-ladder-as-operator";
81
+ };
82
+ };
83
+ /**
84
+ * What a movement is, declared by the act before the draw (CAY-0075). Closed: the
85
+ * movement list's `kind` filter refuses anything outside it (`400 invalid_kind`), and
86
+ * every row's `kind` is one of these.
87
+ */
88
+ export type MovementKind = 'issuance' | 'purchase' | 'grant' | 'charge' | 'payout' | 'transfer' | 'burn' | 'forfeit' | 'commercial_payment' | 'quoted_sale' | 'buy_back' | 'quoted_sale_compensation';
89
+ /** Every {@link MovementKind}, in the service's order — for a filter a person picks from. */
90
+ export declare const MOVEMENT_KINDS: readonly MovementKind[];
91
+ /**
92
+ * One movement as the operator list shows it. A movement is final and append-only
93
+ * (CAY-0023), so there is no status and no failure reason: a movement that did not
94
+ * happen is not a movement.
95
+ *
96
+ * `fromWalletId` is null when the cents came from unissued (an issuance) and
97
+ * `toWalletId` is null when they went back to it (a burn, a forfeiture). Both are
98
+ * wallet ids — the operator-facing handle — and never an identity.
99
+ */
100
+ export interface OperatorMovementRow {
101
+ /** The row's own opaque handle: a stable list key, not an identity. */
102
+ readonly movementId: string;
103
+ /** When the movement happened, as an ISO-8601 UTC instant. */
104
+ readonly occurredAt: string;
105
+ readonly kind: MovementKind;
106
+ readonly fromWalletId: string | null;
107
+ readonly toWalletId: string | null;
108
+ readonly cents: Cents;
109
+ /**
110
+ * The contract's `Restriction`, written out: `restriction.ts` is not on the schema's
111
+ * surface (its capability policy is a mapped type the generator refuses), so a
112
+ * reference would dangle. `operator.test.ts` pins the two equal.
113
+ */
114
+ readonly restriction: 'restricted' | 'unrestricted';
115
+ }
116
+ /**
117
+ * One page of movements, newest first, and the walk's frozen snapshot.
118
+ *
119
+ * `nextCursor` resumes after this page and is null at the end. `anchor` is the
120
+ * snapshot's upper bound: computed on a request that carries none, and sent back
121
+ * thereafter, so `total` and `pageCount` hold still while movements arrive. `page` is
122
+ * the page actually served. An empty walk is `anchor: null`, `total: 0`,
123
+ * `pageCount: 0`, `page: 1`. Both cursors are opaque strings; a consumer passes them
124
+ * back and never reads them. The counts are counts of rows — nothing here but the
125
+ * rows' `cents` is money.
126
+ */
127
+ export interface OperatorMovementsPage {
128
+ readonly movements: readonly OperatorMovementRow[];
129
+ readonly nextCursor: string | null;
130
+ readonly anchor: string | null;
131
+ readonly total: number;
132
+ readonly pageCount: number;
133
+ readonly page: number;
134
+ }
135
+ /**
136
+ * One purchase as the operator list shows it: the buyer's wallet id, the cents, when
137
+ * it began, its status, and — exactly when it failed — the closed-union reason. No
138
+ * identity, no gateway handle, no idempotency key.
139
+ */
140
+ export interface OperatorPurchaseRow {
141
+ /** The row's own opaque handle: a stable list key, not an identity. */
142
+ readonly purchaseId: string;
143
+ /** When the purchase began, as an ISO-8601 UTC instant. */
144
+ readonly createdAt: string;
145
+ readonly walletId: string;
146
+ readonly cents: Cents;
147
+ readonly status: PurchaseStatus;
148
+ readonly failureReason: PurchaseFailureReason | null;
149
+ }
150
+ /** One page of purchases. The envelope is the movement list's, for the same reasons. */
151
+ export interface OperatorPurchasesPage {
152
+ readonly purchases: readonly OperatorPurchaseRow[];
153
+ readonly nextCursor: string | null;
154
+ readonly anchor: string | null;
155
+ readonly total: number;
156
+ readonly pageCount: number;
157
+ readonly page: number;
158
+ }
159
+ /**
160
+ * The query a list accepts, as query-string parameters. Every one is optional, and a
161
+ * filter is refused rather than coerced: a value the service does not accept is a
162
+ * `400` naming the parameter, never a quietly broader list.
163
+ *
164
+ * - `after` — the `nextCursor` of the page before, to resume after it.
165
+ * - `anchor` — the `anchor` the first page answered, to stay inside its snapshot.
166
+ * - `limit` — rows per page. Out of range it is clamped, not refused: above the
167
+ * service's cap is the cap, below one is one, and a value that is not a number
168
+ * is the cap.
169
+ * - `page` — which page of the snapshot to serve, clamped the same way; absent or
170
+ * not a number is the first.
171
+ * - `walletId` — one wallet id. Bounded printable ASCII with no spaces; longer or
172
+ * otherwise malformed is `400 invalid_wallet_id`. A wallet that does not exist is
173
+ * an empty page, not a refusal.
174
+ * - `from`, `to` — the half-open range `[from, to)`: `from` is included, `to` is
175
+ * not. Each is a UTC calendar date (`YYYY-MM-DD`, meaning its midnight) or a
176
+ * `Z`-terminated instant (`YYYY-MM-DDTHH:MM:SS` with optional milliseconds). A
177
+ * zone offset or an impossible date is `400 invalid_from` / `invalid_to`.
178
+ *
179
+ * A parameter given twice is `400 repeated_<name>`.
180
+ */
181
+ export interface OperatorMovementsQuery {
182
+ readonly after?: string;
183
+ readonly anchor?: string;
184
+ readonly limit?: number;
185
+ readonly page?: number;
186
+ readonly walletId?: string;
187
+ readonly from?: string;
188
+ readonly to?: string;
189
+ /** One kind. A movement has no status, and `status` here is `400 status_not_filterable_on_movements`. */
190
+ readonly kind?: MovementKind;
191
+ }
192
+ /** The purchase list's query: the movement list's, with a status and a failure reason for `kind`. */
193
+ export interface OperatorPurchasesQuery {
194
+ readonly after?: string;
195
+ readonly anchor?: string;
196
+ readonly limit?: number;
197
+ readonly page?: number;
198
+ readonly walletId?: string;
199
+ readonly from?: string;
200
+ readonly to?: string;
201
+ readonly status?: PurchaseStatus;
202
+ readonly failureReason?: PurchaseFailureReason;
203
+ }
204
+ /** One band of the ladder. Three integers; no formatted string. */
205
+ export interface QuickeningLadderBand {
206
+ readonly band: number;
207
+ /** The active-citizen count this band begins at. */
208
+ readonly fromActiveCitizens: number;
209
+ /** What ₡1 is worth in this band, in whole pence. */
210
+ readonly publishedValuePence: number;
211
+ }
212
+ /** Where the deployment sits on the ladder, from its newest policy row. */
213
+ export interface LiveQuickeningBand {
214
+ readonly band: number;
215
+ readonly publishedValuePence: number;
216
+ }
217
+ /**
218
+ * The ladder, the live band, and the active-citizen count.
219
+ *
220
+ * `live` is null when no policy row exists. A live band the ladder does not contain is
221
+ * REPORTED as it stands, never repaired (CAY-0028). `activeCitizens` is displayed
222
+ * only: the live band is read from the policy row, never derived from the count.
223
+ */
224
+ export interface QuickeningLadder {
225
+ readonly bands: readonly QuickeningLadderBand[];
226
+ readonly live: LiveQuickeningBand | null;
227
+ readonly activeCitizens: number;
228
+ }
229
+ /**
230
+ * `401` — no credential, or one the verifier refused. Every member is also a
231
+ * {@link import('./errors.js').CaysoApiErrorCode}: the gate is the one every route
232
+ * shares.
233
+ */
234
+ export type OperatorAuthenticationRefusal = 'unauthenticated' | 'assertion_invalid' | 'assertion_expired' | 'assertion_issuer_refused' | 'assertion_key_refused' | 'assertion_algorithm_refused' | 'assertion_subject_refused' | 'assertion_replayed';
235
+ /**
236
+ * `403` — a verified credential that may not make this read, with a bare `{ error }`.
237
+ *
238
+ * - `assertion_scope_refused` — the credential does not name the route's
239
+ * {@link OperatorReadScope}.
240
+ * - `subject_not_a_natural_person` — the credential does not say it belongs to one
241
+ * human being (CAY-0069).
242
+ * - `not_an_operator` — money-grade and a person, but not on this deployment's
243
+ * operator allowlist, which is empty until it is told otherwise.
244
+ */
245
+ export type OperatorAccessRefusal = 'assertion_scope_refused' | 'subject_not_a_natural_person' | 'not_an_operator';
246
+ /**
247
+ * `403` — the credential's verification method is not money-grade (the development
248
+ * bypass, or unverified). The same envelope a money route answers, so a listed
249
+ * operator learns its METHOD is the problem, not its listing.
250
+ */
251
+ export interface OperatorVerificationRefused {
252
+ readonly outcome: 'refused';
253
+ readonly error: 'verification_refused';
254
+ }
255
+ /** `429` — too many credentials presented too fast. */
256
+ export type OperatorRateLimited = 'request_rate_limited';
257
+ /**
258
+ * `503` — the deployment cannot answer any operator read: no verifier, no issuer
259
+ * registry, or the read audit cannot be written. A read that cannot be recorded does
260
+ * not happen (CAY-0027).
261
+ */
262
+ export type OperatorReadUnavailable = 'verifier_not_configured' | 'issuer_registry_not_configured' | 'operator_read_audit_unavailable';
263
+ /** `500` — the service failed, and the reason is not the caller's. */
264
+ export type OperatorReadFailed = 'internal_error';
265
+ /** `400` — the movement list's query was refused. Named per parameter. */
266
+ export type OperatorMovementsQueryRefusal = 'invalid_cursor' | 'invalid_anchor' | 'invalid_wallet_id' | 'invalid_from' | 'invalid_to' | 'invalid_kind' | 'status_not_filterable_on_movements' | 'repeated_walletId' | 'repeated_from' | 'repeated_to' | 'repeated_kind';
267
+ /** `400` — the purchase list's query was refused. Named per parameter. */
268
+ export type OperatorPurchasesQueryRefusal = 'invalid_cursor' | 'invalid_anchor' | 'invalid_wallet_id' | 'invalid_from' | 'invalid_to' | 'invalid_status' | 'invalid_failure_reason' | 'repeated_walletId' | 'repeated_from' | 'repeated_to' | 'repeated_status' | 'repeated_failureReason';
269
+ /** `503` — this deployment has no movement reader wired. */
270
+ export type OperatorMovementsUnavailable = 'operator_movements_reader_not_configured';
271
+ /** `503` — this deployment has no purchase reader wired. */
272
+ export type OperatorPurchasesUnavailable = 'operator_purchases_reader_not_configured';
273
+ /**
274
+ * `503` — the ladder cannot be read: no reader wired, or a reader and no ladder
275
+ * seeded. Kept apart so an operator can tell a wiring fault from an empty table.
276
+ */
277
+ export type QuickeningLadderUnavailable = 'quickening_ladder_reader_not_configured' | 'quickening_ladder_not_configured';
278
+ /** Every `{ error }` code the movement list answers. */
279
+ export type OperatorMovementsErrorCode = OperatorMovementsQueryRefusal | OperatorAuthenticationRefusal | OperatorAccessRefusal | OperatorRateLimited | OperatorReadUnavailable | OperatorMovementsUnavailable | OperatorReadFailed;
280
+ /** Every `{ error }` code the purchase list answers. */
281
+ export type OperatorPurchasesErrorCode = OperatorPurchasesQueryRefusal | OperatorAuthenticationRefusal | OperatorAccessRefusal | OperatorRateLimited | OperatorReadUnavailable | OperatorPurchasesUnavailable | OperatorReadFailed;
282
+ /** Every `{ error }` code the ladder answers. It takes no query, so nothing is a `400`. */
283
+ export type QuickeningLadderErrorCode = OperatorAuthenticationRefusal | OperatorAccessRefusal | OperatorRateLimited | OperatorReadUnavailable | QuickeningLadderUnavailable | OperatorReadFailed;
284
+ export interface OperatorMovementsError {
285
+ readonly error: OperatorMovementsErrorCode;
286
+ }
287
+ export interface OperatorPurchasesError {
288
+ readonly error: OperatorPurchasesErrorCode;
289
+ }
290
+ export interface QuickeningLadderError {
291
+ readonly error: QuickeningLadderErrorCode;
292
+ }
293
+ /** Everything `GET /api/operator/movements` answers: `200`, or one refusal body. */
294
+ export type OperatorMovementsResponse = OperatorMovementsPage | OperatorVerificationRefused | OperatorMovementsError;
295
+ /** Everything `GET /api/operator/purchases` answers: `200`, or one refusal body. */
296
+ export type OperatorPurchasesResponse = OperatorPurchasesPage | OperatorVerificationRefused | OperatorPurchasesError;
297
+ /** Everything `GET /api/operator/quickenings` answers: `200`, or one refusal body. */
298
+ export type QuickeningLadderResponse = QuickeningLadder | OperatorVerificationRefused | QuickeningLadderError;
@@ -0,0 +1,48 @@
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 three reads, by name. The paths and scopes are the service's own. */
17
+ export const OPERATOR_READ_ROUTES = {
18
+ movements: {
19
+ method: 'GET',
20
+ path: '/api/operator/movements',
21
+ scope: 'list-movements-as-operator',
22
+ },
23
+ purchases: {
24
+ method: 'GET',
25
+ path: '/api/operator/purchases',
26
+ scope: 'list-purchases-as-operator',
27
+ },
28
+ quickenings: {
29
+ method: 'GET',
30
+ path: '/api/operator/quickenings',
31
+ scope: 'read-quickening-ladder-as-operator',
32
+ },
33
+ };
34
+ /** Every {@link MovementKind}, in the service's order — for a filter a person picks from. */
35
+ export const MOVEMENT_KINDS = [
36
+ 'issuance',
37
+ 'purchase',
38
+ 'grant',
39
+ 'charge',
40
+ 'payout',
41
+ 'transfer',
42
+ 'burn',
43
+ 'forfeit',
44
+ 'commercial_payment',
45
+ 'quoted_sale',
46
+ 'buy_back',
47
+ 'quoted_sale_compensation',
48
+ ];
package/dist/routes.d.ts CHANGED
@@ -94,6 +94,20 @@
94
94
  * `requestBuyBack` asks the Treasury to buy back (CAY-0080 §2.2). It is a fourth path
95
95
  * for the same reason: selling to the Treasury is not a quote (Open decision G), and a
96
96
  * credential scoped to place one must not thereby cash out. It names no wallet either.
97
+ *
98
+ * ## Why `standingAuthorisation` is here, and the Cloud's settlement is not
99
+ *
100
+ * `standingAuthorisation` is an Instance presenting its owner's standing
101
+ * authorisation under the owner's assertion (`present-standing-authorisation`,
102
+ * CMTY-0018 §1). A person is behind it, so it is classified by a person's
103
+ * assurance like every other entry. It names no wallet: the wallet is the verified
104
+ * holder's own. It is published before it is served.
105
+ *
106
+ * The Contribution Store's settlement assertion is presented by no person. Its path
107
+ * is {@link CLOUD_SETTLEMENT_ROUTE}, outside this table, because every entry here is
108
+ * mapped in `OPERATION_FOR_ROUTE` to the assurance a person needs, and `null` there
109
+ * means "carries no identity", which is false of an assertion a registered issuer
110
+ * signed.
97
111
  */
98
112
  export declare const ROUTES: {
99
113
  readonly wallet: {
@@ -152,8 +166,30 @@ export declare const ROUTES: {
152
166
  readonly method: "POST";
153
167
  readonly path: "/api/marketplace/orders";
154
168
  };
169
+ readonly standingAuthorisation: {
170
+ readonly method: "POST";
171
+ readonly path: "/api/cloud/standing-authorisations";
172
+ };
155
173
  readonly version: {
156
174
  readonly method: "GET";
157
175
  readonly path: "/api/version";
158
176
  };
159
177
  };
178
+ /**
179
+ * Where the Percayso Cloud's Contribution Store presents one period's settlement
180
+ * assertion (CMTY-0018 §2, `cloud-settlement`).
181
+ *
182
+ * **Authenticated by a registered Store issuer (CAY-0030), not by a person.** The
183
+ * assertion is its own credential: signed by a key whose public half is a
184
+ * registered Cayso issuer under its own `kid`, in CAY-0072's format, and verified
185
+ * against a registry that is empty by default, so a Cayso never told about a Store
186
+ * settles nothing (CAY-0021). No person's assertion travels with it, and it is not
187
+ * in {@link ROUTES}, whose every entry is classified by a person's assurance. The
188
+ * client has no method for it, because no person's software calls it.
189
+ *
190
+ * Published before it is served.
191
+ */
192
+ export declare const CLOUD_SETTLEMENT_ROUTE: {
193
+ readonly method: "POST";
194
+ readonly path: "/api/cloud/settlement-assertions";
195
+ };
package/dist/routes.js CHANGED
@@ -109,6 +109,20 @@
109
109
  * `requestBuyBack` asks the Treasury to buy back (CAY-0080 §2.2). It is a fourth path
110
110
  * for the same reason: selling to the Treasury is not a quote (Open decision G), and a
111
111
  * credential scoped to place one must not thereby cash out. It names no wallet either.
112
+ *
113
+ * ## Why `standingAuthorisation` is here, and the Cloud's settlement is not
114
+ *
115
+ * `standingAuthorisation` is an Instance presenting its owner's standing
116
+ * authorisation under the owner's assertion (`present-standing-authorisation`,
117
+ * CMTY-0018 §1). A person is behind it, so it is classified by a person's
118
+ * assurance like every other entry. It names no wallet: the wallet is the verified
119
+ * holder's own. It is published before it is served.
120
+ *
121
+ * The Contribution Store's settlement assertion is presented by no person. Its path
122
+ * is {@link CLOUD_SETTLEMENT_ROUTE}, outside this table, because every entry here is
123
+ * mapped in `OPERATION_FOR_ROUTE` to the assurance a person needs, and `null` there
124
+ * means "carries no identity", which is false of an assertion a registered issuer
125
+ * signed.
112
126
  */
113
127
  export const ROUTES = {
114
128
  wallet: { method: 'GET', path: '/api/wallet' },
@@ -125,5 +139,24 @@ export const ROUTES = {
125
139
  withdrawQuote: { method: 'POST', path: '/api/quote-withdrawals' },
126
140
  requestBuyBack: { method: 'POST', path: '/api/buy-backs' },
127
141
  marketplaceOrder: { method: 'POST', path: '/api/marketplace/orders' },
142
+ standingAuthorisation: { method: 'POST', path: '/api/cloud/standing-authorisations' },
128
143
  version: { method: 'GET', path: '/api/version' },
129
144
  };
145
+ /**
146
+ * Where the Percayso Cloud's Contribution Store presents one period's settlement
147
+ * assertion (CMTY-0018 §2, `cloud-settlement`).
148
+ *
149
+ * **Authenticated by a registered Store issuer (CAY-0030), not by a person.** The
150
+ * assertion is its own credential: signed by a key whose public half is a
151
+ * registered Cayso issuer under its own `kid`, in CAY-0072's format, and verified
152
+ * against a registry that is empty by default, so a Cayso never told about a Store
153
+ * settles nothing (CAY-0021). No person's assertion travels with it, and it is not
154
+ * in {@link ROUTES}, whose every entry is classified by a person's assurance. The
155
+ * client has no method for it, because no person's software calls it.
156
+ *
157
+ * Published before it is served.
158
+ */
159
+ export const CLOUD_SETTLEMENT_ROUTE = {
160
+ method: 'POST',
161
+ path: '/api/cloud/settlement-assertions',
162
+ };