@naughtbot/e2ee-payloads 0.9.0 → 0.11.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/src/schema.ts CHANGED
@@ -45,7 +45,7 @@ export interface components {
45
45
  * @example ssh_sign
46
46
  * @enum {string}
47
47
  */
48
- MailboxEnvelopeType: "link_request" | "link_approval" | "link_rejection" | "captcha_request" | "captcha_response" | "ssh_auth" | "ssh_sign" | "gpg_sign" | "gpg_decrypt" | "age_unwrap" | "pkcs11_sign" | "pkcs11_derive" | "enroll" | "browser_approval_request" | "browser_approval_response" | "first_party_request" | "first_party_response" | "signing_request" | "signing_response";
48
+ MailboxEnvelopeType: "link_request" | "link_approval" | "link_rejection" | "captcha_request" | "captcha_response" | "ssh_auth" | "ssh_sign" | "gpg_sign" | "gpg_decrypt" | "age_unwrap" | "pkcs11_sign" | "pkcs11_derive" | "enroll" | "browser_approval_request" | "browser_approval_response" | "first_party_request" | "first_party_response" | "signing_request" | "signing_response" | "key_inventory_request" | "key_inventory_response";
49
49
  /**
50
50
  * ApprovalChallenge
51
51
  * @description Canonical Longfellow / attested-key-zk approval challenge. Producer sends this inside the request payload; the approver binds it into the approval proof returned in the response payload.
@@ -180,6 +180,40 @@ export interface components {
180
180
  * @enum {string}
181
181
  */
182
182
  KeyPurpose: "ssh" | "gpg" | "age" | "pkcs11";
183
+ /**
184
+ * PublicKeyAlgorithm
185
+ * @description Closed set of public-key algorithms whose canonical byte layout is pinned by this contract. `ecdsa_p256` is a NIST P-256 (secp256r1) key, `ed25519` is an Edwards-curve Ed25519 signing key, and `x25519` is a Curve25519 Diffie-Hellman key. This enum is deliberately closed: receivers MUST reject any algorithm not listed here rather than guessing a byte layout.
186
+ * This DIVERGES from `MailboxEnrollResponseApprovedV1.algorithm`, which is an open free-form string (the `enroll` flow predates the closed canonical-transport contract and stays permissive for forward compatibility). Schemas that need a verifiable canonical public key — notably the `key_inventory` surface — MUST use this closed enum so the producer and the approver cannot disagree on how to interpret `public_key_hex`. New algorithms (e.g. `rsa`) are added here only when there is a concrete implementation that needs them.
187
+ * @example ed25519
188
+ * @enum {string}
189
+ */
190
+ PublicKeyAlgorithm: "ecdsa_p256" | "ed25519" | "x25519";
191
+ /**
192
+ * PublicKeyFormat
193
+ * @description Closed set of byte layouts a `public_key_hex` value can carry. `sec1_compressed` is the SEC1 compressed-point encoding for P-256 (33 bytes: a `0x02`/`0x03` parity prefix followed by the 32-byte X coordinate). `raw_32` is a bare 32-byte public key, used for Ed25519 signing keys and X25519 Diffie-Hellman keys.
194
+ * The format MUST be consistent with `PublicKeyAlgorithm`: `ecdsa_p256` pairs with `sec1_compressed`; `ed25519` and `x25519` pair with `raw_32`. Receivers MUST reject any other pairing. A `spki_der` layout is intentionally NOT defined yet — add it only when a future PKCS#11 RSA or generic public key actually needs it.
195
+ * @example raw_32
196
+ * @enum {string}
197
+ */
198
+ PublicKeyFormat: "sec1_compressed" | "raw_32";
199
+ /**
200
+ * Sec1CompressedPublicKeyHex
201
+ * @description Lowercase hex of a SEC1 compressed P-256 public key: 66 hex chars (33 bytes) whose first byte is the `0x02` or `0x03` parity prefix followed by the 32-byte X coordinate. Use this with `PublicKeyAlgorithm.ecdsa_p256` / `PublicKeyFormat.sec1_compressed`. Receivers MUST reject values whose length or prefix does not match.
202
+ * @example 02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
203
+ */
204
+ Sec1CompressedPublicKeyHex: string;
205
+ /**
206
+ * Raw32PublicKeyHex
207
+ * @description Lowercase hex of a bare 32-byte public key: exactly 64 hex chars. Use this with `PublicKeyAlgorithm.ed25519` or `PublicKeyAlgorithm.x25519` and `PublicKeyFormat.raw_32`. Receivers MUST reject values whose length does not match.
208
+ * @example a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
209
+ */
210
+ Raw32PublicKeyHex: string;
211
+ /**
212
+ * CanonicalPublicKeyHex
213
+ * @description Lowercase hex of the canonical public-key bytes. The exact layout is described by the sibling `PublicKeyAlgorithm` / `PublicKeyFormat` fields: a `sec1_compressed` P-256 key is 66 hex chars with a `02`/`03` prefix; a `raw_32` Ed25519 or X25519 key is 64 hex chars. The relaxed `^(02|03)?[0-9a-f]{64}$` pattern accepts both lengths; receivers MUST additionally reject any value whose length and prefix do not match the declared `algorithm` and `public_key_format`. Hex — never OpenAPI `format: byte` — is the canonical transport for key material; `format: byte` is reserved for opaque bytes (signatures, proofs, ciphertexts, wrapped keys, packet blobs).
214
+ * @example a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
215
+ */
216
+ CanonicalPublicKeyHex: string;
183
217
  /**
184
218
  * DisplayField
185
219
  * @description A single label/value row rendered on the approval surface.
@@ -1981,6 +2015,348 @@ export interface components {
1981
2015
  request_id: string;
1982
2016
  status: components["schemas"]["MailboxFirstPartyResponseStatus"];
1983
2017
  };
2018
+ /**
2019
+ * MailboxKeyInventoryRequestPayloadV1
2020
+ * @description Request payload for the `key_inventory_request` envelope type. The paired CLI sends this to the mobile device to ask for the public-key inventory covering one or more `purposes`. The approver returns a `MailboxKeyInventoryResponsePayloadV1`.
2021
+ */
2022
+ MailboxKeyInventoryRequestPayloadV1: {
2023
+ /**
2024
+ * @description Non-empty, unique set of key purposes the requester wants the inventory for. Any subset of `ssh`, `gpg`, `age`, and `pkcs11` is valid. The approver MUST only return keys whose `purpose` is in this set, and MUST commit the exact requested set into `MailboxKeyInventoryApprovalBindingV1.requested_purposes`.
2025
+ * @example [
2026
+ * "ssh",
2027
+ * "gpg"
2028
+ * ]
2029
+ */
2030
+ purposes: components["schemas"]["KeyPurpose"][];
2031
+ approval_challenge?: components["schemas"]["ApprovalChallenge"];
2032
+ display?: components["schemas"]["DisplaySchema"];
2033
+ ui?: components["schemas"]["ApprovalUiV1"];
2034
+ source_info?: components["schemas"]["SourceInfo"];
2035
+ };
2036
+ /**
2037
+ * MailboxKeyInventoryApprovalBindingFormat
2038
+ * @description Canonical byte format of the `MailboxKeyInventoryApprovalBindingV1` carried by a `key_inventory_response`. The `+json` suffix marks the binding as the UTF-8 JSON encoding of `MailboxKeyInventoryApprovalBindingV1` with lexicographically ordered properties and no insignificant whitespace. These bytes are the proof input the `approval_proof` statement commits to (the statement signs `SHA256(approval_binding bytes)`); they are never a signature input.
2039
+ * @example key-inventory-approval-binding/v1+json
2040
+ * @enum {string}
2041
+ */
2042
+ MailboxKeyInventoryApprovalBindingFormat: "key-inventory-approval-binding/v1+json";
2043
+ /**
2044
+ * MailboxKeyInventoryEntryV1
2045
+ * @description One public key in a shared inventory response. The canonical identity of the key is the triple (`algorithm`, `public_key_format`, `public_key_hex`); every protocol-specific field below is derived export/display metadata, never the identity of the key.
2046
+ * This entry DIVERGES from `MailboxEnrollResponseApprovedV1`: that schema carries `algorithm` as a free-form open string and accepts both 64- and 66-hex public keys under a single relaxed pattern. This entry instead pins `algorithm` and `public_key_format` to the closed `PublicKeyAlgorithm` / `PublicKeyFormat` enums in `common.yaml` so the CLI and mobile cannot disagree on how to interpret `public_key_hex`. Receivers MUST reject an entry whose `public_key_hex` length/prefix is inconsistent with `algorithm` + `public_key_format` (a `sec1_compressed` `ecdsa_p256` key is 66 hex chars with a `02`/`03` prefix; a `raw_32` `ed25519`/`x25519` key is 64 hex chars).
2047
+ * Canonical key material is always lowercase hex. OpenAPI `format: byte` is used only for opaque byte blobs (GPG signature/armor packet bytes), never for key material.
2048
+ */
2049
+ MailboxKeyInventoryEntryV1: {
2050
+ purpose: components["schemas"]["KeyPurpose"];
2051
+ /**
2052
+ * @description Stable inventory identifier for this key. UUID for GPG keys; algorithm- or provider-defined for other purposes. The CLI uses this to refer to the key in later signing/decryption requests.
2053
+ * @example 550e8400-e29b-41d4-a716-446655440000
2054
+ */
2055
+ id: string;
2056
+ /** @description Device-side key handle (e.g. iOS Secure Enclave handle) the CLI passes back as `device_key_id` on subsequent `ssh_*`, `gpg_*`, `age_unwrap`, or `pkcs11_*` requests. */
2057
+ device_key_id: string;
2058
+ /**
2059
+ * @description Human-readable label for the key shown to the user.
2060
+ * @example Work Laptop SSH Key
2061
+ */
2062
+ label?: string;
2063
+ algorithm: components["schemas"]["PublicKeyAlgorithm"];
2064
+ public_key_format: components["schemas"]["PublicKeyFormat"];
2065
+ /**
2066
+ * @description Lowercase hex of the canonical public-key bytes for this key. The byte layout MUST match `algorithm` + `public_key_format`: `ecdsa_p256` + `sec1_compressed` is 66 hex chars (`02`/`03` prefix); `ed25519` / `x25519` + `raw_32` is 64 hex chars. Receivers MUST reject a value whose length/prefix is inconsistent with the declared `algorithm` and `public_key_format`.
2067
+ * @example 02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
2068
+ */
2069
+ public_key_hex: string;
2070
+ /**
2071
+ * Format: int64
2072
+ * @description Unix timestamp in seconds when the key was created on the device. Required input for GPG V4 fingerprint reproduction; optional for other purposes.
2073
+ * @example 1705320000
2074
+ */
2075
+ key_creation_timestamp?: number;
2076
+ attestation?: components["schemas"]["KeyMetadataAttestation"];
2077
+ ssh?: components["schemas"]["KeyInventorySshMetadataV1"];
2078
+ gpg?: components["schemas"]["KeyInventoryGpgMetadataV1"];
2079
+ age?: components["schemas"]["KeyInventoryAgeMetadataV1"];
2080
+ pkcs11?: components["schemas"]["KeyInventoryPkcs11MetadataV1"];
2081
+ };
2082
+ /**
2083
+ * KeyInventorySshMetadataV1
2084
+ * @description Derived SSH export metadata for an inventory entry whose `purpose` is `ssh`. Every field is reproducible from `public_key_hex`, `algorithm`, the SSH SK key type, and the application string, so the CLI MAY recompute and cross-check it; the approver SHOULD still populate it so the CLI can write the `.pub` file without re-deriving.
2085
+ */
2086
+ KeyInventorySshMetadataV1: {
2087
+ /**
2088
+ * @description OpenSSH security-key type string. `sk-ecdsa-sha2-nistp256@openssh.com` for `ecdsa_p256` keys; `sk-ssh-ed25519@openssh.com` for `ed25519` keys.
2089
+ * @example sk-ecdsa-sha2-nistp256@openssh.com
2090
+ */
2091
+ ssh_key_type?: string;
2092
+ /**
2093
+ * @description SSH application string baked into the public-key blob. Defaults to `ssh:` when the credential was enrolled with the default application.
2094
+ * @default ssh:
2095
+ * @example ssh:
2096
+ */
2097
+ application?: string;
2098
+ /**
2099
+ * @description Single-line OpenSSH authorized-keys / `.pub` representation: `<ssh_key_type> <base64(blob)> <comment>`. The blob is the SSH wire encoding of the public key (uncompressed EC point for `ecdsa_p256`) plus the application string.
2100
+ * @example sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20= work-laptop
2101
+ */
2102
+ authorized_key?: string;
2103
+ /**
2104
+ * @description OpenSSH public-key fingerprint as `SHA256:<base64-no-padding>` of `SHA256(public-key-blob)`. The base64 uses the standard alphabet with trailing `=` padding stripped.
2105
+ * @example SHA256:cccccccccccccccccccccccccccccccccccccccccCC
2106
+ */
2107
+ ssh_fingerprint?: string;
2108
+ /**
2109
+ * @description Per-credential SSH-SK flags byte (UP=0x01, UV=0x04) the credential was enrolled with. The CLI persists this and uses it as the request `flags` input on later `ssh_auth` / `ssh_sign` calls.
2110
+ * @example 1
2111
+ */
2112
+ ssh_sk_flags?: number;
2113
+ };
2114
+ /**
2115
+ * KeyInventoryGpgMetadataV1
2116
+ * @description Derived GPG export metadata for an inventory entry whose `purpose` is `gpg`. The primary-key fingerprint is the OpenPGP V4 fingerprint (`SHA1` over the V4 public-key packet) and depends on `key_creation_timestamp`, so that field MUST be present on GPG entries. `armored_public_key` lets the CLI import the key into system GPG without rebuilding the packet stream.
2117
+ */
2118
+ KeyInventoryGpgMetadataV1: {
2119
+ /**
2120
+ * @description Uppercase hex of the 20-byte OpenPGP V4 primary-key fingerprint (40 hex chars), no spaces.
2121
+ * @example A1D597197F5C1DACB3E3BB7862BF2FC536D562FF
2122
+ */
2123
+ fingerprint_hex?: string;
2124
+ /**
2125
+ * @description Display-formatted primary-key fingerprint: the 40 hex chars in uppercase, grouped into ten 4-character blocks separated by single spaces. Display only — `fingerprint_hex` is canonical.
2126
+ * @example A1D5 9719 7F5C 1DAC B3E3 BB78 62BF 2FC5 36D5 62FF
2127
+ */
2128
+ formatted_fingerprint?: string;
2129
+ /**
2130
+ * @description Uppercase hex of the 8-byte OpenPGP key id (16 hex chars), the low 64 bits of `fingerprint_hex`.
2131
+ * @example 62BF2FC536D562FF
2132
+ */
2133
+ key_id?: string;
2134
+ /**
2135
+ * @description ASCII-armored OpenPGP public key block (`-----BEGIN PGP PUBLIC KEY BLOCK-----` … `-----END …-----`), including the primary key, user id, self-certification signature, and — when present — the encryption subkey and its binding signature.
2136
+ * @example -----BEGIN PGP PUBLIC KEY BLOCK-----
2137
+ *
2138
+ * mDMEY...
2139
+ * -----END PGP PUBLIC KEY BLOCK-----
2140
+ */
2141
+ armored_public_key?: string;
2142
+ /**
2143
+ * Format: byte
2144
+ * @description RFC 4648 standard base64 with `=` padding for the raw OpenPGP self-certification (user-id) signature packet bytes.
2145
+ */
2146
+ user_id_signature?: string;
2147
+ /**
2148
+ * Format: byte
2149
+ * @description RFC 4648 standard base64 with `=` padding for the raw OpenPGP subkey binding signature packet bytes, when an encryption subkey is present.
2150
+ */
2151
+ subkey_signature?: string;
2152
+ /**
2153
+ * @description Lowercase hex of the ECDH encryption subkey public key, SEC1 compressed P-256 (66 hex chars). Present only when the GPG key has an encryption subkey.
2154
+ * @example 03b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3
2155
+ */
2156
+ encryption_public_key_hex?: string;
2157
+ /**
2158
+ * @description Uppercase hex of the 20-byte OpenPGP V4 fingerprint of the ECDH encryption subkey (40 hex chars).
2159
+ * @example B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1
2160
+ */
2161
+ encryption_fingerprint_hex?: string;
2162
+ /**
2163
+ * @description Uppercase hex of the 8-byte OpenPGP key id of the ECDH encryption subkey (16 hex chars).
2164
+ * @example B4C5D6E7F8A9B0C1
2165
+ */
2166
+ encryption_key_id?: string;
2167
+ };
2168
+ /**
2169
+ * KeyInventoryAgeMetadataV1
2170
+ * @description Derived age export metadata for an inventory entry whose `purpose` is `age`. The underlying key is an X25519 key (`algorithm: x25519`, `public_key_format: raw_32`).
2171
+ */
2172
+ KeyInventoryAgeMetadataV1: {
2173
+ /**
2174
+ * @description Canonical age recipient string. It is the Bech32 encoding (per the age spec, lowercase, with the standard age Bech32 checksum) of the 32 raw X25519 public-key bytes — the same bytes as `public_key_hex` — under the human-readable prefix `age1nb`. Producers MUST emit the recipient with this exact prefix and Bech32 checksum; the CLI MUST reject a recipient that does not Bech32-decode to the entry's `public_key_hex` bytes. (The legacy CLI shipped two divergent helpers — a Go Bech32 encoder and a Swift `age1ackagent` + raw-hex concatenation; neither is the contract here. This schema field and the cross-language vectors are authoritative.)
2175
+ * @example age1nb1qqqsyqcyq5rqwzqfpg9scrgwpugpzysnzs23v9ccrydpk8qarc0pz5
2176
+ */
2177
+ age_recipient?: string;
2178
+ /**
2179
+ * @description Short display fingerprint for the age key. Display only — not a cryptographic identifier; the canonical identity is `public_key_hex`.
2180
+ * @example age:YWdlLXJlY2lwaWVu
2181
+ */
2182
+ age_fingerprint?: string;
2183
+ };
2184
+ /**
2185
+ * KeyInventoryPkcs11MetadataV1
2186
+ * @description Derived PKCS#11 public-object metadata for an inventory entry whose `purpose` is `pkcs11`. These are the attributes a PKCS#11 provider needs to expose the public key as a `CKO_PUBLIC_KEY` object deterministically. The canonical identity of the key remains `public_key_hex`; `cka_ec_point_hex` is the DER-wrapped restatement of the same key for the `CKA_EC_POINT` attribute.
2187
+ */
2188
+ KeyInventoryPkcs11MetadataV1: {
2189
+ /**
2190
+ * @description Lowercase hex of the `CKA_ID` attribute bytes used to correlate the public object with its private counterpart.
2191
+ * @example a1b2c3d4
2192
+ */
2193
+ cka_id_hex?: string;
2194
+ /**
2195
+ * @description UTF-8 `CKA_LABEL` attribute string for the public object.
2196
+ * @example NaughtBot PKCS#11 Key
2197
+ */
2198
+ cka_label?: string;
2199
+ /**
2200
+ * @description PKCS#11 `CKA_KEY_TYPE` name for the key. `CKK_EC` for P-256 keys; `CKK_EC_EDWARDS` for Ed25519 keys.
2201
+ * @example CKK_EC
2202
+ */
2203
+ cka_key_type?: string;
2204
+ /**
2205
+ * @description Lowercase hex of the DER-encoded `CKA_EC_PARAMS` attribute (the named-curve OID, e.g. `prime256v1` for P-256).
2206
+ * @example 06082a8648ce3d030107
2207
+ */
2208
+ cka_ec_params_hex?: string;
2209
+ /**
2210
+ * @description Lowercase hex of the DER-encoded `CKA_EC_POINT` attribute (an ASN.1 `OCTET STRING` wrapping the EC point). This is the same public key as `public_key_hex`, re-encoded for the PKCS#11 attribute; receivers MUST treat `public_key_hex` as canonical if the two ever disagree.
2211
+ * @example 0441a1b2c3d4
2212
+ */
2213
+ cka_ec_point_hex?: string;
2214
+ /**
2215
+ * @description Whether the key's PKCS#11 object exposes the `CKA_SIGN` / `CKA_VERIFY` capability (signing keys).
2216
+ * @example true
2217
+ */
2218
+ can_sign?: boolean;
2219
+ /**
2220
+ * @description Whether the key's PKCS#11 object exposes the `CKA_DERIVE` capability (ECDH key-agreement keys).
2221
+ * @example false
2222
+ */
2223
+ can_derive?: boolean;
2224
+ };
2225
+ /**
2226
+ * MailboxKeyInventoryResponseSharedV1
2227
+ * @description `shared` branch of `MailboxKeyInventoryResponsePayloadV1`. The mobile user approved the request; this branch carries the approved key list plus the attested-key-zk proof the CLI uses to verify it.
2228
+ * Integrity is carried entirely by `approval_proof`. The device approval signing key is NEVER transmitted: no signing-key identity and no raw signature appears on the wire. Verification is by the `attested-key-zk` proof alone, which verifies the approval WITHOUT revealing the device signing key — exactly as the `captcha` flow does.
2229
+ * Verification rule the CLI MUST apply:
2230
+ * 1. Recompute `key_list_digest` over `keys` exactly as
2231
+ * `MailboxKeyInventoryApprovalBindingV1.key_list_digest` documents
2232
+ * and confirm it matches `approval_binding.key_list_digest`.
2233
+ * 2. Re-encode `approval_binding` to its canonical JSON bytes (see
2234
+ * `MailboxKeyInventoryApprovalBindingV1`) and confirm those bytes
2235
+ * equal `approval_binding_bytes` after base64-decoding.
2236
+ * 3. Verify `approval_proof` (attested-key-zk) over
2237
+ * `SHA256(approval_binding bytes)`: confirm
2238
+ * `approval_proof.statement.approval_hash_hex` is the lowercase hex
2239
+ * SHA-256 of the canonical `approval_binding` bytes, then verify the
2240
+ * zero-knowledge proof against current issuer keys. Because the
2241
+ * binding commits to the request id/type, requested purposes,
2242
+ * response status, requester source info, response timestamp, and
2243
+ * `key_list_digest`, a valid proof binds this exact request and key
2244
+ * list to an attested NaughtBot install that approved it.
2245
+ * There is no signature-verification step. A response that fails any step MUST be treated as not approved.
2246
+ */
2247
+ MailboxKeyInventoryResponseSharedV1: {
2248
+ /**
2249
+ * @description Outcome discriminator (`shared`). (enum property replaced by openapi-typescript)
2250
+ * @enum {string}
2251
+ */
2252
+ status: "shared";
2253
+ /**
2254
+ * Format: uuid
2255
+ * @description Envelope id of the `key_inventory_request` being answered. MUST equal `approval_binding.request_envelope_id`.
2256
+ * @example 11111111-2222-4333-8444-555555555555
2257
+ */
2258
+ request_envelope_id: string;
2259
+ /** @description Approved public-key inventory. MAY be empty when the device holds no keys for the requested purposes. Every entry's `purpose` MUST be in the request's `purposes` set. */
2260
+ keys: components["schemas"]["MailboxKeyInventoryEntryV1"][];
2261
+ approval_binding: components["schemas"]["MailboxKeyInventoryApprovalBindingV1"];
2262
+ /**
2263
+ * Format: byte
2264
+ * @description RFC 4648 standard base64 with `=` padding for the canonical `MailboxKeyInventoryApprovalBindingV1` UTF-8 JSON bytes. These are the proof input: `approval_proof.statement.approval_hash_hex` is `SHA256` of these bytes (after base64 decoding). They are never a signature input.
2265
+ */
2266
+ approval_binding_bytes: string;
2267
+ approval_binding_format: components["schemas"]["MailboxKeyInventoryApprovalBindingFormat"];
2268
+ approval_proof: components["schemas"]["ApprovalAttestedKeyProof"];
2269
+ };
2270
+ /**
2271
+ * MailboxKeyInventoryResponseRejectedV1
2272
+ * @description `rejected` branch of `MailboxKeyInventoryResponsePayloadV1`. The request was declined by the user or could not be satisfied. Carries the signing error code and an optional human-readable message; it never carries key material or an approval binding.
2273
+ */
2274
+ MailboxKeyInventoryResponseRejectedV1: {
2275
+ /**
2276
+ * @description Outcome discriminator (`rejected`). (enum property replaced by openapi-typescript)
2277
+ * @enum {string}
2278
+ */
2279
+ status: "rejected";
2280
+ /**
2281
+ * Format: uuid
2282
+ * @description Envelope id of the `key_inventory_request` being answered.
2283
+ * @example 11111111-2222-4333-8444-555555555555
2284
+ */
2285
+ request_envelope_id: string;
2286
+ error_code: components["schemas"]["SigningErrorCode"];
2287
+ /**
2288
+ * @description Human-readable error message.
2289
+ * @example User rejected the key inventory request
2290
+ */
2291
+ error_message?: string;
2292
+ };
2293
+ /**
2294
+ * MailboxKeyInventoryResponsePayloadV1
2295
+ * @description Response payload for the `key_inventory_response` envelope type. Discriminated on `status`: `shared` carries the approved key list, approval binding, and attested-key-zk approval proof; `rejected` carries only an error code.
2296
+ * Go generator caveat (see repo `AGENTS.md`): the generated `AsMailboxKeyInventoryResponseSharedV1()` helper is permissive and will not error on a `rejected`-shaped JSON. Routing call-sites MUST inspect the union with `Discriminator()` before treating the result as `shared`.
2297
+ */
2298
+ MailboxKeyInventoryResponsePayloadV1: components["schemas"]["MailboxKeyInventoryResponseSharedV1"] | components["schemas"]["MailboxKeyInventoryResponseRejectedV1"];
2299
+ /**
2300
+ * MailboxKeyInventoryApprovalBindingV1
2301
+ * @description Canonical JSON object whose UTF-8 bytes are the input to the attested-key-zk `approval_proof` for a shared key-inventory response. Producers encode these fields with lexicographically ordered properties and no insignificant whitespace and place the resulting bytes in `MailboxKeyInventoryResponseSharedV1.approval_binding_bytes`.
2302
+ * Integrity mechanism: `MailboxKeyInventoryResponseSharedV1.approval_proof` is an attested-key-zk proof whose statement signs `SHA256(approval_binding bytes)` — exactly as the `captcha` flow signs `SHA256(NaughtBotApprovalBindingV1 bytes)`. The proof verifies that the approval decision (this exact request, answered `shared`, returning this exact key list) was made by an attested NaughtBot install, WITHOUT revealing the device signing key. The device approval signing key is never transmitted and never named here: it is seen only by the core auth service, which uses it to issue the ZK attestation credential. There is no signature over these bytes.
2303
+ * `key_list_digest` commits to the full shared key list — canonical key material AND every protocol export field the CLI persists or displays — so the mobile user cannot approve one set of keys while the CLI stores a different exported representation. It is `sha256:<hex>` where `<hex>` is the lowercase hex SHA-256 of the UTF-8 JSON array `MailboxKeyInventoryResponseSharedV1.keys` encoded in the same canonical form (each `MailboxKeyInventoryEntryV1` object with lexicographically ordered properties, omitted optional fields absent, no insignificant whitespace). Recomputing the digest over the delivered `keys` array MUST reproduce this value.
2304
+ */
2305
+ MailboxKeyInventoryApprovalBindingV1: {
2306
+ /**
2307
+ * @description Canonical approval binding schema version.
2308
+ * @enum {string}
2309
+ */
2310
+ version: "key-inventory-approval-binding/v1";
2311
+ /**
2312
+ * Format: uuid
2313
+ * @description Envelope id of the `key_inventory_request` being answered. Copied from `MailboxEnvelopeV1.id` of the request.
2314
+ * @example 11111111-2222-4333-8444-555555555555
2315
+ */
2316
+ request_envelope_id: string;
2317
+ /**
2318
+ * @description `MailboxEnvelopeV1.issued_at` of the request being answered, preserved as the literal RFC 3339 UTC string.
2319
+ * @example 2026-05-21T17:30:00Z
2320
+ */
2321
+ request_envelope_issued_at: string;
2322
+ /**
2323
+ * @description Envelope type of the request being answered.
2324
+ * @example key_inventory_request
2325
+ * @enum {string}
2326
+ */
2327
+ request_envelope_type: "key_inventory_request";
2328
+ /**
2329
+ * @description Exact `purposes` set copied from the request payload. Pins which purposes the mobile user agreed to share so the CLI can reject a response whose scope drifted from the request.
2330
+ * @example [
2331
+ * "ssh",
2332
+ * "gpg"
2333
+ * ]
2334
+ */
2335
+ requested_purposes: components["schemas"]["KeyPurpose"][];
2336
+ /**
2337
+ * @description Response outcome committed by this binding. Always `shared`: this binding only exists on the shared response branch.
2338
+ * @example shared
2339
+ * @enum {string}
2340
+ */
2341
+ response_status: "shared";
2342
+ /**
2343
+ * @description `sha256:<hex>` digest committing to the full shared key list, including canonical key material and protocol export metadata. See the schema description for the exact canonicalization. An approved response with no keys (the device holds none for the requested purposes) commits to the digest of the empty JSON array `[]`, `sha256:4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945`.
2344
+ * @example sha256:70f1e52bd01429bc2f405b182a3abc72751bda213dba41684a12db5116698c3c
2345
+ */
2346
+ key_list_digest: string;
2347
+ /**
2348
+ * Format: uuid
2349
+ * @description Opaque identifier of the device that approved this request, for display and audit. It is NOT key material — no device signing-key identity travels on the wire. The cryptographic binding of the approval to an attested device is carried solely by `MailboxKeyInventoryResponseSharedV1.approval_proof`.
2350
+ * @example 33333333-4444-4555-8666-777777777777
2351
+ */
2352
+ approving_device_id: string;
2353
+ /**
2354
+ * @description RFC 3339 UTC timestamp when mobile produced the response.
2355
+ * @example 2026-05-21T17:31:00Z
2356
+ */
2357
+ responded_at: string;
2358
+ requester_source_info?: components["schemas"]["SourceInfo"];
2359
+ };
1984
2360
  };
1985
2361
  responses: never;
1986
2362
  parameters: never;