@percayso-community/cayso-contracts 0.24.0 → 0.27.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,12 @@
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';
47
+ import type { CitizenTransferRefusal } from './citizen-transfer.js';
46
48
  import type { CommercialPaymentRefusal } from './commercial-payment.js';
47
49
  import type { MarketplaceReceiptReadRefusal } from './marketplace-receipt.js';
48
50
  import type { MarketplaceOrderRefusal, MarketplaceRefundRefusal } from './marketplace-settlement.js';
@@ -118,6 +120,12 @@ export type CaysoApiErrorCode =
118
120
  * (CAY-0079 §3).
119
121
  */
120
122
  | 'commercial_payment_store_not_configured'
123
+ /**
124
+ * No Citizen transfer store is wired, so the route is closed (CAY-0088 §3). It
125
+ * describes the deployment and not the transfer, so it is not a member of the
126
+ * transfer's refusal union.
127
+ */
128
+ | 'citizen_transfer_store_not_configured'
121
129
  /**
122
130
  * The citizen market is shut on this deployment: no store is wired, or a figure
123
131
  * the book needs is not set in the canon and so not configured here (CAY-0080,
@@ -175,7 +183,7 @@ export type CaysoApiErrorCode =
175
183
  /** There is no such purchase under this caller's wallet. */
176
184
  | 'not_found'
177
185
  /** Something failed on the way and the refusal discloses nothing further. */
178
- | 'internal_error' | PurchaseFailureReason | PurchaseCancelRefusalReason | FounderClaimRefusal | CommercialPaymentRefusal | QuotePlacementRefusal | QuoteWithdrawalRefusal | BuyBackRefusal | MarketplaceReceiptReadRefusal | MarketplaceOrderRefusal | MarketplaceRefundRefusal;
186
+ | 'internal_error' | PurchaseFailureReason | PurchaseCancelRefusalReason | FounderClaimRefusal | CommercialPaymentRefusal | CitizenTransferRefusal | QuotePlacementRefusal | QuoteWithdrawalRefusal | BuyBackRefusal | MarketplaceReceiptReadRefusal | MarketplaceOrderRefusal | MarketplaceRefundRefusal | StandingAuthorisationRefusal | SettlementAssertionRefusal;
179
187
  /**
180
188
  * The body of every refusal on this surface: one code, and nothing beside it.
181
189
  *
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,37 @@
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.26.0` → `0.27.0` publishes and SERVES the Citizen transfer (CAY-0088):
80
+ * `ROUTES.citizenTransfer`, `POST /api/citizen-transfers`, mapped to the new
81
+ * operation `'make-citizen-transfer'`, money-grade in `ASSURANCE_POLICY`; the client
82
+ * method `makeCitizenTransfer`; and `CaysoApiErrorCode` gains
83
+ * {@link CitizenTransferRefusal} by reference and the seam code
84
+ * `citizen_transfer_store_not_configured`. It is BREAKING in the package's sense
85
+ * because three closed tables grew. It is additive on the wire: no route a `0.26.0`
86
+ * consumer calls changed or answers anything new (CAY-0086).
87
+ *
88
+ * `0.25.0` → `0.26.0` publishes the operator read surface on its own entry point,
89
+ * `@percayso-community/cayso-contracts/operator` (CAY-0026 Amendment 4), and describes
90
+ * it in the schema under `operator`: the movement list, the purchase list and the
91
+ * quickening ladder, with their scopes, query inputs, rows, pages and closed refusal
92
+ * bodies. Nothing new is served — the three routes answered these shapes already —
93
+ * and nothing in this barrel changed, so no closed table grew: `ROUTES`,
94
+ * `ContractOperation` and `CaysoApiErrorCode` are as `0.25.0` published them. It is
95
+ * additive in the package's sense and on the wire (CAY-0086).
96
+ *
97
+ * `0.24.0` → `0.25.0` publishes the Percayso Cloud's two seams with Cayso (CMTY-0018
98
+ * §3) and serves neither. `ROUTES` gains `standingAuthorisation`, where an Instance
99
+ * presents its owner's standing authorisation under the owner's assertion, with the
100
+ * client method `presentStandingAuthorisation`; the Contribution Store's settlement
101
+ * path is published as {@link CLOUD_SETTLEMENT_ROUTE}, outside `ROUTES`, and in the
102
+ * schema under `issuerRoutes`. The claim types of both documents and of Cayso's
103
+ * acknowledgement arrive from `cloud-settlement`, carrying no Instance ID (CAY-0059
104
+ * §6) and no figure. It is BREAKING in the package's sense because three closed
105
+ * tables grew: `ROUTES`, `ContractOperation` (with `'present-standing-authorisation'`,
106
+ * money-grade in `ASSURANCE_POLICY`) and `CaysoApiErrorCode`, which gains the two
107
+ * seams' refusal unions by reference. It is additive on the wire: no route a
108
+ * `0.24.0` consumer calls changed or answers anything new (CAY-0086).
109
+ *
74
110
  * `0.23.0` → `0.24.0` SERVES `settle-marketplace-order` for a house-publisher sale
75
111
  * at `ROUTES.marketplaceOrder` (CAY-0082 §2, CAY-0083 §3), with the client method
76
112
  * `settleMarketplaceOrder` and three seam codes: `marketplace_order_keys_not_configured`,
@@ -486,7 +522,7 @@
486
522
  * have needed a breaking bump on their own. Under semver below `1.0.0` the minor
487
523
  * is where a breaking change goes, so the minor moves and the patch does not.
488
524
  */
