@codespar/sdk 0.16.6 → 0.16.7
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/generated/openapi.d.ts +335 -15
- package/dist/generated/openapi.d.ts.map +1 -1
- package/dist/generated/operations.d.ts +12 -0
- package/dist/generated/operations.d.ts.map +1 -1
- package/dist/generated/operations.js +2 -0
- package/dist/generated/operations.js.map +1 -1
- package/package.json +1 -1
|
@@ -45,6 +45,70 @@ export interface paths {
|
|
|
45
45
|
patch?: never;
|
|
46
46
|
trace?: never;
|
|
47
47
|
};
|
|
48
|
+
"/.well-known/codespar-receipt-keys.json": {
|
|
49
|
+
parameters: {
|
|
50
|
+
query?: never;
|
|
51
|
+
header?: never;
|
|
52
|
+
path?: never;
|
|
53
|
+
cookie?: never;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Receipt verification keys (JWKS)
|
|
57
|
+
* @description The public half of the key that signs agentic receipts, so a party with no CodeSpar credential can check one. An agentic receipt carries two seals: `receipt_sig`, an HMAC under the consumer's own secret, which proves the payment to whoever holds that secret and to nobody else; and `receipt_sig_ed25519`, made with the key published here.
|
|
58
|
+
*
|
|
59
|
+
* To verify: take `receipt_sig_kid` from the receipt, find the key with that `kid` below, build `codespar-receipt:v1:<receipt_id>:<chain>` and check the base64url signature over those UTF-8 bytes with any Ed25519 verifier. `x` is the raw 32-byte public key, base64url (RFC 8037).
|
|
60
|
+
*
|
|
61
|
+
* Keys ROTATE and a retired key stays listed — that is what keeps an old receipt verifiable. A revoked key is removed entirely: its private half is assumed compromised, so signatures it made are worth nothing. An empty `keys` means this deployment publishes none, which is consistent with its receipts carrying a null `receipt_sig_kid`.
|
|
62
|
+
*
|
|
63
|
+
* Every `kid` names the DEPLOYMENT that minted it — `<did>#<namespace>-<n>`, and `key_namespace` repeats the namespace this document serves. A `receipt_sig_kid` that is ABSENT here therefore means the receipt came from another environment (a sandbox receipt checked against production, most often), which is `unknown_key` and NOT a tampered receipt. Before ent#1641 the id was `<did>#<n>` in every environment, so receipts sealed then carry an id that more than one document may claim; they keep verifying against the document of the environment that issued them and nowhere else.
|
|
64
|
+
*/
|
|
65
|
+
get: {
|
|
66
|
+
parameters: {
|
|
67
|
+
query?: never;
|
|
68
|
+
header?: never;
|
|
69
|
+
path?: never;
|
|
70
|
+
cookie?: never;
|
|
71
|
+
};
|
|
72
|
+
requestBody?: never;
|
|
73
|
+
responses: {
|
|
74
|
+
/** @description OK */
|
|
75
|
+
200: {
|
|
76
|
+
headers: {
|
|
77
|
+
[name: string]: unknown;
|
|
78
|
+
};
|
|
79
|
+
content: {
|
|
80
|
+
"application/json": {
|
|
81
|
+
issuer: string;
|
|
82
|
+
/** @description The deployment whose keys this document serves, and the namespace every `kid` below carries. A kid from another namespace is unknown here, not forged. */
|
|
83
|
+
key_namespace: string;
|
|
84
|
+
algorithm: string;
|
|
85
|
+
/** @description The template of the bytes a signature covers, stated so a verifier needs nothing else from us. */
|
|
86
|
+
signing_string: string;
|
|
87
|
+
keys: {
|
|
88
|
+
kid: string;
|
|
89
|
+
kty: string;
|
|
90
|
+
crv: string;
|
|
91
|
+
x: string;
|
|
92
|
+
alg: string;
|
|
93
|
+
use: string;
|
|
94
|
+
/** @description `active` or `retired`. A retired key signs nothing new. */
|
|
95
|
+
status: string;
|
|
96
|
+
created_at: string;
|
|
97
|
+
retired_at: string | null;
|
|
98
|
+
}[];
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
put?: never;
|
|
105
|
+
post?: never;
|
|
106
|
+
delete?: never;
|
|
107
|
+
options?: never;
|
|
108
|
+
head?: never;
|
|
109
|
+
patch?: never;
|
|
110
|
+
trace?: never;
|
|
111
|
+
};
|
|
48
112
|
"/.well-known/oauth-authorization-server": {
|
|
49
113
|
parameters: {
|
|
50
114
|
query?: never;
|
|
@@ -1388,6 +1452,7 @@ export interface paths {
|
|
|
1388
1452
|
content: {
|
|
1389
1453
|
"application/json": {
|
|
1390
1454
|
name: string;
|
|
1455
|
+
/** @description The event type to subscribe to. Matching is EXACT string equality — there is no prefix and no wildcard, so `commerce.payment.succeeded` does not receive `commerce.payment.received`. A name outside the list below is accepted and recorded (`trigger.event_unknown`) rather than refused, so you can subscribe ahead of a release; until something emits it the subscription simply never fires. What this build emits: approval.decided, approval.pending, commerce.account_launch_in.received, commerce.account_launch_out.received, commerce.account_status.changed, commerce.cashout.confirmed, commerce.charge.cancelled, commerce.charge.created, commerce.charge.expired, commerce.charge.expiry_notified, commerce.charge.paid, commerce.charge.payment_notified, commerce.dict_claim.cancelled, commerce.dict_claim.completed, commerce.dict_claim.confirmed, commerce.dict_claim.opened, commerce.dict_claim.waiting, commerce.internal_transfer_in.received, commerce.internal_transfer_out.received, commerce.mandate.granted, commerce.mandate.paused, commerce.mandate.resumed, commerce.mandate.revoked, commerce.onboarding.backgroundcheck_approved, commerce.onboarding.backgroundcheck_pending, commerce.onboarding.backgroundcheck_rejected, commerce.onboarding.documentscopy_approved, commerce.onboarding.documentscopy_pending, commerce.onboarding.documentscopy_processing, commerce.onboarding.documentscopy_rejected, commerce.onboarding.proposal_approved, commerce.onboarding.proposal_processing_documentscopy, commerce.onboarding.proposal_rejected, commerce.payment.failed, commerce.payment.pending, commerce.payment.received, commerce.payment.refunded, commerce.payment.succeeded, commerce.payment.updated, commerce.pix_out.failed, commerce.pix_out.succeeded, commerce.pix_out.unconfirmed, commerce.pix_reversal_in.received, commerce.pix_reversal_out.received, commerce.rinne.observed, commerce.spend.failed, commerce.spend.settled, commerce.ted_in.succeeded, dda.boleto.registered, dda.subscription.activated, dda.subscription.failed, proxy_call.failed, proxy_call.succeeded, session.closed, system.health.degraded, system.health.recovered, tool_call.failed, tool_call.succeeded, trigger.paused_automatically, trigger.test_fire, user.signed_up. */
|
|
1391
1456
|
event: string;
|
|
1392
1457
|
server_id?: string;
|
|
1393
1458
|
/** Format: uri */
|
|
@@ -1505,6 +1570,7 @@ export interface paths {
|
|
|
1505
1570
|
content: {
|
|
1506
1571
|
"application/json": {
|
|
1507
1572
|
name: string;
|
|
1573
|
+
/** @description The event type to subscribe to. Matching is EXACT string equality — there is no prefix and no wildcard, so `commerce.payment.succeeded` does not receive `commerce.payment.received`. A name outside the list below is accepted and recorded (`trigger.event_unknown`) rather than refused, so you can subscribe ahead of a release; until something emits it the subscription simply never fires. What this build emits: approval.decided, approval.pending, commerce.account_launch_in.received, commerce.account_launch_out.received, commerce.account_status.changed, commerce.cashout.confirmed, commerce.charge.cancelled, commerce.charge.created, commerce.charge.expired, commerce.charge.expiry_notified, commerce.charge.paid, commerce.charge.payment_notified, commerce.dict_claim.cancelled, commerce.dict_claim.completed, commerce.dict_claim.confirmed, commerce.dict_claim.opened, commerce.dict_claim.waiting, commerce.internal_transfer_in.received, commerce.internal_transfer_out.received, commerce.mandate.granted, commerce.mandate.paused, commerce.mandate.resumed, commerce.mandate.revoked, commerce.onboarding.backgroundcheck_approved, commerce.onboarding.backgroundcheck_pending, commerce.onboarding.backgroundcheck_rejected, commerce.onboarding.documentscopy_approved, commerce.onboarding.documentscopy_pending, commerce.onboarding.documentscopy_processing, commerce.onboarding.documentscopy_rejected, commerce.onboarding.proposal_approved, commerce.onboarding.proposal_processing_documentscopy, commerce.onboarding.proposal_rejected, commerce.payment.failed, commerce.payment.pending, commerce.payment.received, commerce.payment.refunded, commerce.payment.succeeded, commerce.payment.updated, commerce.pix_out.failed, commerce.pix_out.succeeded, commerce.pix_out.unconfirmed, commerce.pix_reversal_in.received, commerce.pix_reversal_out.received, commerce.rinne.observed, commerce.spend.failed, commerce.spend.settled, commerce.ted_in.succeeded, dda.boleto.registered, dda.subscription.activated, dda.subscription.failed, proxy_call.failed, proxy_call.succeeded, session.closed, system.health.degraded, system.health.recovered, tool_call.failed, tool_call.succeeded, trigger.paused_automatically, trigger.test_fire, user.signed_up. */
|
|
1508
1574
|
event: string;
|
|
1509
1575
|
server_id?: string;
|
|
1510
1576
|
/** Format: uri */
|
|
@@ -4241,6 +4307,165 @@ export interface paths {
|
|
|
4241
4307
|
patch?: never;
|
|
4242
4308
|
trace?: never;
|
|
4243
4309
|
};
|
|
4310
|
+
"/v1/audit-events/verify": {
|
|
4311
|
+
parameters: {
|
|
4312
|
+
query?: never;
|
|
4313
|
+
header?: never;
|
|
4314
|
+
path?: never;
|
|
4315
|
+
cookie?: never;
|
|
4316
|
+
};
|
|
4317
|
+
get?: never;
|
|
4318
|
+
put?: never;
|
|
4319
|
+
/**
|
|
4320
|
+
* Verify the chain over an interval
|
|
4321
|
+
* @description Walks your chain across the interval and answers with a verdict: `verified`, `broken` with the first violated sequence, or `unverified` when a stretch of it could not be checked at all.
|
|
4322
|
+
*
|
|
4323
|
+
* Before this existed a client had to COMPOSE that answer — list the interval, read `watermark_sequence` off `/v1/audit-events/health`, and call the interval verified when every sequence sat at or below it. The deduction is sound and conservative, and it is still the client asserting something this server never said. This operation says it. It runs the same walk as the background verifier: the same link check, the same hash recompute, the same tombstone-witness rule, over the same rows.
|
|
4324
|
+
*
|
|
4325
|
+
* `unverified` is NOT a weaker `verified` and NOT a `broken`. It means part of the interval has no verifiable link — rows are missing, or the first row has no predecessor to measure against — so nothing here certifies that stretch either way. `unverified_segments` names them, capped at 20 entries while `unverified_segment_count` stays the true total.
|
|
4326
|
+
*
|
|
4327
|
+
* THE INTERVAL IS STATED IN TIME AND THE CHAIN IS ORDERED BY SEQUENCE. `from`/`to` select rows by `happened_at`; the walk then covers the contiguous sequence span those rows occupy, reported as `sequence_range`, because a link can only be checked against the row immediately before it. That span can hold more rows than the window does, which is why `events_walked` is reported next to `events_in_interval`.
|
|
4328
|
+
*
|
|
4329
|
+
* BOUNDED BY ROWS, not by days: at most 50,000 rows in the span, or the request is refused with 413 `interval_too_large` and the count, so you can split it. A day count would bound nothing — `happened_at` is written by whoever appended the event, so an hour-wide window can hold an entire chain.
|
|
4330
|
+
*
|
|
4331
|
+
* Unlike `GET /v1/audit-events/health`, this read has NO side effects. It opens no incident, records no unverifiable segment and moves no watermark; poll it as often as you like.
|
|
4332
|
+
*/
|
|
4333
|
+
post: {
|
|
4334
|
+
parameters: {
|
|
4335
|
+
query?: never;
|
|
4336
|
+
header?: never;
|
|
4337
|
+
path?: never;
|
|
4338
|
+
cookie?: never;
|
|
4339
|
+
};
|
|
4340
|
+
requestBody?: {
|
|
4341
|
+
content: {
|
|
4342
|
+
"application/json": {
|
|
4343
|
+
/** @description Start of the interval, inclusive. ISO 8601, read against `happened_at`. */
|
|
4344
|
+
from: string;
|
|
4345
|
+
/** @description End of the interval, inclusive. ISO 8601, read against `happened_at`. */
|
|
4346
|
+
to: string;
|
|
4347
|
+
};
|
|
4348
|
+
};
|
|
4349
|
+
};
|
|
4350
|
+
responses: {
|
|
4351
|
+
/** @description OK */
|
|
4352
|
+
200: {
|
|
4353
|
+
headers: {
|
|
4354
|
+
[name: string]: unknown;
|
|
4355
|
+
};
|
|
4356
|
+
content: {
|
|
4357
|
+
"application/json": {
|
|
4358
|
+
/**
|
|
4359
|
+
* @description `verified` — every row in the span linked to the one before it and hashed to its stored `entry_hash`. `broken` — a row was caught lying, named by `first_violation`. `unverified` — nothing was caught, and part of the span has no verifiable link, so it is certified neither way.
|
|
4360
|
+
* @enum {string}
|
|
4361
|
+
*/
|
|
4362
|
+
status: "verified" | "unverified" | "broken";
|
|
4363
|
+
interval: {
|
|
4364
|
+
/** Format: date-time */
|
|
4365
|
+
from: string;
|
|
4366
|
+
/** Format: date-time */
|
|
4367
|
+
to: string;
|
|
4368
|
+
};
|
|
4369
|
+
/** @description The contiguous sequence span the interval's rows occupy, and what was walked. */
|
|
4370
|
+
sequence_range: {
|
|
4371
|
+
from: number;
|
|
4372
|
+
to: number;
|
|
4373
|
+
};
|
|
4374
|
+
/** @description Rows whose `happened_at` falls inside the interval. */
|
|
4375
|
+
events_in_interval: number;
|
|
4376
|
+
/** @description Rows inside `sequence_range`. At least `events_in_interval`, and larger when rows written with a `happened_at` outside the window sit between them. */
|
|
4377
|
+
events_walked: number;
|
|
4378
|
+
/** @description Rows that passed both checks. Below `events_walked` when the walk stopped at a break. */
|
|
4379
|
+
events_verified: number;
|
|
4380
|
+
/** @description The last sequence that verified. null when the very first row of the span did not, which is also the shape of a break at `sequence_range.from`. */
|
|
4381
|
+
verified_through_sequence: number | null;
|
|
4382
|
+
/** @description The FIRST violated sequence. The walk stops there; later rows are not reported. */
|
|
4383
|
+
first_violation: {
|
|
4384
|
+
sequence_number: number;
|
|
4385
|
+
/**
|
|
4386
|
+
* @description Which check fired. `chain_link_break_detected` — this row's `prev_hash` does not match the previous row's `entry_hash`, which is the only cross-row binding there is. `chain_integrity_break_detected` — the row's own fields no longer hash to its stored `entry_hash`. `tombstone_witness_missing` — an anonymized row with no live witness vouching for it, which would otherwise buy silence for free.
|
|
4387
|
+
* @enum {string}
|
|
4388
|
+
*/
|
|
4389
|
+
check: "chain_link_break_detected" | "chain_integrity_break_detected" | "tombstone_witness_missing";
|
|
4390
|
+
detail: string;
|
|
4391
|
+
} | null;
|
|
4392
|
+
/** @description A sample, capped at 20. `unverified_segment_count` is the total. */
|
|
4393
|
+
unverified_segments: {
|
|
4394
|
+
/** @description Last sequence verified before the hole; 0 when there was no anchor at all. */
|
|
4395
|
+
from_sequence: number;
|
|
4396
|
+
/** @description First sequence observed after the hole. */
|
|
4397
|
+
to_sequence: number;
|
|
4398
|
+
/** @enum {string} */
|
|
4399
|
+
reason: "sequence_gap" | "no_anchor";
|
|
4400
|
+
detail: string;
|
|
4401
|
+
}[];
|
|
4402
|
+
unverified_segment_count: number;
|
|
4403
|
+
/**
|
|
4404
|
+
* Format: date-time
|
|
4405
|
+
* @description When this walk ran. The verdict is about the rows as they stood then.
|
|
4406
|
+
*/
|
|
4407
|
+
checked_at: string;
|
|
4408
|
+
};
|
|
4409
|
+
};
|
|
4410
|
+
};
|
|
4411
|
+
/** @description Bad Request. `invalid_body` when `from` or `to` is missing or not a string, `invalid_iso_8601` when either is not a date this server can parse, `from_after_to` when the interval is inverted. */
|
|
4412
|
+
400: {
|
|
4413
|
+
headers: {
|
|
4414
|
+
[name: string]: unknown;
|
|
4415
|
+
};
|
|
4416
|
+
content: {
|
|
4417
|
+
"application/json": {
|
|
4418
|
+
/** @enum {string} */
|
|
4419
|
+
error: "invalid_body" | "invalid_iso_8601" | "from_after_to";
|
|
4420
|
+
};
|
|
4421
|
+
};
|
|
4422
|
+
};
|
|
4423
|
+
/** @description The sequence span covered by the interval holds more rows than one request will walk. Split the interval; `row_count` and `limit` say by how much. */
|
|
4424
|
+
413: {
|
|
4425
|
+
headers: {
|
|
4426
|
+
[name: string]: unknown;
|
|
4427
|
+
};
|
|
4428
|
+
content: {
|
|
4429
|
+
"application/json": {
|
|
4430
|
+
/** @enum {string} */
|
|
4431
|
+
error: "interval_too_large";
|
|
4432
|
+
remediation: string;
|
|
4433
|
+
row_count: number;
|
|
4434
|
+
limit: number;
|
|
4435
|
+
sequence_range: {
|
|
4436
|
+
from: number;
|
|
4437
|
+
to: number;
|
|
4438
|
+
};
|
|
4439
|
+
};
|
|
4440
|
+
};
|
|
4441
|
+
};
|
|
4442
|
+
/** @description The interval holds no audit events, so there is no verdict to give. Deliberately NOT a `verified` 200: a walk over nothing trivially finds nothing wrong, and a clean verdict for a period the chain says nothing about is the one claim a proof bundle must not carry — a mistyped date and an intact month would read identically. */
|
|
4443
|
+
422: {
|
|
4444
|
+
headers: {
|
|
4445
|
+
[name: string]: unknown;
|
|
4446
|
+
};
|
|
4447
|
+
content: {
|
|
4448
|
+
"application/json": {
|
|
4449
|
+
/** @enum {string} */
|
|
4450
|
+
error: "interval_empty";
|
|
4451
|
+
remediation: string;
|
|
4452
|
+
interval: {
|
|
4453
|
+
/** Format: date-time */
|
|
4454
|
+
from: string;
|
|
4455
|
+
/** Format: date-time */
|
|
4456
|
+
to: string;
|
|
4457
|
+
};
|
|
4458
|
+
};
|
|
4459
|
+
};
|
|
4460
|
+
};
|
|
4461
|
+
};
|
|
4462
|
+
};
|
|
4463
|
+
delete?: never;
|
|
4464
|
+
options?: never;
|
|
4465
|
+
head?: never;
|
|
4466
|
+
patch?: never;
|
|
4467
|
+
trace?: never;
|
|
4468
|
+
};
|
|
4244
4469
|
"/v1/audit-events/incidents": {
|
|
4245
4470
|
parameters: {
|
|
4246
4471
|
query?: never;
|
|
@@ -14413,6 +14638,17 @@ export interface paths {
|
|
|
14413
14638
|
* - `partner` — your server submits. `attestation` is REQUIRED (400 `attestation_required`): the IP and user-agent recorded are your server's, so the only statement about the human is yours. It is signed into the mandate as `consent_attestation` and cannot be edited afterwards without breaking the signature.
|
|
14414
14639
|
*
|
|
14415
14640
|
* `attestation.method` says how the human authorized: `partner_session` (an authenticated session in your product), `in_person`, `verified_code` (a code YOU issued and verified), or `partner_biometric` (YOU ran a biometric check at the moment of the act). `partner_biometric` is not a flavour of `partner_session`: in a dispute a session says someone was logged in and a biometric says a body was present. We capture and verify no biometric ourselves — this records what YOU assert, sealed by the mandate signature so it cannot be edited afterwards; the evidence behind it stays with you. `asserted_at` is the instant you say they authorized, in Unix seconds. `reference` is your own record id, `[A-Za-z0-9_-]{1,120}`, and never personal data — it is joined into the signed string, so the character set is the schema's, not a suggestion.
|
|
14641
|
+
*
|
|
14642
|
+
* `attestation.evidence` (optional) is what you OBSERVED of the act, signed with the rest of the mandate. `channel` is required and decides which other keys may be present, because a value a channel cannot expose was inferred, and an inferred value inside a signed record reads exactly like an observed one:
|
|
14643
|
+
*
|
|
14644
|
+
* - `whatsapp`, `sms`, `email`, `llm_chat` — `contact`, `message_id`, `session_id`, `provider_ts`. These hand you a conversation, not a connection.
|
|
14645
|
+
* - `web_chat` — the above plus `ip`, `user_agent`, `geo`. A browser has no install, so no `device_id_hash`.
|
|
14646
|
+
* - `app` — the above plus `device_id_hash`.
|
|
14647
|
+
* - `other` — everything, because we cannot say what a channel we have not named exposes. An auditor reading `other` knows exactly that.
|
|
14648
|
+
*
|
|
14649
|
+
* A key outside its channel's set, or a key the object does not declare, is a 400 `attestation_evidence_invalid` with `details.key` naming it — never a silent drop. `contact` is the e-mail or E.164 phone the consumer acted from; it is hashed server-side into the signed `contact_hash` and never stored in the clear. `device_id_hash` you hash yourself (64 hex characters). `geo` is `{country, region, city}` and refuses coordinates.
|
|
14650
|
+
*
|
|
14651
|
+
* `method: "verified_code"` additionally REQUIRES `evidence.contact` to carry a contact verification we ran for this consumer in the last 24h (`POST /v1/consumers/{consumerId}/contact-verifications`), or the submit is refused with 409 `contact_verification_required` and the token is left unspent. A rung that is only asserted is not stronger than the one below it.
|
|
14416
14652
|
*/
|
|
14417
14653
|
post: {
|
|
14418
14654
|
parameters: {
|
|
@@ -14436,6 +14672,23 @@ export interface paths {
|
|
|
14436
14672
|
method: "partner_session" | "in_person" | "verified_code" | "partner_biometric";
|
|
14437
14673
|
asserted_at: number;
|
|
14438
14674
|
reference?: string;
|
|
14675
|
+
evidence?: {
|
|
14676
|
+
/** @enum {string} */
|
|
14677
|
+
channel: "whatsapp" | "web_chat" | "app" | "llm_chat" | "sms" | "email" | "other";
|
|
14678
|
+
message_id?: string;
|
|
14679
|
+
session_id?: string;
|
|
14680
|
+
provider_ts?: number;
|
|
14681
|
+
/** Format: ip */
|
|
14682
|
+
ip?: string;
|
|
14683
|
+
user_agent?: string;
|
|
14684
|
+
device_id_hash?: string;
|
|
14685
|
+
geo?: {
|
|
14686
|
+
country: string;
|
|
14687
|
+
region?: string;
|
|
14688
|
+
city?: string;
|
|
14689
|
+
};
|
|
14690
|
+
contact?: string;
|
|
14691
|
+
};
|
|
14439
14692
|
};
|
|
14440
14693
|
};
|
|
14441
14694
|
};
|
|
@@ -14460,7 +14713,7 @@ export interface paths {
|
|
|
14460
14713
|
};
|
|
14461
14714
|
};
|
|
14462
14715
|
};
|
|
14463
|
-
/** @description The body did not match the schema (`invalid_body`, with the Zod issues in `details.issues`),
|
|
14716
|
+
/** @description The body did not match the schema (`invalid_body`, with the Zod issues in `details.issues`), the attestation does not match the token's surface (`attestation_required` on `partner` without one, `attestation_not_accepted` on `hosted` with one), or the evidence carries a key its channel cannot expose or one the object does not declare (`attestation_evidence_invalid`, `details.key`). */
|
|
14464
14717
|
400: {
|
|
14465
14718
|
headers: {
|
|
14466
14719
|
[name: string]: unknown;
|
|
@@ -14469,7 +14722,7 @@ export interface paths {
|
|
|
14469
14722
|
"application/json": {
|
|
14470
14723
|
error: {
|
|
14471
14724
|
/** @enum {string} */
|
|
14472
|
-
code: "invalid_body" | "attestation_required" | "attestation_not_accepted";
|
|
14725
|
+
code: "invalid_body" | "attestation_required" | "attestation_not_accepted" | "attestation_evidence_invalid";
|
|
14473
14726
|
message: string;
|
|
14474
14727
|
details?: {
|
|
14475
14728
|
[key: string]: unknown;
|
|
@@ -14500,7 +14753,7 @@ export interface paths {
|
|
|
14500
14753
|
};
|
|
14501
14754
|
};
|
|
14502
14755
|
};
|
|
14503
|
-
/** @description The token was already submitted, or a concurrent submit won the race
|
|
14756
|
+
/** @description The token was already submitted, or a concurrent submit won the race (nothing was created twice: the loser rolls back whole); or `method: "verified_code"` was claimed without a contact verification for this consumer in the last 24h, in which case nothing was created at all and the token is still pending. */
|
|
14504
14757
|
409: {
|
|
14505
14758
|
headers: {
|
|
14506
14759
|
[name: string]: unknown;
|
|
@@ -14509,7 +14762,7 @@ export interface paths {
|
|
|
14509
14762
|
"application/json": {
|
|
14510
14763
|
error: {
|
|
14511
14764
|
/** @enum {string} */
|
|
14512
|
-
code: "consent_already_resolved" | "consent_race";
|
|
14765
|
+
code: "consent_already_resolved" | "consent_race" | "contact_verification_required";
|
|
14513
14766
|
message: string;
|
|
14514
14767
|
details?: {
|
|
14515
14768
|
[key: string]: unknown;
|
|
@@ -14595,6 +14848,7 @@ export interface paths {
|
|
|
14595
14848
|
attempt_id?: string;
|
|
14596
14849
|
ted?: components["schemas"]["TedDestination"];
|
|
14597
14850
|
quote?: components["schemas"]["SpendQuote"];
|
|
14851
|
+
actor?: components["schemas"]["PaymentActor"];
|
|
14598
14852
|
};
|
|
14599
14853
|
};
|
|
14600
14854
|
};
|
|
@@ -14608,7 +14862,7 @@ export interface paths {
|
|
|
14608
14862
|
"application/json": components["schemas"]["SpendOutcome"];
|
|
14609
14863
|
};
|
|
14610
14864
|
};
|
|
14611
|
-
/** @description The body did not match the schema. */
|
|
14865
|
+
/** @description The body did not match the schema (`invalid_body`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in either case. */
|
|
14612
14866
|
400: {
|
|
14613
14867
|
headers: {
|
|
14614
14868
|
[name: string]: unknown;
|
|
@@ -14617,7 +14871,7 @@ export interface paths {
|
|
|
14617
14871
|
"application/json": {
|
|
14618
14872
|
error: {
|
|
14619
14873
|
/** @enum {string} */
|
|
14620
|
-
code: "invalid_body";
|
|
14874
|
+
code: "invalid_body" | "actor_consumer_mismatch";
|
|
14621
14875
|
message: string;
|
|
14622
14876
|
details?: {
|
|
14623
14877
|
[key: string]: unknown;
|
|
@@ -14820,6 +15074,7 @@ export interface paths {
|
|
|
14820
15074
|
attempt_id?: string;
|
|
14821
15075
|
ted?: components["schemas"]["TedDestination"];
|
|
14822
15076
|
quote?: components["schemas"]["SpendQuote"];
|
|
15077
|
+
actor?: components["schemas"]["PaymentActor"];
|
|
14823
15078
|
};
|
|
14824
15079
|
};
|
|
14825
15080
|
};
|
|
@@ -14833,7 +15088,7 @@ export interface paths {
|
|
|
14833
15088
|
"application/json": components["schemas"]["SpendOutcome"];
|
|
14834
15089
|
};
|
|
14835
15090
|
};
|
|
14836
|
-
/** @description The body did not match the schema. */
|
|
15091
|
+
/** @description The body did not match the schema (`invalid_body`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in either case. */
|
|
14837
15092
|
400: {
|
|
14838
15093
|
headers: {
|
|
14839
15094
|
[name: string]: unknown;
|
|
@@ -14842,7 +15097,7 @@ export interface paths {
|
|
|
14842
15097
|
"application/json": {
|
|
14843
15098
|
error: {
|
|
14844
15099
|
/** @enum {string} */
|
|
14845
|
-
code: "invalid_body";
|
|
15100
|
+
code: "invalid_body" | "actor_consumer_mismatch";
|
|
14846
15101
|
message: string;
|
|
14847
15102
|
details?: {
|
|
14848
15103
|
[key: string]: unknown;
|
|
@@ -14997,6 +15252,7 @@ export interface paths {
|
|
|
14997
15252
|
attempt_id?: string;
|
|
14998
15253
|
ted?: components["schemas"]["TedDestination"];
|
|
14999
15254
|
quote?: components["schemas"]["SpendQuote"];
|
|
15255
|
+
actor?: components["schemas"]["PaymentActor"];
|
|
15000
15256
|
};
|
|
15001
15257
|
};
|
|
15002
15258
|
};
|
|
@@ -15010,7 +15266,7 @@ export interface paths {
|
|
|
15010
15266
|
"text/event-stream": string;
|
|
15011
15267
|
};
|
|
15012
15268
|
};
|
|
15013
|
-
/** @description The body did not match the schema. */
|
|
15269
|
+
/** @description The body did not match the schema (`invalid_body`), or `actor.on_behalf_of` names a consumer other than the one this mandate belongs to (`actor_consumer_mismatch`). Nothing was read, held or sent in either case. */
|
|
15014
15270
|
400: {
|
|
15015
15271
|
headers: {
|
|
15016
15272
|
[name: string]: unknown;
|
|
@@ -15019,7 +15275,7 @@ export interface paths {
|
|
|
15019
15275
|
"application/json": {
|
|
15020
15276
|
error: {
|
|
15021
15277
|
/** @enum {string} */
|
|
15022
|
-
code: "invalid_body";
|
|
15278
|
+
code: "invalid_body" | "actor_consumer_mismatch";
|
|
15023
15279
|
message: string;
|
|
15024
15280
|
details?: {
|
|
15025
15281
|
[key: string]: unknown;
|
|
@@ -17796,6 +18052,18 @@ export interface paths {
|
|
|
17796
18052
|
receipt_id: string;
|
|
17797
18053
|
/** @enum {string} */
|
|
17798
18054
|
state: "paid" | "delivered" | "exception" | "voided";
|
|
18055
|
+
/** @description WHO triggered the spend, as the caller declared it at payment time. Null when they declared none, and null is the honest answer rather than a gap to fill: it is never inferred from `mandate.scope` or from the agent the mandate was signed for. A null here means nobody said, not that an agent did it. */
|
|
18056
|
+
actor: {
|
|
18057
|
+
/** @enum {string} */
|
|
18058
|
+
type: "agent";
|
|
18059
|
+
id: string;
|
|
18060
|
+
on_behalf_of: string;
|
|
18061
|
+
} | {
|
|
18062
|
+
/** @enum {string} */
|
|
18063
|
+
type: "human";
|
|
18064
|
+
id: string;
|
|
18065
|
+
channel?: string;
|
|
18066
|
+
} | null;
|
|
17799
18067
|
mandate: {
|
|
17800
18068
|
id: string;
|
|
17801
18069
|
nonce: string;
|
|
@@ -17849,6 +18117,10 @@ export interface paths {
|
|
|
17849
18117
|
} | null;
|
|
17850
18118
|
chain: string;
|
|
17851
18119
|
receipt_sig: string;
|
|
18120
|
+
/** @description base64url Ed25519 signature over `codespar-receipt:v1:<receipt_id>:<chain>`, made with the platform issuer key. Verifiable by anyone: fetch `/.well-known/codespar-receipt-keys.json` (no credential), take the key whose `kid` is the one below, and check the signature over that string. Null on a receipt sealed before this existed, and on one sealed while the key could not be resolved — `receipt_sig` is the HMAC seal either way and is unaffected. */
|
|
18121
|
+
receipt_sig_ed25519: string | null;
|
|
18122
|
+
/** @description Which published key signed it, `<did:web:...>#<namespace>-<n>`. Keys rotate and a retired key stays published, so an old receipt names its own key rather than leaving a verifier to try each one. The namespace names the DEPLOYMENT that minted the key (ent#1641), so a kid absent from the key document you fetched means the receipt came from another environment — `unknown_key`, not a tampered receipt. */
|
|
18123
|
+
receipt_sig_kid: string | null;
|
|
17852
18124
|
exceptions: {
|
|
17853
18125
|
code: string;
|
|
17854
18126
|
detail: string;
|
|
@@ -17903,6 +18175,18 @@ export interface paths {
|
|
|
17903
18175
|
receipt_id: string;
|
|
17904
18176
|
/** @enum {string} */
|
|
17905
18177
|
state: "paid" | "delivered" | "exception" | "voided";
|
|
18178
|
+
/** @description WHO triggered the spend, as the caller declared it at payment time. Null when they declared none, and null is the honest answer rather than a gap to fill: it is never inferred from `mandate.scope` or from the agent the mandate was signed for. A null here means nobody said, not that an agent did it. */
|
|
18179
|
+
actor: {
|
|
18180
|
+
/** @enum {string} */
|
|
18181
|
+
type: "agent";
|
|
18182
|
+
id: string;
|
|
18183
|
+
on_behalf_of: string;
|
|
18184
|
+
} | {
|
|
18185
|
+
/** @enum {string} */
|
|
18186
|
+
type: "human";
|
|
18187
|
+
id: string;
|
|
18188
|
+
channel?: string;
|
|
18189
|
+
} | null;
|
|
17906
18190
|
mandate: {
|
|
17907
18191
|
id: string;
|
|
17908
18192
|
nonce: string;
|
|
@@ -17956,6 +18240,10 @@ export interface paths {
|
|
|
17956
18240
|
} | null;
|
|
17957
18241
|
chain: string;
|
|
17958
18242
|
receipt_sig: string;
|
|
18243
|
+
/** @description base64url Ed25519 signature over `codespar-receipt:v1:<receipt_id>:<chain>`, made with the platform issuer key. Verifiable by anyone: fetch `/.well-known/codespar-receipt-keys.json` (no credential), take the key whose `kid` is the one below, and check the signature over that string. Null on a receipt sealed before this existed, and on one sealed while the key could not be resolved — `receipt_sig` is the HMAC seal either way and is unaffected. */
|
|
18244
|
+
receipt_sig_ed25519: string | null;
|
|
18245
|
+
/** @description Which published key signed it, `<did:web:...>#<namespace>-<n>`. Keys rotate and a retired key stays published, so an old receipt names its own key rather than leaving a verifier to try each one. The namespace names the DEPLOYMENT that minted the key (ent#1641), so a kid absent from the key document you fetched means the receipt came from another environment — `unknown_key`, not a tampered receipt. */
|
|
18246
|
+
receipt_sig_kid: string | null;
|
|
17959
18247
|
exceptions: {
|
|
17960
18248
|
code: string;
|
|
17961
18249
|
detail: string;
|
|
@@ -19865,6 +20153,18 @@ export interface paths {
|
|
|
19865
20153
|
receipt_id: string;
|
|
19866
20154
|
/** @enum {string} */
|
|
19867
20155
|
state: "paid" | "delivered" | "exception" | "voided";
|
|
20156
|
+
/** @description WHO triggered the spend, as the caller declared it at payment time. Null when they declared none, and null is the honest answer rather than a gap to fill: it is never inferred from `mandate.scope` or from the agent the mandate was signed for. A null here means nobody said, not that an agent did it. */
|
|
20157
|
+
actor: {
|
|
20158
|
+
/** @enum {string} */
|
|
20159
|
+
type: "agent";
|
|
20160
|
+
id: string;
|
|
20161
|
+
on_behalf_of: string;
|
|
20162
|
+
} | {
|
|
20163
|
+
/** @enum {string} */
|
|
20164
|
+
type: "human";
|
|
20165
|
+
id: string;
|
|
20166
|
+
channel?: string;
|
|
20167
|
+
} | null;
|
|
19868
20168
|
mandate: {
|
|
19869
20169
|
id: string;
|
|
19870
20170
|
nonce: string;
|
|
@@ -19918,6 +20218,10 @@ export interface paths {
|
|
|
19918
20218
|
} | null;
|
|
19919
20219
|
chain: string;
|
|
19920
20220
|
receipt_sig: string;
|
|
20221
|
+
/** @description base64url Ed25519 signature over `codespar-receipt:v1:<receipt_id>:<chain>`, made with the platform issuer key. Verifiable by anyone: fetch `/.well-known/codespar-receipt-keys.json` (no credential), take the key whose `kid` is the one below, and check the signature over that string. Null on a receipt sealed before this existed, and on one sealed while the key could not be resolved — `receipt_sig` is the HMAC seal either way and is unaffected. */
|
|
20222
|
+
receipt_sig_ed25519: string | null;
|
|
20223
|
+
/** @description Which published key signed it, `<did:web:...>#<namespace>-<n>`. Keys rotate and a retired key stays published, so an old receipt names its own key rather than leaving a verifier to try each one. The namespace names the DEPLOYMENT that minted the key (ent#1641), so a kid absent from the key document you fetched means the receipt came from another environment — `unknown_key`, not a tampered receipt. */
|
|
20224
|
+
receipt_sig_kid: string | null;
|
|
19921
20225
|
exceptions: {
|
|
19922
20226
|
code: string;
|
|
19923
20227
|
detail: string;
|
|
@@ -24512,7 +24816,7 @@ export interface paths {
|
|
|
24512
24816
|
"application/json": {
|
|
24513
24817
|
/** @description `did:web:` derived from the org and the handle. */
|
|
24514
24818
|
agent_did: string;
|
|
24515
|
-
/** @description `<agent_did>#<n
|
|
24819
|
+
/** @description `<agent_did>#<namespace>-<n>` — the namespace names the deployment that minted the key (ent#1641). */
|
|
24516
24820
|
kid: string;
|
|
24517
24821
|
/** @description Raw 32-byte Ed25519 public key, base64. */
|
|
24518
24822
|
pubkey: string;
|
|
@@ -24725,7 +25029,7 @@ export interface paths {
|
|
|
24725
25029
|
*
|
|
24726
25030
|
* Takes no body. Unlike rotation, this is the verb that stops a key from counting: the mandate spend gate resolves the key an existing mandate was signed with and refuses the spend once that key is revoked, so revoking reaches BACKWARDS into mandates already issued.
|
|
24727
25031
|
*
|
|
24728
|
-
* `{kid}` is a full key id of the form `<did:web:...>#<n>`, and its `#` MUST be percent-encoded as `%23` to survive as one path segment. This revokes ONE key; it does not revoke the agent identity.
|
|
25032
|
+
* `{kid}` is a full key id of the form `<did:web:...>#<namespace>-<n>`, and its `#` MUST be percent-encoded as `%23` to survive as one path segment. This revokes ONE key; it does not revoke the agent identity.
|
|
24729
25033
|
*
|
|
24730
25034
|
* Revoking an already-revoked key is 409 rather than a no-op, so a retry after a timeout is distinguishable from a first call.
|
|
24731
25035
|
*/
|
|
@@ -24737,7 +25041,7 @@ export interface paths {
|
|
|
24737
25041
|
orgId: string;
|
|
24738
25042
|
/** @description The registration handle, not the `did:web`. */
|
|
24739
25043
|
agentId: string;
|
|
24740
|
-
/** @description `<did:web:...>#<n>`, with the `#` percent-encoded as `%23`. */
|
|
25044
|
+
/** @description `<did:web:...>#<namespace>-<n>`, with the `#` percent-encoded as `%23`. */
|
|
24741
25045
|
kid: string;
|
|
24742
25046
|
};
|
|
24743
25047
|
cookie?: never;
|
|
@@ -32801,7 +33105,7 @@ export interface paths {
|
|
|
32801
33105
|
content: {
|
|
32802
33106
|
"application/json": {
|
|
32803
33107
|
agent_did: string;
|
|
32804
|
-
/** @description `<did>#<n
|
|
33108
|
+
/** @description `<did>#<namespace>-<n>`: the namespace names the deployment that minted the key (ent#1641), n is its ordinal. */
|
|
32805
33109
|
kid: string;
|
|
32806
33110
|
/** @description base64. */
|
|
32807
33111
|
pubkey: string;
|
|
@@ -33697,7 +34001,7 @@ export interface paths {
|
|
|
33697
34001
|
*
|
|
33698
34002
|
* It also changes what counterparties can see. The published `did:web` document lists the identity's keys where status is not `revoked`, so a REVOKED key disappears from it while a RETIRED one stays and keeps verifying its own past issuance. Revoking is the verb for a key you believe is compromised; rotating is the verb for hygiene.
|
|
33699
34003
|
*
|
|
33700
|
-
* `{kid}` is a full kid (`<did>#<n>`), and its `#` MUST be percent-encoded as `%23` so the whole kid arrives as one path segment.
|
|
34004
|
+
* `{kid}` is a full kid (`<did>#<namespace>-<n>`), and its `#` MUST be percent-encoded as `%23` so the whole kid arrives as one path segment.
|
|
33701
34005
|
*
|
|
33702
34006
|
* Idempotency is NOT offered: revoking an already-revoked key is 409, not a repeat of the 200.
|
|
33703
34007
|
*/
|
|
@@ -36108,6 +36412,22 @@ export interface components {
|
|
|
36108
36412
|
session_id?: string;
|
|
36109
36413
|
at?: string;
|
|
36110
36414
|
};
|
|
36415
|
+
/** @description WHO triggered this spend, recorded on the receipt and read back from it. Optional, and absence is a real answer: a spend that sends no actor records `null`, and nothing is ever inferred from `agent_id` — that field names the agent the mandate was SIGNED for, which is an authority, not an event. A person acting through WhatsApp under an agent's mandate and the agent acting unattended are the same row without this field. */
|
|
36416
|
+
PaymentActor: {
|
|
36417
|
+
/** @enum {string} */
|
|
36418
|
+
type: "agent";
|
|
36419
|
+
/** @description The agent's own identifier. */
|
|
36420
|
+
id: string;
|
|
36421
|
+
/** @description The consumer the agent is acting for. It must be the consumer this mandate belongs to; any other value is refused with `actor_consumer_mismatch` before anything is read, held or sent. */
|
|
36422
|
+
on_behalf_of: string;
|
|
36423
|
+
} | {
|
|
36424
|
+
/** @enum {string} */
|
|
36425
|
+
type: "human";
|
|
36426
|
+
/** @description The person's identifier — a user id, not a name. */
|
|
36427
|
+
id: string;
|
|
36428
|
+
/** @description Where the person acted from: `whatsapp`, `dashboard`, `cli`. */
|
|
36429
|
+
channel?: string;
|
|
36430
|
+
};
|
|
36111
36431
|
};
|
|
36112
36432
|
responses: never;
|
|
36113
36433
|
parameters: never;
|