@percayso-community/cayso-contracts 0.23.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/LICENSE +201 -0
- package/README.md +114 -0
- package/dist/assertion.d.ts +867 -0
- package/dist/assertion.js +63 -0
- package/dist/assurance.d.ts +353 -0
- package/dist/assurance.js +551 -0
- package/dist/citizen-market.d.ts +468 -0
- package/dist/citizen-market.js +16 -0
- package/dist/citizenship.d.ts +215 -0
- package/dist/citizenship.js +26 -0
- package/dist/client.d.ts +288 -0
- package/dist/client.js +370 -0
- package/dist/commercial-payment.d.ts +243 -0
- package/dist/commercial-payment.js +16 -0
- package/dist/contract-schema.generated.d.ts +14 -0
- package/dist/contract-schema.generated.js +3107 -0
- package/dist/errors.d.ts +171 -0
- package/dist/errors.js +28 -0
- package/dist/index.d.ts +621 -0
- package/dist/index.js +624 -0
- package/dist/marketplace-receipt.d.ts +306 -0
- package/dist/marketplace-receipt.js +116 -0
- package/dist/marketplace-settlement.d.ts +298 -0
- package/dist/marketplace-settlement.js +16 -0
- package/dist/money.d.ts +84 -0
- package/dist/money.js +34 -0
- package/dist/organisation.d.ts +60 -0
- package/dist/organisation.js +16 -0
- package/dist/purchase.d.ts +531 -0
- package/dist/purchase.js +107 -0
- package/dist/restriction.d.ts +262 -0
- package/dist/restriction.js +316 -0
- package/dist/routes.d.ts +155 -0
- package/dist/routes.js +128 -0
- package/dist/schema-types.d.ts +101 -0
- package/dist/schema-types.js +16 -0
- package/dist/schema.d.ts +24 -0
- package/dist/schema.js +16 -0
- package/dist/wallet.d.ts +92 -0
- package/dist/wallet.js +59 -0
- package/package.json +41 -0
|
@@ -0,0 +1,63 @@
|
|
|
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 credential's clock and retention parameters -------------------------
|
|
17
|
+
/**
|
|
18
|
+
* The furthest ahead of now, in **seconds**, a verified assertion's `exp` may
|
|
19
|
+
* sit before it is refused as over-long.
|
|
20
|
+
*
|
|
21
|
+
* It is a ceiling, not the lifetime: the lifetime band is 60–120 seconds (see the
|
|
22
|
+
* file docblock) and this sits comfortably above it, so an issuer working inside
|
|
23
|
+
* the band is never near it. It exists because the issuer is ANOTHER TEAM and
|
|
24
|
+
* this is a check on somebody else's output: a verifier that trusts an `exp`
|
|
25
|
+
* because the issuer is friendly forbids nothing, and a correctly-signed
|
|
26
|
+
* credential whose `exp` sits a week out is the long-lived credential this
|
|
27
|
+
* contract exists to refuse (CAY-0008).
|
|
28
|
+
*
|
|
29
|
+
* It lives on the contract rather than inside one service because two things read
|
|
30
|
+
* it — the verifier that refuses an over-long credential, and the replay
|
|
31
|
+
* retention floor derived from it below — and because a consumer is entitled to
|
|
32
|
+
* know the ceiling its credentials are measured against.
|
|
33
|
+
*/
|
|
34
|
+
export const MAX_ASSERTION_LIFETIME_SECONDS = 300;
|
|
35
|
+
/**
|
|
36
|
+
* How far apart, in **seconds**, two honest clocks are assumed to be able to
|
|
37
|
+
* drift.
|
|
38
|
+
*
|
|
39
|
+
* It is applied in ONE DIRECTION ONLY: to refuse a credential whose `iat` sits
|
|
40
|
+
* further into the future than this, which no honest issuer's clock explains. It
|
|
41
|
+
* is NOT added to `exp`. Tolerance that extends a credential's life is tolerance
|
|
42
|
+
* that defeats the short lifetime, so the rule is stated as a direction rather
|
|
43
|
+
* than as a number a reader might apply symmetrically: **skew may refuse; it may
|
|
44
|
+
* never admit.** `exp` at or before now is expired, exactly.
|
|
45
|
+
*/
|
|
46
|
+
export const CLOCK_SKEW_TOLERANCE_SECONDS = 30;
|
|
47
|
+
/**
|
|
48
|
+
* The floor, in **seconds**, on how long a recorded assertion use must be kept so
|
|
49
|
+
* that replay is actually refused (CAY-0030).
|
|
50
|
+
*
|
|
51
|
+
* DERIVED, NEVER WRITTEN DOWN AS A NUMBER. A retention window shorter than the
|
|
52
|
+
* longest life a credential can have plus the clock disagreement around it is a
|
|
53
|
+
* window a replay simply waits out: the record of the first use is discarded
|
|
54
|
+
* while the credential itself is still within `exp`, and the second presentation
|
|
55
|
+
* looks like a first. Deriving the floor from the two constants above means the
|
|
56
|
+
* relationship cannot go stale when either moves, and means there is no second
|
|
57
|
+
* copy of it to disagree with this one.
|
|
58
|
+
*
|
|
59
|
+
* It is a FLOOR, not the window. A deployment may keep uses longer; it may not
|
|
60
|
+
* keep them for less, and an implementation must refuse a shorter configured
|
|
61
|
+
* window **in code** rather than note the requirement in a comment.
|
|
62
|
+
*/
|
|
63
|
+
export const MINIMUM_ASSERTION_USE_RETENTION_SECONDS = MAX_ASSERTION_LIFETIME_SECONDS + CLOCK_SKEW_TOLERANCE_SECONDS;
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `assurance` — what each `VerificationMethod` actually proves, and which methods
|
|
3
|
+
* each operation accepts (CAY-0029).
|
|
4
|
+
*
|
|
5
|
+
* `assertion.ts` declares that a claim carries a method. It does not say what any
|
|
6
|
+
* method *asserts*, and until this file there was no statement of that anywhere:
|
|
7
|
+
* the money gate's own condition was the only operative definition of "good
|
|
8
|
+
* enough to move value", which made the acceptance policy an implementation
|
|
9
|
+
* detail a consumer could not read and could change without anybody being told.
|
|
10
|
+
* This file is that statement, written down as contract.
|
|
11
|
+
*
|
|
12
|
+
* ## The standard is Cayso's own, and it is versioned
|
|
13
|
+
*
|
|
14
|
+
* No external assurance scheme is adopted here. The three methods on this surface
|
|
15
|
+
* are the issuer's, their evidence is described in the issuer's terms, and
|
|
16
|
+
* inventing a mapping onto somebody else's levels would assert a correspondence
|
|
17
|
+
* nobody has checked. So the profile is written here — and {@link
|
|
18
|
+
* ASSURANCE_PROFILE_VERSION} exists so that adopting an external scheme later is a
|
|
19
|
+
* NEW VERSION of this profile rather than a rewrite of it. A claim says which
|
|
20
|
+
* version it was made under; a deployment says which versions it recognises; a
|
|
21
|
+
* claim made under a version this deployment does not recognise is refused rather
|
|
22
|
+
* than read as if it meant what this version means.
|
|
23
|
+
*
|
|
24
|
+
* ## The statements must be TRUTHFUL, and the one that matters is the comparison
|
|
25
|
+
*
|
|
26
|
+
* `'document-and-biometric'` is distinguished from `'document'` by exactly one
|
|
27
|
+
* thing: a live capture **compared against the document's portrait, with a
|
|
28
|
+
* recorded match decision**. Not a captured photograph. Not a liveness check. The
|
|
29
|
+
* comparison.
|
|
30
|
+
*
|
|
31
|
+
* The issuer today checks that a passport is valid and that a photograph contains
|
|
32
|
+
* *a* face, and never compares the two. That evidence supports `'document'` and
|
|
33
|
+
* nothing stronger — which is why the issuer maps it to `'document'` and refuses
|
|
34
|
+
* to mint a purchase assertion at all, rather than assert a biometric match that
|
|
35
|
+
* did not occur. {@link evidenceSupports} makes that refusal MECHANICAL rather
|
|
36
|
+
* than scrupulous: an issuer asks it before minting, and a claim asserting
|
|
37
|
+
* evidence that did not occur is refusable at the point it would be made.
|
|
38
|
+
*
|
|
39
|
+
* ## Acceptance is a CLOSED SET per operation, never a threshold
|
|
40
|
+
*
|
|
41
|
+
* Each operation names the methods it accepts, and the set is authored as a
|
|
42
|
+
* decision for every method ({@link MethodDecisions}) rather than as a rank with a
|
|
43
|
+
* `>=` comparison. The difference is the whole design:
|
|
44
|
+
*
|
|
45
|
+
* - A rank ADMITS A NEW METHOD SILENTLY. Add a stronger method tomorrow and
|
|
46
|
+
* every operation whose bar sits below it widens the moment it is declared,
|
|
47
|
+
* with no review anywhere.
|
|
48
|
+
* - A decision per method CANNOT. {@link MethodDecisions} is a mapped type over
|
|
49
|
+
* {@link VerificationMethod}, so a new member is a COMPILE ERROR at every
|
|
50
|
+
* gated operation until somebody writes `'accepted'` or `'refused'` for it.
|
|
51
|
+
* Widening becomes a deliberate, reviewable edit.
|
|
52
|
+
*
|
|
53
|
+
* `'dev-bypass'` appears in no operation's accepted set and permanently (CAY-0021):
|
|
54
|
+
* it asserts nothing, so there is no operation meaning "identity-verified" that it
|
|
55
|
+
* can clear. That is not this slice's to revisit.
|
|
56
|
+
*
|
|
57
|
+
* ## An operation may have NO assurance bar, and that is not the same as accepting everything
|
|
58
|
+
*
|
|
59
|
+
* Reading one's own wallet requires authentication and no assurance at all: a
|
|
60
|
+
* holder looking at their own balance moves nothing, and the surface deliberately
|
|
61
|
+
* serves a development-bypassed identity its own wallet while refusing it a
|
|
62
|
+
* purchase. Recording that as `'not-required'` is the truthful entry. Recording it
|
|
63
|
+
* instead as "accepts every method" would put `'dev-bypass'` in an accepted set
|
|
64
|
+
* and assert, falsely, that the bypass clears a bar — when the honest statement is
|
|
65
|
+
* that no bar is applied. An operation with no bar cannot be widened by a new
|
|
66
|
+
* method, because it was never narrowed.
|
|
67
|
+
*
|
|
68
|
+
* ## What this file is NOT
|
|
69
|
+
*
|
|
70
|
+
* It is not the trust envelope. Whether a claim can be trusted at all — who
|
|
71
|
+
* issued it, under which key, whether it has been replayed or revoked — is a
|
|
72
|
+
* SEPARATE decision, taken in CAY-0030 and expressed in `assertion.ts`'s header
|
|
73
|
+
* and envelope types. A perfect face match signed by a runtime its owner controls
|
|
74
|
+
* is still not evidence. Nothing here reads an issuer, a key id or a scope, and
|
|
75
|
+
* nothing here should grow one: {@link assessAssurance} answers "how well is this
|
|
76
|
+
* identity known", the envelope answers "may this credential be believed at all",
|
|
77
|
+
* and a gate must satisfy both.
|
|
78
|
+
*
|
|
79
|
+
* It is not a gate either. This is data and pure functions: no route, no state, no
|
|
80
|
+
* environment read, nothing that runs on import (CLAUDE.md: packages have no side
|
|
81
|
+
* effects). `apps/api`'s money gate stays the single place the check HAPPENS; it
|
|
82
|
+
* stops being the place the policy is WRITTEN.
|
|
83
|
+
*
|
|
84
|
+
* It carries no numbers. An assurance profile version is a version identifier, not
|
|
85
|
+
* an amount, rate, tier, schedule or threshold; every economic figure lives in the
|
|
86
|
+
* canon PRD and is read from one place.
|
|
87
|
+
*
|
|
88
|
+
* ## Why the policy is not in the generated contract schema
|
|
89
|
+
*
|
|
90
|
+
* `contract-schema.generated.ts` describes the DATA CROSSING THE BOUNDARY — the
|
|
91
|
+
* wire shapes a consumer decodes. The wire consequence of this file is one field,
|
|
92
|
+
* `AssertionClaims.assuranceProfileVersion`, and that IS described there. The
|
|
93
|
+
* policy itself is a table a consumer imports at compile time, not a shape it
|
|
94
|
+
* decodes off a response, so it is deliberately not in the descriptor.
|
|
95
|
+
*/
|
|
96
|
+
import type { AssertionClaims, ContractOperation, VerificationMethod } from './assertion.js';
|
|
97
|
+
import { ROUTES } from './routes.js';
|
|
98
|
+
/**
|
|
99
|
+
* The version of the assurance profile this deployment speaks — the one an issuer
|
|
100
|
+
* stamps on a claim it mints, as `AssertionClaims.assuranceProfileVersion`.
|
|
101
|
+
*
|
|
102
|
+
* It names the standard as well as the version, because the standard is Cayso's
|
|
103
|
+
* own (see the file docblock) and a bare `1` would not say whose. Adopting an
|
|
104
|
+
* external scheme later, or changing what any method asserts, is a NEW version
|
|
105
|
+
* with a new identifier — never a redefinition of this one. Redefining a version
|
|
106
|
+
* in place is how a claim minted last month silently comes to mean something else.
|
|
107
|
+
*
|
|
108
|
+
* It is deliberately NOT the contract version: the contract version describes the
|
|
109
|
+
* wire surface and moves when a type changes, while this moves when the MEANING of
|
|
110
|
+
* evidence changes. Two clocks, two numbers, for the same reason the contract
|
|
111
|
+
* version is not the schema version (CONTEXT.md, Contract version).
|
|
112
|
+
*/
|
|
113
|
+
export declare const ASSURANCE_PROFILE_VERSION: "cayso-assurance-1";
|
|
114
|
+
/**
|
|
115
|
+
* Every assurance profile version this deployment recognises. A claim carrying
|
|
116
|
+
* anything else is refused ({@link assessAssurance}) rather than read as if it
|
|
117
|
+
* meant what this version means — fail closed, the posture every adapter in this
|
|
118
|
+
* tree takes (CLAUDE.md, Trust and authentication).
|
|
119
|
+
*
|
|
120
|
+
* A future version that is genuinely compatible is added here deliberately. It
|
|
121
|
+
* contains {@link ASSURANCE_PROFILE_VERSION} by construction: a deployment always
|
|
122
|
+
* recognises the profile it speaks.
|
|
123
|
+
*/
|
|
124
|
+
export declare const RECOGNISED_ASSURANCE_PROFILE_VERSIONS: readonly string[];
|
|
125
|
+
/**
|
|
126
|
+
* The evidence behind a verification, as three facts that either happened or did
|
|
127
|
+
* not. Booleans rather than prose because an issuer has to be able to CHECK its
|
|
128
|
+
* own claim against them ({@link evidenceSupports}), and prose cannot be checked.
|
|
129
|
+
*
|
|
130
|
+
* `biometricComparedToDocumentPortrait` is the field that matters. Capturing a
|
|
131
|
+
* biometric and comparing one are different events, and conflating them is exactly
|
|
132
|
+
* the overclaim this file exists to make refusable.
|
|
133
|
+
*/
|
|
134
|
+
export interface VerificationEvidence {
|
|
135
|
+
/** A government-issued identity document was examined and checked for validity. */
|
|
136
|
+
readonly identityDocumentChecked: boolean;
|
|
137
|
+
/** A live biometric was captured from the person presenting. Capture ALONE proves no link to the document. */
|
|
138
|
+
readonly biometricCaptured: boolean;
|
|
139
|
+
/** The captured biometric was compared against the document's portrait AND a match decision was recorded. */
|
|
140
|
+
readonly biometricComparedToDocumentPortrait: boolean;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* What one verification method asserts: the evidence it stands for, and the
|
|
144
|
+
* sentence a human reads. The sentence and the booleans say the same thing twice
|
|
145
|
+
* on purpose — one for a person deciding whether their evidence qualifies, one for
|
|
146
|
+
* code that must decide the same question without reading English.
|
|
147
|
+
*/
|
|
148
|
+
export interface EvidenceStatement {
|
|
149
|
+
readonly method: VerificationMethod;
|
|
150
|
+
/** The evidence this method asserts occurred. Anything `false` here is asserted by this method NOT to have happened. */
|
|
151
|
+
readonly evidence: VerificationEvidence;
|
|
152
|
+
/** The truthful statement, for a human. It must not overclaim, and it must name what was NOT done. */
|
|
153
|
+
readonly asserts: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A statement for EVERY method — a mapped type, so a new member of {@link
|
|
157
|
+
* VerificationMethod} cannot arrive without somebody writing down what it proves.
|
|
158
|
+
* That is the first of the two compile errors a new method causes; the second is
|
|
159
|
+
* at every gated operation's {@link MethodDecisions}.
|
|
160
|
+
*/
|
|
161
|
+
type EvidenceStatements = {
|
|
162
|
+
readonly [M in VerificationMethod]: EvidenceStatement;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* What each method asserts. These statements are the contract: a consumer reads
|
|
166
|
+
* them to decide whether its evidence qualifies, and an issuer is bound by them
|
|
167
|
+
* when it mints.
|
|
168
|
+
*/
|
|
169
|
+
export declare const EVIDENCE_STATEMENTS: EvidenceStatements;
|
|
170
|
+
/**
|
|
171
|
+
* Every verification method, as a value. Derived from {@link EVIDENCE_STATEMENTS}
|
|
172
|
+
* rather than hand-listed: that table is a mapped type over the union, so its keys
|
|
173
|
+
* ARE the union and this list cannot drift from it. A hand-written array beside a
|
|
174
|
+
* union is a second home for the same fact, and the two disagree eventually.
|
|
175
|
+
*/
|
|
176
|
+
export declare const VERIFICATION_METHODS: readonly VerificationMethod[];
|
|
177
|
+
/**
|
|
178
|
+
* Whether `evidence` supports asserting `method` — the issuer's check, and the
|
|
179
|
+
* whole of what makes an overclaiming claim REFUSABLE rather than merely
|
|
180
|
+
* discouraged.
|
|
181
|
+
*
|
|
182
|
+
* True when everything the method asserts actually happened. Evidence may exceed
|
|
183
|
+
* what the method asserts (a compared biometric supports `'document'` perfectly
|
|
184
|
+
* well); it may never fall short of it.
|
|
185
|
+
*
|
|
186
|
+
* The case this exists for: an issuer that checked a document and captured a face
|
|
187
|
+
* WITHOUT comparing them gets `false` for `'document-and-biometric'`. It must then
|
|
188
|
+
* mint `'document'` or mint nothing — it must not assert a match decision that was
|
|
189
|
+
* never recorded.
|
|
190
|
+
*
|
|
191
|
+
* `'dev-bypass'` asserts nothing, so nothing can fall short of it and this is
|
|
192
|
+
* vacuously true for it. That is correct and harmless: a method that claims
|
|
193
|
+
* nothing cannot overclaim, and it is refused at every gated operation anyway.
|
|
194
|
+
*/
|
|
195
|
+
export declare function evidenceSupports(method: VerificationMethod, evidence: VerificationEvidence): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* The strongest method this evidence honestly supports, or `null` when it supports
|
|
198
|
+
* none. An issuer mints THIS, rather than the method it would like to have.
|
|
199
|
+
*
|
|
200
|
+
* `'dev-bypass'` is never returned. It is not a conclusion evidence supports — it
|
|
201
|
+
* is the marker of a verification that examined nothing, set by the bypass itself
|
|
202
|
+
* and never derived from evidence. Evidence that proves nothing yields `null`, and
|
|
203
|
+
* an issuer holding `null` has nothing to assert.
|
|
204
|
+
*/
|
|
205
|
+
export declare function methodForEvidence(evidence: VerificationEvidence): VerificationMethod | null;
|
|
206
|
+
/**
|
|
207
|
+
* The operation vocabulary, re-exported from `assertion.ts` where it is declared.
|
|
208
|
+
*
|
|
209
|
+
* ONE VOCABULARY, NOT TWO. An assertion's `scope` lists the operations a
|
|
210
|
+
* credential was minted to perform (CAY-0030) and this file writes an acceptance
|
|
211
|
+
* policy per operation (CAY-0029); those are the same operations, so the type is
|
|
212
|
+
* declared once — beside the claims that carry it — and consumed here. It is
|
|
213
|
+
* re-exported rather than restated for exactly the reason {@link
|
|
214
|
+
* VERIFICATION_METHODS} is derived from {@link EVIDENCE_STATEMENTS}: a second
|
|
215
|
+
* home for one fact is two facts that disagree eventually. The same direction
|
|
216
|
+
* already holds for `VerificationMethod`, which this file consumes from
|
|
217
|
+
* `assertion.ts` and never redeclares.
|
|
218
|
+
*/
|
|
219
|
+
export type { ContractOperation } from './assertion.js';
|
|
220
|
+
/** What one operation does with one method. There is no third answer and no ordering. */
|
|
221
|
+
export type MethodDecision = 'accepted' | 'refused';
|
|
222
|
+
/**
|
|
223
|
+
* A decision for EVERY method. This mapped type is the mechanism behind the
|
|
224
|
+
* acceptance criterion "adding a stronger method does not silently widen what an
|
|
225
|
+
* existing operation accepts": add a member to {@link VerificationMethod} and
|
|
226
|
+
* every gated operation stops compiling until somebody decides, for that
|
|
227
|
+
* operation, whether the new method is accepted.
|
|
228
|
+
*/
|
|
229
|
+
export type MethodDecisions = {
|
|
230
|
+
readonly [M in VerificationMethod]: MethodDecision;
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* An operation that means "identity-verified": it applies an assurance bar, and
|
|
234
|
+
* the closed set of methods that clear it is authored as {@link decisions}.
|
|
235
|
+
*/
|
|
236
|
+
export interface AssuranceRequired {
|
|
237
|
+
readonly operation: ContractOperation;
|
|
238
|
+
readonly assurance: 'required';
|
|
239
|
+
/** A decision for every method. The accepted SET is read from here, never a rank. */
|
|
240
|
+
readonly decisions: MethodDecisions;
|
|
241
|
+
/** Why this bar, in a sentence a consumer can act on. */
|
|
242
|
+
readonly rationale: string;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* An operation that applies no assurance bar at all. Distinct from one that
|
|
246
|
+
* accepts every method: no bar is APPLIED, rather than every method CLEARING one.
|
|
247
|
+
* A caller still has to be authenticated — that is a different gate and not this
|
|
248
|
+
* profile's business.
|
|
249
|
+
*/
|
|
250
|
+
export interface AssuranceNotRequired {
|
|
251
|
+
readonly operation: ContractOperation;
|
|
252
|
+
readonly assurance: 'not-required';
|
|
253
|
+
readonly rationale: string;
|
|
254
|
+
}
|
|
255
|
+
/** What one operation requires of a verification. Switch on `assurance`. */
|
|
256
|
+
export type OperationAssurance = AssuranceRequired | AssuranceNotRequired;
|
|
257
|
+
/**
|
|
258
|
+
* An entry for EVERY operation — a mapped type, so a new operation cannot be added
|
|
259
|
+
* without being classified, the same discipline the route-policy table applies to
|
|
260
|
+
* routes.
|
|
261
|
+
*/
|
|
262
|
+
type AssurancePolicyTable = {
|
|
263
|
+
readonly [O in ContractOperation]: OperationAssurance;
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* The acceptance policy: which methods each operation accepts. THE statement of
|
|
267
|
+
* record — a gate reads it rather than holding its own condition.
|
|
268
|
+
*
|
|
269
|
+
* `'dev-bypass'` is `'refused'` at every gated operation and appears in no
|
|
270
|
+
* accepted set (CAY-0021).
|
|
271
|
+
*/
|
|
272
|
+
export declare const ASSURANCE_POLICY: AssurancePolicyTable;
|
|
273
|
+
/**
|
|
274
|
+
* Every operation, as a value. Derived from {@link ASSURANCE_POLICY} for the same
|
|
275
|
+
* reason {@link VERIFICATION_METHODS} is derived from the statements: the mapped
|
|
276
|
+
* type makes the table's keys the union, so this cannot drift.
|
|
277
|
+
*/
|
|
278
|
+
export declare const CONTRACT_OPERATIONS: readonly ContractOperation[];
|
|
279
|
+
/**
|
|
280
|
+
* Which operation each route on the contract surface exercises, or `null` for a
|
|
281
|
+
* route that carries no identity at all (the public version handshake — you cannot
|
|
282
|
+
* be assured before you can negotiate the contract).
|
|
283
|
+
*
|
|
284
|
+
* Adding a route to `ROUTES` is a compile error here until it is mapped, so "every
|
|
285
|
+
* operation on this surface is classified" is mechanical rather than asserted.
|
|
286
|
+
* The reverse direction is deliberately not total — an operation may be
|
|
287
|
+
* classified before it has a route, which is how `'provision-citizenship'` was
|
|
288
|
+
* decided here and then served, unchanged, by CAY-0031.
|
|
289
|
+
*
|
|
290
|
+
* The two citizenship routes map to two DIFFERENT operations, which is the whole
|
|
291
|
+
* reason they are two paths: one path carries one scope requirement at CAY-0030's
|
|
292
|
+
* gate, so a read sharing a path with a write would share its scope too.
|
|
293
|
+
*/
|
|
294
|
+
export declare const OPERATION_FOR_ROUTE: {
|
|
295
|
+
readonly [R in keyof typeof ROUTES]: ContractOperation | null;
|
|
296
|
+
};
|
|
297
|
+
/**
|
|
298
|
+
* The closed set of methods an operation accepts, or `null` when it applies no
|
|
299
|
+
* assurance bar. `null` and `[]` are different answers and the caller must tell
|
|
300
|
+
* them apart: `[]` would mean "accepts nothing", which is true of no operation
|
|
301
|
+
* here.
|
|
302
|
+
*
|
|
303
|
+
* Derived from the decisions, never authored beside them — one table, read two
|
|
304
|
+
* ways, so an accepted set cannot disagree with the decision it came from.
|
|
305
|
+
*/
|
|
306
|
+
export declare function acceptedMethods(operation: ContractOperation): readonly VerificationMethod[] | null;
|
|
307
|
+
/**
|
|
308
|
+
* Why a verifier will not accept a claim ON ASSURANCE GROUNDS. A closed union, so
|
|
309
|
+
* a consumer renders a member instead of pattern-matching on our prose — the same
|
|
310
|
+
* discipline the purchase failure reasons follow (CAY-0023). A new reason is a new
|
|
311
|
+
* member and a version bump, never a free-text field.
|
|
312
|
+
*
|
|
313
|
+
* There is deliberately no member naming the development bypass. Which methods an
|
|
314
|
+
* operation accepts is policy that moves; "the method you presented is not
|
|
315
|
+
* accepted here" is the reason, and it stays true whatever the table says.
|
|
316
|
+
*/
|
|
317
|
+
export type AssuranceRefusalReason =
|
|
318
|
+
/** The claim was made under an assurance profile this deployment does not recognise. */
|
|
319
|
+
'assurance_profile_unrecognised'
|
|
320
|
+
/** The issuer does not regard this identity as verified at all. */
|
|
321
|
+
| 'identity_unverified'
|
|
322
|
+
/** Verified, but naming no method — there is no evidence to assess. */
|
|
323
|
+
| 'verification_method_absent'
|
|
324
|
+
/** The method is not in this operation's accepted set. */
|
|
325
|
+
| 'verification_method_not_accepted';
|
|
326
|
+
/**
|
|
327
|
+
* The outcome of assessing a claim against an operation's policy. A discriminated
|
|
328
|
+
* union rather than a boolean and a nullable reason: a refusal always carries a
|
|
329
|
+
* reason, and an acceptance cannot carry one.
|
|
330
|
+
*/
|
|
331
|
+
export type AssuranceAssessment = {
|
|
332
|
+
readonly accepted: true;
|
|
333
|
+
} | {
|
|
334
|
+
readonly accepted: false;
|
|
335
|
+
readonly refusalReason: AssuranceRefusalReason;
|
|
336
|
+
};
|
|
337
|
+
/**
|
|
338
|
+
* May this claim perform this operation, on assurance grounds? The verifier half
|
|
339
|
+
* of the profile, and the function a gate calls instead of writing a condition.
|
|
340
|
+
*
|
|
341
|
+
* It reads exactly three fields — the profile version, the status and the method —
|
|
342
|
+
* and nothing else. Not `mandateFor`: whether a caller may act for a wallet is
|
|
343
|
+
* authority, not assurance, and the Signatory / Authorised-User threshold is a
|
|
344
|
+
* canon figure the gate for that operation reads from configuration. Not the reserved
|
|
345
|
+
* claims. Not the issuer or the key: whether the claim can be TRUSTED is the trust
|
|
346
|
+
* envelope's question, a separate gap, and a caller must answer it separately.
|
|
347
|
+
* This function assumes it has already been answered.
|
|
348
|
+
*
|
|
349
|
+
* The order of the checks is the order of the questions: do we understand this
|
|
350
|
+
* profile at all, does this operation apply a bar, was the identity verified, did
|
|
351
|
+
* it name a method, is that method accepted here.
|
|
352
|
+
*/
|
|
353
|
+
export declare function assessAssurance(operation: ContractOperation, claims: AssertionClaims): AssuranceAssessment;
|