489
- export declare const CONTRACT_VERSION: "0.24.0";
525
+ export declare const CONTRACT_VERSION: "0.27.0";
490
526
  /** The package's own name, so a consumer can name what it depends on. */
491
527
  export declare const packageName = "@percayso-community/cayso-contracts";
492
528
  /**
@@ -503,6 +539,13 @@ export { WALLET_CAPABILITY } from './wallet.js';
503
539
  */
504
540
  export { PURCHASE_CAPABILITY } from './purchase.js';
505
541
  export { ROUTES } from './routes.js';
542
+ /**
543
+ * Where the Percayso Cloud's Contribution Store presents a settlement assertion
544
+ * (CMTY-0018 §2). A value beside `ROUTES` and never in it: the path is
545
+ * authenticated by a registered Store issuer (CAY-0030), not by a person, so it has
546
+ * no operation, no assurance bar and no client method.
547
+ */
548
+ export { CLOUD_SETTLEMENT_ROUTE } from './routes.js';
506
549
  /**
507
550
  * The purchase lifecycle's runtime half (CAY-0032): which statuses a purchase
508
551
  * never leaves, the predicate over them, and the window an authorisation holds its
@@ -619,9 +662,11 @@ export type { HolderType, Millis, Cents, WalletRecord, Balance, Allowance, Walle
619
662
  export type { SignUpGrantTerms, SignUpGrant, CitizenshipNotProvisioned, CitizenshipProvisioned, CitizenshipFounderClaimed, Citizenship, CitizenshipView, FounderClaimRefusal, } from './citizenship.js';
620
663
  export type { OrganisationView } from './organisation.js';
621
664
  export type { CommercialPaymentAuthority, CommercialPaymentRequest, CommercialPayment, CommercialPaymentMade, CommercialPaymentRefused, CommercialPaymentResponse, CommercialPaymentRefusal, } from './commercial-payment.js';
665
+ export type { CitizenTransferRequest, CitizenTransfer, CitizenTransferMade, CitizenTransferRefused, CitizenTransferResponse, CitizenTransferRefusal, } from './citizen-transfer.js';
622
666
  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
667
  export type { MarketplaceReceiptSignatureAlgorithm, MarketplaceReceiptKeyId, MarketplaceSaleKind, MarketplaceReceiptLeg, MarketplaceSettlementReceiptStatement, HousePublisherChargeReceiptStatement, ThirdPartyRefundReceiptStatement, HousePublisherRefundReceiptStatement, MarketplaceReceiptStatement, MarketplaceReceipt, MarketplaceReceiptReadRequest, MarketplaceReceiptFound, MarketplaceNoMovement, MarketplaceReceiptReadRefusal, MarketplaceReceiptReadRefused, MarketplaceReceiptReadResponse, } from './marketplace-receipt.js';
624
668
  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';
625
670
  export type { PurchaseRequest, PurchaseAuthorised, PurchaseTerminal, PurchaseUnresolved, PurchaseRefused, PurchaseAuthorisationResponse, PurchaseFailureReason, PurchaseStatus, LivePurchaseStatus, TerminalPurchaseStatus, PurchaseCancelRefusalReason, PurchaseCancelled, PurchaseCancelRefused, PurchaseCancelResponse, PurchaseResult, } from './purchase.js';
626
671
  export type { VerificationMethod, VerificationStatus, SubjectPersonhood, AssertionClaims, AssertionHeader, AssertionEnvelope, ContractOperation, InternalOperation, ScopeKey, } from './assertion.js';
627
672
  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,37 @@
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.26.0` → `0.27.0` publishes and SERVES the Citizen transfer (CAY-0088):
96
+ * `ROUTES.citizenTransfer`, `POST /api/citizen-transfers`, mapped to the new
97
+ * operation `'make-citizen-transfer'`, money-grade in `ASSURANCE_POLICY`; the client
98
+ * method `makeCitizenTransfer`; and `CaysoApiErrorCode` gains
99
+ * {@link CitizenTransferRefusal} by reference and the seam code
100
+ * `citizen_transfer_store_not_configured`. It is BREAKING in the package's sense
101
+ * because three closed tables grew. It is additive on the wire: no route a `0.26.0`
102
+ * consumer calls changed or answers anything new (CAY-0086).
103
+ *
104
+ * `0.25.0` → `0.26.0` publishes the operator read surface on its own entry point,
105
+ * `@percayso-community/cayso-contracts/operator` (CAY-0026 Amendment 4), and describes
106
+ * it in the schema under `operator`: the movement list, the purchase list and the
107
+ * quickening ladder, with their scopes, query inputs, rows, pages and closed refusal
108
+ * bodies. Nothing new is served — the three routes answered these shapes already —
109
+ * and nothing in this barrel changed, so no closed table grew: `ROUTES`,
110
+ * `ContractOperation` and `CaysoApiErrorCode` are as `0.25.0` published them. It is
111
+ * additive in the package's sense and on the wire (CAY-0086).
112
+ *
113
+ * `0.24.0` → `0.25.0` publishes the Percayso Cloud's two seams with Cayso (CMTY-0018
114
+ * §3) and serves neither. `ROUTES` gains `standingAuthorisation`, where an Instance
115
+ * presents its owner's standing authorisation under the owner's assertion, with the
116
+ * client method `presentStandingAuthorisation`; the Contribution Store's settlement
117
+ * path is published as {@link CLOUD_SETTLEMENT_ROUTE}, outside `ROUTES`, and in the
118
+ * schema under `issuerRoutes`. The claim types of both documents and of Cayso's
119
+ * acknowledgement arrive from `cloud-settlement`, carrying no Instance ID (CAY-0059
120
+ * §6) and no figure. It is BREAKING in the package's sense because three closed
121
+ * tables grew: `ROUTES`, `ContractOperation` (with `'present-standing-authorisation'`,
122
+ * money-grade in `ASSURANCE_POLICY`) and `CaysoApiErrorCode`, which gains the two
123
+ * seams' refusal unions by reference. It is additive on the wire: no route a
124
+ * `0.24.0` consumer calls changed or answers anything new (CAY-0086).
125
+ *
90
126
  * `0.23.0` → `0.24.0` SERVES `settle-marketplace-order` for a house-publisher sale
91
127
  * at `ROUTES.marketplaceOrder` (CAY-0082 §2, CAY-0083 §3), with the client method
92
128
  * `settleMarketplaceOrder` and three seam codes: `marketplace_order_keys_not_configured`,
@@ -502,7 +538,7 @@
502
538
  * have needed a breaking bump on their own. Under semver below `1.0.0` the minor
503
539
  * is where a breaking change goes, so the minor moves and the patch does not.
504
540
  */
505
- export const CONTRACT_VERSION = '0.24.0';
541
+ export const CONTRACT_VERSION = '0.27.0';
506
542
  /** The package's own name, so a consumer can name what it depends on. */
507
543
  export const packageName = '@percayso-community/cayso-contracts';
508
544
  /**
@@ -519,6 +555,13 @@ export { WALLET_CAPABILITY } from './wallet.js';
519
555
  */
520
556
  export { PURCHASE_CAPABILITY } from './purchase.js';
521
557
  export { ROUTES } from './routes.js';
558
+ /**
559
+ * Where the Percayso Cloud's Contribution Store presents a settlement assertion
560
+ * (CMTY-0018 §2). A value beside `ROUTES` and never in it: the path is
561
+ * authenticated by a registered Store issuer (CAY-0030), not by a person, so it has
562
+ * no operation, no assurance bar and no client method.
563
+ */
564
+ export { CLOUD_SETTLEMENT_ROUTE } from './routes.js';
522
565
  /**
523
566
  * The purchase lifecycle's runtime half (CAY-0032): which statuses a purchase
524
567
  * 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
@@ -76,6 +76,14 @@
76
76
  * (CAY-0079 §2). A path that took a payee's identity would make this route a
77
77
  * directory of identities for anyone holding a mandate.
78
78
  *
79
+ * ## Why `citizenTransfer` names only the payee, and never the sender
80
+ *
81
+ * `POST /api/citizen-transfers` is a Citizen transferring Cayso to another Citizen
82
+ * (CAY-0088). The body carries the payee's wallet id, the cents and the key. The
83
+ * sending wallet is NOT in the request: it is the verified subject's own Citizen
84
+ * Wallet, resolved inside `apps/api`, because a sending wallet the caller named would
85
+ * be the caller's claim about whose cents these are (CAY-0021).
86
+ *
79
87
  * ## Why the citizen market is FOUR PATHS, and none of them names a wallet
80
88
  *
81
89
  * `citizenMarket` reads the book, `placeQuote` places a quote, and `withdrawQuote`
@@ -94,6 +102,20 @@
94
102
  * `requestBuyBack` asks the Treasury to buy back (CAY-0080 §2.2). It is a fourth path
95
103
  * for the same reason: selling to the Treasury is not a quote (Open decision G), and a
96
104
  * credential scoped to place one must not thereby cash out. It names no wallet either.
105
+ *
106
+ * ## Why `standingAuthorisation` is here, and the Cloud's settlement is not
107
+ *
108
+ * `standingAuthorisation` is an Instance presenting its owner's standing
109
+ * authorisation under the owner's assertion (`present-standing-authorisation`,
110
+ * CMTY-0018 §1). A person is behind it, so it is classified by a person's
111
+ * 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.
113
+ *
114
+ * The Contribution Store's settlement assertion is presented by no person. Its path
115
+ * is {@link CLOUD_SETTLEMENT_ROUTE}, outside this table, because every entry here is
116
+ * mapped in `OPERATION_FOR_ROUTE` to the assurance a person needs, and `null` there
117
+ * means "carries no identity", which is false of an assertion a registered issuer
118
+ * signed.
97
119
  */
98
120
  export declare const ROUTES: {
99
121
  readonly wallet: {
@@ -132,6 +154,10 @@ export declare const ROUTES: {
132
154
  readonly method: "POST";
133
155
  readonly path: "/api/commercial-payments";
134
156
  };
157
+ readonly citizenTransfer: {
158
+ readonly method: "POST";
159
+ readonly path: "/api/citizen-transfers";
160
+ };
135
161
  readonly citizenMarket: {
136
162
  readonly method: "GET";
137
163
  readonly path: "/api/citizen-market";
@@ -152,8 +178,30 @@ export declare const ROUTES: {
152
178
  readonly method: "POST";
153
179
  readonly path: "/api/marketplace/orders";
154
180
  };
181
+ readonly standingAuthorisation: {
182
+ readonly method: "POST";
183
+ readonly path: "/api/cloud/standing-authorisations";
184
+ };
155
185
  readonly version: {
156
186
  readonly method: "GET";
157
187
  readonly path: "/api/version";
158
188
  };
159
189
  };
190
+ /**
191
+ * Where the Percayso Cloud's Contribution Store presents one period's settlement
192
+ * assertion (CMTY-0018 §2, `cloud-settlement`).
193
+ *
194
+ * **Authenticated by a registered Store issuer (CAY-0030), not by a person.** The
195
+ * assertion is its own credential: signed by a key whose public half is a
196
+ * registered Cayso issuer under its own `kid`, in CAY-0072's format, and verified
197
+ * against a registry that is empty by default, so a Cayso never told about a Store
198
+ * settles nothing (CAY-0021). No person's assertion travels with it, and it is not
199
+ * in {@link ROUTES}, whose every entry is classified by a person's assurance. The
200
+ * client has no method for it, because no person's software calls it.
201
+ *
202
+ * Published before it is served.
203
+ */
204
+ export declare const CLOUD_SETTLEMENT_ROUTE: {
205
+ readonly method: "POST";
206
+ readonly path: "/api/cloud/settlement-assertions";
207
+ };